
{"id":8315,"date":"2020-06-26T14:24:38","date_gmt":"2020-06-26T14:24:38","guid":{"rendered":"https:\/\/rax-stg-wp-aws.com\/blogs\/creating-a-vm-in-azure-by-using-terraform-with-for-loops\/"},"modified":"2026-11-03T19:29:33","modified_gmt":"2026-11-03T19:29:33","slug":"creating-a-vm-in-azure-by-using-terraform-with-for-loops","status":"publish","type":"blogs","link":"https:\/\/www.rackspace.com\/de\/blogs\/creating-a-vm-in-azure-by-using-terraform-with-for-loops\/","title":{"rendered":"Creating a VM in Azure by using Terraform with for loops"},"content":{"rendered":"<p><strong>Introduction<\/strong><\/p>\n<p>You can easily create multiple virtual machines (VMs) on Azure\u00ae by using&nbsp;Hashicorp\u00ae Terraform\u00ae with the help of Visual Studio\u00ae Code (VS Code).<\/p>\n<p>This blog post focuses on bulk VM creation on Azure. I also emphasize the&nbsp;Infrastructure-as-Code (IaC) approach. I use VS Code throughout this blog, but&nbsp;you can use your favorite IDE.<\/p>\n<p><strong>&nbsp;Let&#8217;s get started<\/strong><\/p>\n<p>I went through the general requirements to create multiple VMs in Azure with&nbsp;some specific standard or typical nomenclature. Even when we build stuff on the&nbsp;fly, we have to keep an eagle eye on everything to sustain our standards. And&nbsp;maintaining the standard is not at all easy, mainly because we have to follow&nbsp;the same name canons for VM name, OS disk, data disk, network interface controller&nbsp;(NIC) name, and so on.<\/p>\n<p>IaC lets us manage every aspect of maintaining standards, including things we<br \/>\nbuild in the backend on the real surface.<\/p>\n<p>I have written some simple Terraform code to create two VMs in Azure with similar&nbsp;names for every resource. I also use tags, which are a new way of segregating&nbsp;things. So, let&#8217;s straight jump into the action and get our hands dirty with&nbsp;Terraform.<\/p>\n<p>Azure VM creation requires a resource group (RG), virtual network (VNet), subnet,&nbsp;NIC, and VM configuration. Keeping all that in mind, let&#8217;s make all the files&nbsp;separate so that it is easy to understand.<\/p>\n<p><strong>&nbsp;Create the resource group file<\/strong><\/p>\n<p>First, we need to create an RG code block in the Hashicorp configuration language&nbsp;(HCL). Let&#8217;s create two RGs (one for the VM and NIC and another for networking&nbsp;stuff). As a best practice, I don&#8217;t recommend keeping everything together.&nbsp;Before creating the RGs, define a provider block for Terraform, so it understands&nbsp;that we are deploying Azure resources. Store this information for Terraform in&nbsp;a separate file called <strong>providers.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture1_2.png\" alt=\"azure terraform pic 1\" \/><\/p>\n<p>The RG code, <strong>rg.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture2_0.png\" alt=\"azure terraform pic 2\" \/><\/p>\n<p><strong>&nbsp;&nbsp;Create the VNET and subnet files<\/strong><\/p>\n<p>Now, the second task is to create a VNet and a subnet for our VM. The VNet block,<strong>vnet.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture3_0.png\" alt=\"azure terraform pic 3\" \/><\/p>\n<p>And the subnet code, <strong>subnet.tf :<\/strong>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture4_0.png\" alt=\"azure terraform pic 4\" \/><\/p>\n<p><strong>&nbsp;Create the NIC file&nbsp;<\/strong><\/p>\n<p>We are almost done with networking stuff except for our VM&#8217;s NIC. Let&#8217;s put the&nbsp;NIC code in the VM&#8217;s RG. Notice that I&nbsp; referenced the app RG in&nbsp;<strong>resource\\_group\\_name<\/strong>&nbsp;because keeping NIC details in the Network RG does not&nbsp;suit me.<\/p>\n<p>The NIC code:&nbsp;<strong>Nic.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture5.png\" alt=\"Azure terraform pic 5\" \/><\/p>\n<p><strong>&nbsp;Create the storage file&nbsp;<\/strong><\/p>\n<p>Now we are done with all the networking stuff, but most people consider a VM without&nbsp;diagnostic settings enabled to be a poor build. And I don&#8217;t want anyone to call&nbsp;me a &#8220;new builder&#8221;! Storage account code is simple, and by using that, we can&nbsp;call ourselves good Azure implementors.<\/p>\n<p>The Storage account file, <strong>storage_account.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture6.png\" alt=\"azure terraform pic 6\" \/><\/p>\n<p><strong>&nbsp;Create the VM file&nbsp;<\/strong><\/p>\n<p>We are all set for VM code, but remember, we have to use the same standards that&nbsp;we used earlier, such as VM name, NIC name, disk name, and so on.<\/p>\n<p>Final code for our VM, <strong>vm.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture7.png\" alt=\"azure terraform pic 7\" \/><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture8.png\" alt=\"azure terraform pic 8\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture9.png\" alt=\"azure terraform pic 9\" \/><\/p>\n<p><strong>Create the variable file&nbsp;<\/strong><\/p>\n<p>Finally, I put a few things into variables such as all the VM names. You can put&nbsp;other items into variables, such as RG, VNet, and subnet names. Using variables&nbsp;helps when you do giant builds.<\/p>\n<p>The variable file, <strong>Variable.tf<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26712-body-Picture10.png\" alt=\"azure terraform pic 10\" \/><\/p>\n<p><strong>Build the VMs&nbsp;<\/strong><\/p>\n<p>My goal is to create two VMs by using a for loop. Thus, the <strong>vm_name<\/strong>&nbsp;variable has two VM names (you can add multiples), and the second variable is the location&nbsp;to which I want to deploy the Azure resources.<\/p>\n<p>Let me share how I keep my standards intact: I used <strong>VMName-nic<\/strong>&nbsp;for every NIC,&nbsp;<strong>VMName-Osdisk<\/strong>, and <strong>-data1<\/strong>. All resources such as VM, NIC, and DISK pop&nbsp;up with the same nomenclature, thus, we can easily understand which resources<br \/>\nbelong to which VM.<\/p>\n<p><strong>Deploy<\/strong><\/p>\n<p>Let&#8217;s get down to business and learn how to deploy the VMs in Azure. It&#8217;s time&nbsp;to boil the eggs.&nbsp;For simplicity, I use the Azure CLI for this task instead of using a proper DevOps&nbsp;approach and running this through a pipeline and storing the site files somewhere&nbsp;other than our directory.<\/p>\n<p>If you don&#8217;t have the `az` CLI on your machine, you can<br \/>\n[install it](https:\/\/docs.microsoft.com\/en-us\/cli\/azure\/install-azure-cli?view=azure-cli-latest).<\/p>\n<p>1. Log into Azure:<em>&nbsp;az login<\/em><\/p>\n<p>2. Check how many subscriptions we have for this tenant:&nbsp;<em>az account list &#8211;output table<\/em><\/p>\n<p>3. Set the right subscription for our deployment:<\/p>\n<p>&nbsp; &nbsp; &nbsp; &nbsp;<em> az account set &#8211;subscription &#8220;XXXXXX-XXXXXXX-XXXX-XXX&#8221;<\/em><\/p>\n<p>4. Navigate to the directory where we have put our all Terraform code files (I&nbsp;used temp for this example, but I don&#8217;t recommend that location):<\/p>\n<p>&nbsp; &nbsp; &nbsp; &nbsp; cd <em>C:\\temp<\/em><\/p>\n<p>5. Initialize Terraform in this directory:<\/p>\n<p><em>&nbsp; &nbsp; &nbsp; &nbsp; terraform init<\/em><\/p>\n<p>6. Run the Terraform plan to check what we are going to build and save the&nbsp;plan output for later use by adding the `<em>-out<\/em>` flag in the command:<\/p>\n<p><em>&nbsp; &nbsp; &nbsp; &nbsp; terraform plan<\/em><\/p>\n<p>&nbsp; &nbsp; &nbsp; &nbsp; or<\/p>\n<p><em>&nbsp; &nbsp; &nbsp; &nbsp; terraform plan -out<\/em><\/p>\n<p>7. Execute the Terraform code to deploy and type yes at the confirmation check<br \/>\n&nbsp; &nbsp;or use <em>-auto-approve<\/em>&nbsp;to skip manual confirmation:<\/p>\n<p>&nbsp; &nbsp;<em> &nbsp; &nbsp; terraform apply<\/em><\/p>\n<p>&nbsp; &nbsp; &nbsp; &nbsp; or<\/p>\n<p><em>&nbsp; &nbsp; &nbsp; &nbsp; terraform apply -auto-apply<\/em><\/p>\n<p>8. Check the VM that you created:<\/p>\n<p>&nbsp; &nbsp;<em> &nbsp; &nbsp; az vm list -o table<\/em><\/p>\n<p><strong>&nbsp;Some secret for loop hacks<\/strong><\/p>\n<p>You can create multiple VMs by running a Terraform for loop as shown in the&nbsp;following code. The loop executes as many times as you defined the variable&nbsp;(twice, in our case, because I defined two VM names in the variable):<\/p>\n<p><em>&nbsp; &nbsp; for_each = toset(var.vm_name)<\/em><\/p>\n<p><strong>&nbsp;The `<em>each<\/em>` object:<\/strong><\/p>\n<p>The for loop in Terraform has a key-pair, key and value, but both are generally&nbsp;similar.&nbsp;In resource blocks, where you set <strong>for_each<\/strong>, you can use additional r<em>each<\/em>&nbsp;<em>objects<\/em> in your expressions to modify the configuration of each instance.<\/p>\n<p>And&nbsp;<strong>each<\/strong> object has two attributes:<\/p>\n<p>&#8211; <strong>each.key<\/strong>: The map key (or set member) corresponding to this instance.<\/p>\n<p>&#8211; <strong>each.value<\/strong>: The map value corresponding to this instance. If you provided&nbsp;a set, this is the same as <strong>each.key<\/strong>.<\/p>\n<p>You can use the Terraform <strong>fmt<\/strong>&nbsp;command to format the code, such as rewriting&nbsp;Terraform configuration files to conform to a canonical format and style.&nbsp;This command applies a subset of Terraform language style conventions, along&nbsp;with other minor adjustments for readability.<br \/>\n&nbsp;<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>Have fun using Terraform for Azure and maintain standards with some simple code<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating a VM in Azure by using Terraform with for loops<\/p>\n","protected":false},"author":2,"featured_media":8317,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","format":"standard","meta":{"content-type":"","nid":"26712","content_type":"blog","created_by":"10130","authored_on":"2024-03-15T14:24:38+00:00","field_article_industries":"","tag_category":"Technical","field_blog_author_text":"by Rackspace Technology Staff","seo_description":"Learn how to create multiple VMs on Azure using Hashicorp Terraform with the help of Visual Studio Code, emphasising the Infrastructure-as-Code approach.\r\n","field_featured_image":"","insights_image":"\/wp-content\/uploads\/2026\/blog_technical_images\/26712-insights_image-microsoft-technical-blog-1-insights.jpg","field_partners":"VMware","rxt_platforms":"Microsoft Azure","product":"","publisheddate":"2020-06-26T14:24:38","rxt_solutions":"Cloud Management & Operations, Multicloud","opengraph_tag":"","x_tag":"","teaser_flag":"Technical Blog","seo_titile":"Efficient Virtual Machine Creation Azure | Rackspace Technology","field_topics":"","field_slug":"create-a-vm-in-azure-by-using-terraform-with-for-loops","footnotes":""},"categories":[178],"tags":[204,201],"class_list":["post-8315","blogs","type-blogs","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-technical","tag-vmware"],"_links":{"self":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs\/8315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs"}],"about":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/types\/blogs"}],"author":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/comments?post=8315"}],"version-history":[{"count":3,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs\/8315\/revisions"}],"predecessor-version":[{"id":10041,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs\/8315\/revisions\/10041"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/media\/8317"}],"wp:attachment":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/media?parent=8315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/categories?post=8315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/tags?post=8315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}