Getting started with Azure and Terraform – Part 3

Martin Therkelsen/ May 12, 2021/ Automation, Azure, Citrix, DevOps, Microsoft/ 0 comments

In this part of the series, I want to create the Azure vNet and subnets for my Azure environment. I will be creating a hub/spoke topology where the hub will be connected to my on-premises environment later in this series. To get started with networking, I read through the modules and providers that Terraform provides. You can find it here.

In the last part I wrote that I wasn’t sure how to handle the number of files and that is still the case, I do however want to change a bit from my last post, so let us get started.

I will rename my file called “resourcegroups.tf” to “main.tf”. Doing this makes sense to me so I can have more things in the same file, and for now, I hope it won’t mean there will be many hundred lines of code, but I guess I will see what happens.

After reading the documentation on the Terraform site, I can see that I am now working with a module called “network”. Working with modules also means that I need to run “terraform init” again to ensure that the module is present on my laptop. Before I run the command, I need to add the code to my file, so the module is declared. Below is my code for the hub vNet creation, and below that, you can see what happens when I run the “terraform init” command after the module has been declared.

module "HubvNet" {
  source              = "Azure/network/azurerm"
  resource_group_name = var.ResourceGroups.HubNetwork
  address_space       = var.HubvNet.address_space
  subnet_prefixes     = [var.HubvNet.GatewaySubnetPrefix, var.HubvNet.HubCoreVMSubnetPrefix, var.HubvNet.HubSharedServicesSubnetPrefix]
  subnet_names        = [var.HubvNet.GatewaySubnetName, var.HubvNet.HubCoreVMSubnetName, var.HubvNet.HubSharedServicesSubnetName]

  depends_on = [azurerm_resource_group.resourcegroups]
}

If I run the “terraform plan -out network.plan” command now, I can see that it will add 4 new resources to my environment.

Before I deploy this plan, I will add my spoke vNet and show the updated variables file. The variables file now contains information about both hub and spoke subnet along with the resource groups, as you can see below.

variable "Location" {
  type = string
  default = "WestEurope"
}
variable "ResourceGroups" {
  type    = map
  default = {
    "HubNetwork"          = "Terraform-Hub-Network"
    "HubCoreVMs"          = "Terraform-Hub-CoreVMs"
    "HubSharedServices"   = "Terraform-Hub-SharedServices" 
    "SpokeNetwork"        = "Terraform-Spoke-Network"
    "SpokeSharedServices" = "Terraform-Spoke-SharedServices"
    "SpokeCitrixCore"     = "Terraform-Citrix-Core"
    "SpokeCitrixSilo1"    = "Terraform-Citrix-Silo1"
  }
}
variable "HubvNet" {
  type = map
  default = {
    "vNetName"                      = "HubvNet"
    "address_space"                 = "172.16.0.0/16"
    "GatewaySubnetPrefix"           = "172.16.0.0/26"
    "GatewaySubnetName"             = "GatewaySubnet"
    "HubCoreVMSubnetPrefix"         = "172.16.0.64/26"
    "HubCoreVMSubnetName"           = "Core-VM"
    "HubSharedServicesSubnetPrefix" = "172.16.0.128/26"
    "HubSharedServicesSubnetName"   = "Shared-Services"
  }  
}
variable "SpokevNet" {
  type = map
  default = {
    "vNetName"                        = "SpokevNet"
    "address_space"                   = "172.17.0.0/16"
    "SpokeCoreVMSubnetPrefix"         = "172.17.0.64/26"
    "SpokeCoreVMSubnetName"           = "Core-VM"
    "SpokeSharedServicesSubnetPrefix" = "172.17.0.128/26"
    "SpokeSharedServicesSubnetName"   = "Shared-Services"
    "SpokeCitrixCoreSubnetPrefix"     = "172.17.0.192/26"
    "SpokeCitrixCoreSubnetName"       = "Citrix-Core-VM"
    "SpokeSilo1SubnetPrefix"          = "172.17.1.0/24"
    "SpokeSilo1SubnetName"            = "Citrix-Silo1"
  }  
}

Now I can add the spoke vNet to the main file and it will then look like this.

resource "azurerm_resource_group" "resourcegroups" {
  for_each  = var.ResourceGroups
  name      = each.value
  location  = var.Location
}

module "HubvNet" {
  source              = "Azure/network/azurerm"
  vnet_name           = var.HubvNet.vNetName
  resource_group_name = var.ResourceGroups.HubNetwork
  address_space       = var.HubvNet.address_space
  subnet_prefixes     = [var.HubvNet.GatewaySubnetPrefix, var.HubvNet.HubCoreVMSubnetPrefix, var.HubvNet.HubSharedServicesSubnetPrefix]
  subnet_names        = [var.HubvNet.GatewaySubnetName, var.HubvNet.HubCoreVMSubnetName, var.HubvNet.HubSharedServicesSubnetName]

  depends_on = [azurerm_resource_group.resourcegroups]
}
module "SpokevNet" {
  source              = "Azure/network/azurerm"
  vnet_name           = var.SpokevNet.vNetName
  resource_group_name = var.ResourceGroups.SpokeNetwork
  address_space       = var.SpokevNet.address_space
  subnet_prefixes     = [var.SpokevNet.SpokeCoreVMSubnetPrefix, var.SpokevNet.SpokeSharedServicesSubnetPrefix, var.SpokevNet.SpokeCitrixCoreSubnetPrefix,var.SpokevNet.SpokeSilo1SubnetPrefix]
  subnet_names        = [var.SpokevNet.SpokeCoreVMSubnetName, var.SpokevNet.SpokeSharedServicesSubnetName, var.SpokevNet.SpokeCitrixCoreSubnetName,var.SpokevNet.SpokeSilo1SubnetName]

  depends_on = [azurerm_resource_group.resourcegroups]
}

Since I added a second vNet I need to run “terraform init” again to make use of the network module in this code. When I run that command it will look like below.

I am now ready to run the “terraform plan -out network.plan” command again to see which resources will be added to my deployment.

As you can see it will add 9 resources to my deployment, so I will now run the command ‘terraform apply “network.plan”‘.

After the command completes I can take a look at my subnets in the spoke vNet.

This all looks great, but there is one more thing I want to do before I finish the part of the blog series, and that is to create the vNet peering between the hub and spoke vNet. To create this, I need to add a new provider called “azurerm_virtual_network_peering”. You can find the documentation here.

I will add two sections to my main file and no extra variables are needed. The main file now looks like below.

resource "azurerm_resource_group" "resourcegroups" {
  for_each  = var.ResourceGroups
  name      = each.value
  location  = var.Location
}

module "HubvNet" {
  source              = "Azure/network/azurerm"
  vnet_name           = var.HubvNet.vNetName
  resource_group_name = var.ResourceGroups.HubNetwork
  address_space       = var.HubvNet.address_space
  subnet_prefixes     = [var.HubvNet.GatewaySubnetPrefix, var.HubvNet.HubCoreVMSubnetPrefix, var.HubvNet.HubSharedServicesSubnetPrefix]
  subnet_names        = [var.HubvNet.GatewaySubnetName, var.HubvNet.HubCoreVMSubnetName, var.HubvNet.HubSharedServicesSubnetName]

  depends_on = [azurerm_resource_group.resourcegroups]
}
module "SpokevNet" {
  source              = "Azure/network/azurerm"
  vnet_name           = var.SpokevNet.vNetName
  resource_group_name = var.ResourceGroups.SpokeNetwork
  address_space       = var.SpokevNet.address_space
  subnet_prefixes     = [var.SpokevNet.SpokeCoreVMSubnetPrefix, var.SpokevNet.SpokeSharedServicesSubnetPrefix, var.SpokevNet.SpokeCitrixCoreSubnetPrefix,var.SpokevNet.SpokeSilo1SubnetPrefix]
  subnet_names        = [var.SpokevNet.SpokeCoreVMSubnetName, var.SpokevNet.SpokeSharedServicesSubnetName, var.SpokevNet.SpokeCitrixCoreSubnetName,var.SpokevNet.SpokeSilo1SubnetName]

  depends_on = [azurerm_resource_group.resourcegroups]
}
resource "azurerm_virtual_network_peering" "Hub-2-Spoke-Peering" {
  name                      = "Hub-2-Spoke-Peering"
  resource_group_name       = var.ResourceGroups.HubNetwork
  virtual_network_name      = var.HubvNet.vNetName
  remote_virtual_network_id = module.SpokevNet.vnet_id
}

resource "azurerm_virtual_network_peering" "Spoke-2-Hub-Peering" {
  name                      = "Spoke-2-Hub-Peering"
  resource_group_name       = var.ResourceGroups.SpokeNetwork
  virtual_network_name      = var.SpokevNet.vNetName
  remote_virtual_network_id = module.HubvNet.vnet_id
}

After running my plan and applying command, I now have my peering up and running in Azure.

I think this is a good place to end the part of the blog series and in the next part I want to add the VPN gateway to the environment. Stay tuned.

Share this Post

Leave a Comment

Your email address will not be published. Required fields are marked *

*
*