What better way to learn a new skill than to practice? Terraform is easily the best IaC application. Using it, I've created and deployed Azure resources like Kubernetes clusters, Active Directory and Security groups, CI/CD solutions using Azure DevOps, and Virtual Machine instances. It has been super easy to learn!
Terraform is similar to Azure Resource Management (ARM) templates, which I am familiar with and have completed a couple projects using it. However, Terraform is useful as it allows you to configure infrastructure across multiple cloud platforms. Most companies don't just use one cloud providers as one might have a resource that better than the other and vice versa. For example, Azure Active Directory is the arguably the best solution for identity and access management while AWS can be a better solution for IaaS. This is where Terraform comes in handy!
General Steps
Creating resources and solutions using Terraform is pretty straightforward. Each solution was deployed using these steps.
1.Create the respective providers, main, variables, outputs files, and service principal credentials.
- providers: specifies cloud provider used
- main: specifies the parameters for my resources
- variables: specifies the variables for our parameters like the resource group location. These are parameter values that start with var in my main file.
- outputs: specifies output variables
- service principal credentials: specifies my service principal app id and password as I choose to use a least privilege model to protect my subscriptions and its resources
2.Using Azure CloudShell, I created and applied my Terraform execution plan.
terraform plan -out main.tfplan
terraform apply main.tfplan
3.Test the results!
Note: code are only samples of what was used and resources have additional parameters that were included in my Terraform files. You can find the complete code in my Github repo.
End to End Governance (Azure DevOps and Terraform)
In this project, designed an end to end governance solution for a scenario where a construction company called Kay Inc is working on the construction of a new hospital.
Kay Inc has various departments: Structural Design, Project Management, and IT (or superadmins). Each department has:
- a team that develops solutions to make some aspects of the department more efficient. For example, a function application that automatically uploads published drawings from the design team to a Cosmos DB to be used and tracked by the project management dept.
- an admin team that creates and manages management groups, subscriptions, RBAC, Policies, etc.
Active Directory and IAM: I created three Active Directory groups for each department: a group for the entire department and two separate groups for the developer team with DevOps and ARM Contributor roles and admin team with ARM Owner and DevOps Project Administrator roles. The IT department only has one AD group with "superadmin" privileges.
The construction project is broken down into 5 projects groups: one for each department, one for the entire company, and a collaborative space.
To implement my solution, I...
I created a DevOps Organization and PAT to configure the environment then created the DevOps projects, AD group assignments, and service connections for the company.
1. Configuring the AD groups
resource "azuread_group" "groups" {
for_each = var.groups
display_name = "kayinc-${each.value}-${local.suffix}"
prevent_duplicate_names = true
security_enabled = true
}
2. Configuring the DevOps projects and enabling their necessary features
resource "azuredevops_project" "team_projects" {
for_each = var.projects
name = each.value.name
description = each.value.description
visibility = "private"
version_control = "Git"
features = {
repositories = "enabled"
pipelines = "enabled"
artifacts = "disabled"
boards = "disabled"
testplans = "disabled"
}
}
3. Configuring Security Group Assignments for each project with their assigned permissions and dependencies
module "ado_team_permissions" {
for_each = var.projects
source = "./modules/azure-devops-permissions"
ado_project_id = azuredevops_project.team_projects["${each.value.team}"].id
team_aad_id = azuread_group.groups["${each.value.team}_devs"].id # Receives 'Contributor' Permissions
admin_aad_id = azuread_group.groups["${each.value.team}_admins"].id # Receives 'Project Administrator' Permissions
depends_on = [
azuread_group.groups,
azuredevops_project.team_projects
]
}
Creating a Kubernetes cluster using AKS
In this task, I created a AKS cluster and configured Container Insights to manage my Kubernetes environment using Terraform.
1. Create an AKS cluster specifying node pool parameters including the number of nodes
resource "azurerm_kubernetes_cluster" "k8s" {
location = azurerm_resource_group.rg.location
name = var.cluster_name
resource_group_name = azurerm_resource_group.rg.name
dns_prefix = var.dns_prefix
tags = {
Environment = "Development"
}
default_node_pool {
name = "agentpool"
vm_size = "Standard_D2_v2"
node_count = var.agent_count
}
2. Configure Container Insights to monitor the health and performance of my cluster
resource "azurerm_log_analytics_solution" "test" {
location = azurerm_log_analytics_workspace.test.location
resource_group_name = azurerm_resource_group.rg.name
solution_name = "ContainerInsights"
workspace_name = azurerm_log_analytics_workspace.test.name
workspace_resource_id = azurerm_log_analytics_workspace.test.id
plan {
product = "OMSGallery/ContainerInsights"
publisher = "Microsoft"
}
}
Virtual Machine Scale Sets from a custom Packer image
Azure Virtual Machine Scale Sets automate the deployment of Virtual Machine instances based on specified parameters to decrease latency and increase availability.
1. Configuring the VM image by creating a resource group, service principal, and the Packer template file to a Packer image.
az group create -n kayPackerimages -l eastus
az ad sp create-for-rbac --role Contributor --scopes /subscriptions/kayssub1234 --query "{client_id: appId, client_secret: password, tenant_id: tenant }"
packer build ubuntu.json
Packer image file is a json file that include my Azure credentials, os type, image sku and location, etc.
2. Create a Virtual Network, subnet, and loadbalancer
resource "azurerm_virtual_network" "vmss" {
name = "vmss-vnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = azurerm_resource_group.vmss.name
tags = var.tags
}
resource "azurerm_subnet" "vmss" {
name = "vmss-subnet"
resource_group_name = azurerm_resource_group.vmss.name
virtual_network_name = azurerm_virtual_network.vmss.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_lb" "vmss" {
name = "vmss-lb"
location = var.location
resource_group_name = azurerm_resource_group.vmss.name
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = azurerm_public_ip.vmss.id
}
tags = var.tags
}
2. Create my virtual machine using the Packer image
data "azurerm_image" "image" {
name = var.packer_image_name
resource_group_name = data.azurerm_resource_group.image.name
}
Of course I did not start with these more complicated tasks. I first practiced configuring simple solutions like:
- an Azure CosmosDB
- Azure Virtual Machines
- resource groups
Top comments (0)