#
Bonus Hands-On Exercise: Dynamic Configuration with Workspaces and Provisioners
#
Exercise Objective
In this exercise, participants will create dynamic infrastructure that adjusts based on the current workspace. They will also use provisioners to automatically install different software on virtual machines based on the environment (e.g., installing Nginx in development and Apache in production).
#
Steps
#
Step 1: Set Up Workspace-Based Variables
Create Separate Variable Files for Dev and Prod:
- In your project directory, create two separate variable files:
dev.tfvars
andprod.tfvars
.
- In your project directory, create two separate variable files:
Define Environment-Specific Variables in Each File:
Add environment-specific values for
resource_group_name
,location
, andvm_software
in each file.dev.tfvars
:resource_group_name = "dev-resource-group" location = "East US" vm_software = "nginx"
prod.tfvars
:resource_group_name = "prod-resource-group" location = "West US" vm_software = "apache2"
Create
variables.tf
:- Define the variables for
resource_group_name
,location
, andvm_software
invariables.tf
:variable "resource_group_name" { description = "The name of the resource group" type = string } variable "location" { description = "The location for the resources" type = string } variable "vm_software" { description = "The software to install on the VM" type = string }
- Define the variables for
Save All Variable Files.
#
Step 2: Define the Virtual Machine Configuration in main.tf
Open or Create
main.tf
:- In your project directory, create or open a
main.tf
file to define the VM configuration.
- In your project directory, create or open a
Add a Virtual Machine Resource with Provisioners:
- Define the Azure VM resource, using a
remote-exec
provisioner to install software based on the environment. - Example configuration:
resource "azurerm_virtual_machine" "example" { name = "example-vm" location = var.location resource_group_name = var.resource_group_name network_interface_ids = [azurerm_network_interface.example.id] vm_size = terraform.workspace == "prod" ? "Standard_DS2_v2" : "Standard_DS1_v2" storage_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "18.04-LTS" version = "latest" } os_profile { computer_name = "examplevm" admin_username = "adminuser" admin_password = "P@ssw0rd123!" } os_profile_linux_config { disable_password_authentication = false } # Provisioner to install different software based on environment provisioner "remote-exec" { connection { type = "ssh" host = self.public_ip_address user = "adminuser" password = "P@ssw0rd123!" } inline = [ "sudo apt-get update", "sudo apt-get install -y ${var.vm_software}" ] } }
- The
vm_size
parameter dynamically changes based on the workspace, and thevm_software
variable installs different software based on the environment.
- Define the Azure VM resource, using a
Save
main.tf
.
#
Step 3: Set Up Networking Resources (if needed)
- Define Network Interface and Public IP:
- Ensure that the VM has a network interface and a public IP to allow SSH access for the provisioner.
- Example:
resource "azurerm_network_interface" "example" { name = "example-nic" location = var.location resource_group_name = var.resource_group_name ip_configuration { name = "internal" subnet_id = azurerm_subnet.example.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.example.id } } resource "azurerm_public_ip" "example" { name = "example-pip" location = var.location resource_group_name = var.resource_group_name allocation_method = "Static" }
#
Step 4: Initialize and Configure Workspaces for Dev and Prod
Initialize the Project:
- Run
terraform init
to download provider plugins and prepare the environment:terraform init
- Run
Create and Switch to the Development Workspace:
- In the terminal, create the dev workspace and switch to it:
terraform workspace new dev
- In the terminal, create the dev workspace and switch to it:
Create the Production Workspace:
- Create another workspace for production:
terraform workspace new prod
- Create another workspace for production:
Verify Current Workspace:
- Run
terraform workspace show
to confirm your current workspace.
- Run
#
Step 5: Run Terraform Commands for Each Environment
Run
terraform plan
for Development Environment:- In the dev workspace, use
terraform plan
withdev.tfvars
to preview the changes:terraform plan -var-file="dev.tfvars"
- In the dev workspace, use
Run
terraform apply
for Development Environment:- Apply the configuration to deploy the VM with Nginx in the development environment:
terraform apply -var-file="dev.tfvars"
- Type
yes
to confirm.
- Apply the configuration to deploy the VM with Nginx in the development environment:
Switch to Production Workspace:
- Switch to the production workspace:
terraform workspace select prod
- Switch to the production workspace:
Run
terraform plan
andterraform apply
for Production Environment:- Run
terraform plan
andterraform apply
withprod.tfvars
to deploy the VM with Apache in the production environment:terraform plan -var-file="prod.tfvars" terraform apply -var-file="prod.tfvars"
- Confirm the deployment by typing
yes
when prompted.
- Run
#
Verification
Check the Azure Portal:
- Go to the Azure Portal and navigate to the resource groups for each environment (
dev-resource-group
andprod-resource-group
). - Verify that VMs have been created in each environment with the correct size (based on workspace).
- Go to the Azure Portal and navigate to the resource groups for each environment (
Verify Software Installation:
- Connect to each VM via SSH and confirm the installed software:
- For dev, verify Nginx:
ssh adminuser@<DEV_VM_PUBLIC_IP> systemctl status nginx
- For prod, verify Apache:
ssh adminuser@<PROD_VM_PUBLIC_IP> systemctl status apache2
- For dev, verify Nginx:
- Connect to each VM via SSH and confirm the installed software:
Confirm Dynamic Configuration:
- Verify that the VM size and software installation vary based on the workspace (dev or prod).