Bicep vs Terraform - A fair and balanced comparison

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey this is john gallant today we're going to take a look at bicep the new arm template abstraction dsl from the azure team we're going to take a look at how i applied this to memolizer and we're going to take a look at how it compares to using terraform and arm templates directly the app that we're going to be applying bicep to is called memolizer it's an app that i've been working on to showcase some of the latest and greatest tech coming from microsoft to help you build azure solutions such as the new azure sdks project tie and now bicep at the surface this app is pretty simple it takes in a meme extracts the text from the meme determines the sentiment and then changes the border color based on that sentiment so a green border means it's a positive meme a red border means it's a negative meme and a yellow border means it's a neutral beam under the covers memolizer looks like this we have a blazer front end we have a net api we have a dot net service to process messages and we have an azure function to send messages back to the front end we use a slew of other azure services which i go into detail in my project tie video which i will link to in the description from an infrastructure s code perspective i've been using terraform to provision all of these services to azure bicep came out a couple of months ago so i said let's just take it for a spin and see how that would compare to what i'm already doing with terraform so i'm in vs code and i have the memolizer workspace open under the memolyzer folder you see i have iac under there i have bicep and i have terraform the files highlighted in blue over here are the bicep files that i created to deploy my azure resources the script files are simply just helper script files so i don't have to type in the commands every time this main.json file is the arm template that is generated by bicep so the main command i call when i want to provision my resources is called deploy and i pass it in a base name parameter for my application so deploy.sh space memolizerdev01 that will provision all of my resources with that prefix i then call easy deployment sub create and pass it the name of the json that's created by bicep so in this case main.json and then i just pass it a bunch of standard parameters and then in my plan.sh file i'm simply calling what if instead of create so i can see what would happen if i were to deploy that arm template so to reiterate the output of bicep is simply an arm template bicep helps you develop arm templates by giving you an abstraction or an easy to use interface on top of arm arm can be quite overwhelming especially when you're first getting started so the goals or one of the goals of bicep is to make it easier to create arm templates from a terraform perspective the files i created for terraform are highlighted here in blue and just like bicep i created a bunch of shell scripts to help me execute those terraform commands now you notice here that terraform doesn't generate an arm template that's sent to azure it simply executes methods on the go management library sdk to provision those resources so it converts something like this to a create resource group sdk call and that brings me to my first big point about bicep and terraform is that if you want features to be supported in your iac native then bicep and arm are really the way to go as soon as arm supports something then the arm templates and bicep will support it as well with terraform you might have to wait a while for the terraform team or somebody from the open source community or somebody from microsoft to implement those features but there's a workaround with terraform so before a bicep i was using terraforming to get around that i have this tweaks.sh file this file is all of the gap filling code that's needed in order to support the features that i needed in my application that weren't yet supported by terraform for example custom domain for cognitive services managed identity for cognitive services and a couple of other things just simply weren't supported by terraform so i have to shell out to this tweaks.sh file every time i want to deploy you'll notice with bicep i didn't have to do this because all of the features that i needed were supported by arm therefore arm templates therefore bicep so i like to call this zero day support which basically just means the day that something is released on azure your iac with bicep and arm templates will support it one thing i want to mention though is that we do not have perfect azure swagger documents and bicep is built on top of those swagger documents so you'll see some things like missing intellisense missing validation and so on so bicep has actually been a pretty good driver to help us sure up those azure swagger files and we definitely have efforts internally to go and fix all of those things but for now you might find some differences between bicep validation and intellisense and what you can actually get from the azure underlying resource provider so you might have to do some googling and some other things to find out what those properties are on your own and that's just for now that's something we're working on and will be fixed the next thing i want to talk about is deployment state so you'll notice here i have this terraform.tf state.d and i have dev and i have staging so i have these different workspaces in terraform to keep track of the state for each of the environments that i want to provision the azure services to for example i have dev staging prod those files are all kept locally you can store them in blob storage but you have to manage the state of your terraform deployments through these files to be honest i ran into a bunch of issues with terraform state and if they get out of sync you have to import those resources to your state and it can get pretty messy on the other hand bicep doesn't really have the concept of a workspace they have a concept of deployment and you name your deployments and those deployments either fail or succeed you can manage them but it's not as easy as it can be and the arm team is working on something called stacks and i'll link to the description where they talk about that more in one of the recent community calls but for now when you have a failed deployment you got to kind of do some work to figure that out that's in the works will be improved soon as well so here we have the three versions of our iac code on the left we have bicep we have the arm template that's generated by bicep and then we have the terraform file let's first take a look at how you pass variables to your scripts so in bicep you simply define param the name the type and the default value the interesting thing though is that those parameters are only available to that immediate scope and so you need to redefine those parameters for every file or resource or module that you create that in turn generates the arm valid parameters that you can then use in your arm template file in terraform we have a variables file with all the variables defined here and they can be accessed in any terraform file in your project and then string interpolation is supported by biceps so here for example we wanted to find the resource group name we just do single quote dollar curly base name which is the parameter name rg and that will set our resource group name in arm what that looks like is right here we use format and then we have to pass in the parameters and the base name once you figure this out once in arm it's fine but i'll tell you what string interpolation is nice and then in terraform we also have string interpolation pretty straightforward there so to actually deploy a resource in bicep you specify that you want a resource you give it a friendly name that can be anything and then you pass in the resource provider name in this case it's microsoft.resourceslash resource groups and then you pass in the api version needed for that rfp now i've already typed this in but if you were starting from a blank file you would simply type in resource give it a friendly name and then just start typing the resource type so for example resource groups and then i'm just going to hit enter equals and then i'm going to hit enter again and then enter again and now i'm in the template so if i do control space that gives me all the valid properties i need so for example location and i can add and i have intellisense for the parameters as well and then i go on my way and i'm building up my resources with standard arm you use the resource provider type the api version the name location but you have to do your own variable substitution your parameter substitution it's a little bit harder to figure out exactly what's happening and we have a bunch of vs code extensions and all that and it's getting better but bicep tries to help you one step further and terraform is pretty similar we have a resource we have the string of the resource provider which is a friendly name slash alias of it and then we have a friendly name in this case rg we then define our properties you'll notice here that you'll notice here terraform does not require an api version whereas arm and bicep do one of the first suggestions i had to the bicep team is is to just let me do this say resource resource group like this and not require me to know the resource provider specific magic string as well as know the api version this would be much cleaner and then say if i wanted to say specify the api version i could just do so on my own if i wanted to be something other than the default so let's take a look at how we define then sub resources starting here on the left we have bicep where we define all of those resources in a module so what this is saying is i want the target scope to be subscription at the top which means my resource group is deployed to the subscription but my resources are deployed to the scope of the resource group okay and in order to use scope you have to put it in a module i like this because it's modulized but in terraform i don't even have to think about that see over here where i just have one terraform file and all of my azure resources are in that one file i could obviously break those into different files but my point is with bicep i have to think about subscription level deployment and think about resource group level deployment whereas with terraform i do not now when i first started with this in arm directly i tried to do the subscription level deployment and you have to put in a very specific template subscription deployment template and then you say you want to do a resource group and then resource is slash deployments and then you have all these past the parameters and then there's a new template and so on and it it did the nesting got crazy the scrolling got crazy and i just eventually figured it out but i had some help from the arm team to do so now over on the left i have resources dot bicep which defines those same parameters like i said you have to define them in all the files and modules that you use those parameters and then i have a variable here which is an array of secrets that i pass to key vault for my access policies and then i go on and define all of my azure resources now let's talk about aliasing here for a second because in bicep we're using the actual resource provider name it doesn't often match the friendly name that we're used to referring to the services for example cosmos database is resource provider name is microsoft.documentdb so when i came in here first i just typed in resource cosmos and then cosmos db and i couldn't find it um i i know that it's called document database but at the time i was just looking for cosmos so i had to google it i had to find it and i had to find the arm template and then find the resource provider and i found it and it was fine but a little bit frustrating so the good thing with terraform is that they can call it whatever they want and so the azure rm cosmos db account super easy to find so what i would recommend from a bicep perspective is enable aliases here so i can say resource cosmos account cosmos database which points to microsoft.document database the next thing i want to talk about is accessing the properties of a resource after it's been deployed such as principal ids connection strings keys and so on with terraform it's super super easy the documentation is super clear you have inputs you have outputs you can find connection strings and it's just super easy to use for example this is my function out i have app settings that needs to store the connection string so how i do that is storage account storage primary connection string super easy now that same thing in bicep looks like this you have to actually construct your connection string on your own and this is really that's not really bicep fault per se it's really just that the resource provider doesn't provide a really friendly way to get this connection string but this is what i had to go through i had actually had to stack overflow a lot of this and google this to find out the exact pattern in ways to access this not very friendly at all we really really need to fix that on the other hand we have other properties that dangle just fine for example vault.uri instrumentation key you know those things are super easy to dangle off of those main resource provider objects very friendly and easy to use just as another example of that for service bus if i wanted to get the primary connection string for my service bus super simple and terraform primary connection string right there so the same thing in bicep you have to call list keys you have to construct the resource id the service bus name this root manage shared access key you have to pass in the api version and the primary connection string so this is not really biceps fault per se because the underlying resource provider doesn't support it but it would be great to solve that just because i spent a bunch of time trying to figure that out now let's talk about code validation as you can see on the left here i have a squiggly under form recognizer that's telling me the resource needs a property name which is great it has some good validation there so add that back the squiggly goes away now i did notice that bicep doesn't have all the validation rules in place that the arm templates do and so i would get a false positive and bicep i would generate the files and that would get validation errors and arm templates so that's something that we definitely need to figure out we need a 100 validation in bicep at least whatever we have equivalent to whatever the arm swagger templates give us and from a terraform perspective they have a lot of vs code plugins the language server validation rules so you know that it's terraform correct but you may still get some errors when you publish to azure api differences or whatever so that whole validation piece is not fleshed out for any of these options and it can be improved across the board now let's talk about dependent resources within a deployment from an armed perspective you need to specify the depends on property which is an array of all the resources that this resource depends on you have to construct the resource id with the type and the name in bicep all you have to do is reference the name of that resource within your other resource and it will automatically generate those depends on properties which is very similar to how it works in terraform and terraform you can specify depends on but you don't have to now let's talk about how we deal with child resources in bicep we're defining a cosmos account a sql database and a sql container the account has a name of base name cosmos account the database has cosmos account dot name slash the name of the sql database and then the collection within that database is sql database name dot name slash images so that's going to generate all depends on you need but you have to keep in mind that's how you do child resources is with the naming convention of slash i know the team is working on alternate approaches to do child resources and i hope they come up with something a little better than that now in terraform we define the cosmos account but then in the sql database here all we do is we say the account name is equal to cosmos account name and then here when we define the container we say the database name is equal to the sql database that we defined earlier so it's a little bit cleaner than what we have with bicep like i said the bicep team is working on improving how we do child resources but for now it is what it is and just to show you real quick what that translates to in arm is a bunch of format strings we're formatting the cosmos account or formatting the database name and then the collection name now let's talk about how we do role assignments in bicep from my resources.bicep file i'm calling this module called roles.bicep starting from the bottom of the role stack we have a role assignment resource and we pass a bunch of properties to it and we pass in a guide that is defined in the subscription id the principal id the role id and the resource group name you can keep going to make it more unique i found that this is the right mix that works for me one step above that i have roles dot bicep so all of the roles that are needed for each of the principles are defined here i have the role ids this is going to be a lot better when bicep supports loops right now they do not support loops you could imagine i have a variable which is an array of all of the roles that i need and i just loop through those roles and assign this i don't need to do this dance here and then i have roles acr to bicep because my service principles need as well as the managed identity of my kubernetes cluster only needs to pull those containers down from acr so i broke those up into a different file and then back to resources.bicep i am calling roll.bicep for each of the ids i need so the cli user which is my account the function identity principal id the the aks qubit identity as well as the aks manage identity for that service now over to terraform i could not figure out how to do role assignment consistently or it wasn't failing every time so i just ripped all of my role assignment code out of my terraform files and just resorted to creating this script file which does really the same thing that you saw in bicep it's just shelling out to the azure cli so as part of my deployment i run this perms.sh i could go back and figure out how it works but i'm not really motivated to do so just so i'm just going to keep it as is so one of the other cool things that i wanted to point out with terraform is that they give you access to the principle that is executing the terraform deployment so i could easily reference my cli user id from within my terraform template so for example if i specify data azure rm client config current within my terraform files i can access the object id of my cli user or bicep how i get that cli user id is i call az80 signed in user and get the object id and then i'm passing that when i do my deployment cli user id and then i'm referencing it there a little bit of a hack there but i hope that bicep implements a feature that allows me to access the principle id of the account that is executing that bicep script it's a little bit difficult because the arm template executes on arm in terraform executes on the local machine so i don't know how they're going to do that but i hope we can figure out a way the last thing i want to talk about is documentation so as you're going about building up your bicep file you're going to need to research some things online intellisense might not be perfect right away validation might not be perfect but i'm just going to show you what i do i select this text document database database accounts and then i search for that text and i find the arm template specification here i also often find myself at github.com azure azure quickstart templates where you can search for various templates to suit your needs so for example here's one on cosmos db sql yes this is arm but the format of it is very helpful when filling the gaps with what bicep has today and what it will have in the future from a terraform perspective you're going to grab this text and search for that online that's going to pull up a sample all of the inputs and then all of the outputs so terraform definitely better documented easier to use from a property input output perspective as it stands today but i believe bicep will get better over time especially as the azure swaggers improve and get more correct over time alright that was a lot i know but i hope it helps you i hope it jump starts your effort with bicep helps you get around some of the rough edges and also helps you understand the differences between bicep arm templates and terraform thank you for watching have an awesome day
Info
Channel: Jon Gallant
Views: 3,874
Rating: 4.9245281 out of 5
Keywords:
Id: 3lTrIgTJ9yc
Channel Id: undefined
Length: 21min 42sec (1302 seconds)
Published: Wed Dec 09 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.