While preparing a Kubernetes course, I had to put in place a cloud infrastructure for future students so as they can perform the tasks of the course.

Basically, I had to provision a couple of Vitual Machnines and a virtual network. Which is no big deal if you have to do it once. But Since we’re planning on having multiple classes on different periods of time, it could be a good idea to automate the provisioning and deletion of classes.

To achieve this we’ll be using Terraform s Azure Provider to create our cloud resources for the course.

Only prerequirement is to generate an Azure Service Principal Account Credentials for your Azure Cloud Subscription.

Then setup your terraform folder where the *.tf files will be.

terraform.tfvars

We declare variable values here, they’ll be used afterwards in our terraform scripts.

# Azure Subscription Id
azure-subscription-id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Azure Client Id/appId
azure-client-id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Azure Client Secret/password
azure-client-secret = "XXXXXXXX"
# Azure Tenant Id
azure-tenant-id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 

variables.tf

We declare our variables here, subscription credentials, a map and a list of strings.

variable "user_names" {
  description = "Create IAM users with these names"
  type        = list(string)
  default     = ["student1", "student2", "student3"]
}

variable "nic_numbers" {
  description = "map of VMs and private ips"
  default     = {
    "1" = "nic-vm1"
    "2" = "nic-vm2"
    "3" = "nic-vm3"
  }
}

variable "azure-subscription-id" {
  type        = string
  description = "Azure Subscription Id"
}
variable "azure-client-id" {
  type        = string
  description = "Azure Client Id/appId"
}
variable "azure-client-secret" {
  type        = string
  description = "Azure Client Id/appId"
}
variable "azure-tenant-id" {
  type        = string
  description = "Azure Tenant Id"
}

main.tf

The main.tf file is where we specify which terraform version we’ll be using and which provider as well. Here, it’s the azurerm provider.

We need to precise the providers variables so it can authenticate to our Azure Subscription. These variables are fetched from the terraform.tfvar file.

Also the Azure resource group, virtual network and subnet blocks as they are central resources, but you can also just put them in a separate file.

terraform {
  required_version = ">= 0.12"
  required_providers {
    azurerm = ">= 2.39.0"
  }
  
}

provider "azurerm" {
  features {}
  subscription_id = var.azure-subscription-id
  client_id       = var.azure-client-id
  client_secret   = var.azure-client-secret 
  tenant_id       = var.azure-tenant-id
}

resource "azurerm_resource_group" "virtual-class" {
  name     = "virtual-class"
  location = "West Europe"
}

resource "azurerm_virtual_network" "virtual-net" {
  name                = "class-vnet"
  address_space       = ["192.168.0.0/16"]
  location            = azurerm_resource_group.virtual-class.location
  resource_group_name = azurerm_resource_group.virtual-class.name
}

resource "azurerm_subnet" "class-subnet" {
  name                 = "class-snet"
  resource_group_name  = azurerm_resource_group.virtual-class.name
  virtual_network_name = azurerm_virtual_network.virtual-net.name
  address_prefixes     = ["192.168.1.0/24"]
}

vms.tf

This is the bloc that will allow us to create a Virtual machine per Student, give it a static IP within the subnet and create credentials of the student for that VM. to do so, it will loop through the map and list of strings we wrote in the variables.tf file, creates and configures each student’s VM.

Per example, student1 will get internal-vm1 with the private IP 192.168.1.11, he can access it with the student1:student1 username:password pair.

resource "azurerm_network_interface" "vm-nic" {
    for_each            = var.nic_numbers
    name                = "nic-vm${each.key}"
    location            = azurerm_resource_group.virtual-class.location
    resource_group_name = azurerm_resource_group.virtual-class.name

    ip_configuration {
      name                          = "internal-vm${each.key}"
      subnet_id                     = azurerm_subnet.class-subnet.id
      private_ip_address_allocation = "Static"
      private_ip_address            = "192.168.1.1${each.key}"
    }
}

resource "azurerm_linux_virtual_machine" "vm" {

    for_each            = var.nic_numbers
    name                = "vm${each.key}"
    resource_group_name = azurerm_resource_group.virtual-class.name
    location            = azurerm_resource_group.virtual-class.location
    size                = "Standard_F2"
    admin_username      = "student${each.key}"
    network_interface_ids = ["/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/virtual-class/providers/Microsoft.Network/networkInterfaces/${each.value}"]
    admin_password = "student${each.key}"

    os_disk {
      caching              = "ReadWrite"
      storage_account_type = "Standard_LRS"
    }

    source_image_reference {
      publisher = "Canonical"
      offer     = "UbuntuServer"
      sku       = "16.04-LTS"
      version   = "latest"
    }
}

** Change the xxxx-xx….xxxx characters with your Azure subscription ID.

Provision the Infrastructure

Okey now we’re all set. We can init, plan, apply and destroy our resources with the provided terraform scripts. Make sure they’re in the same directory.

So the day we have a planned class, we can mount the cloud infrastructure for it with the right number of students, all we have to do is to append the list of strings in the variables.tf file.

Provision the class resources

terraform init
terraform plan -var-file="terraform.tfvars"
terraform apply -var-file="terraform.tfvars"

Destroy the class resources

terraform destroy 

That’s it, we now have a Cloud Virtual class Infrastructure with a dynamic number of students. Using terraform gives us the flexibility to switch to other Cloud providers easily.