Infrastructure as Code: A Practical Approach
Before continuing with the Key Concept of system desing we need to talk about infrastructure
In the Key concept of system design series we have took the decision of deploying our Discord clone application into the cloud. More specifically to MS Azure.
One aspect I consider key when talking about developing and deploying an application is Infrastructure as code (IaC).
I think it is crucial to touch this aspect before we move on to the deployment view.
IaC is an essential practice in modern software development, especially when working in the cloud. It allows teams to define infrastructure through code rather than manual processes, making environments reproducible, scalable, and maintainable.
In this article, we'll explore what IaC is, the main technologies used to implement it, and why a build pipeline is crucial. We'll also look at key considerations when working with IaC in cloud environments—focusing on Microsoft Azure.
What Is Infrastructure as Code?
IaC is the practice of managing infrastructure (networks, virtual machines, storage, databases, etc.) using machine-readable definition files instead of manual configuration. This approach brings several advantages:
Consistency – Environments can be recreated reliably.
Version Control – Infrastructure changes are tracked like application code.
Automation – Reduces human error and speeds up deployment.
Scalability – Makes it easier to replicate environments across teams and regions.
Declarative vs. Imperative IaC
IaC tools fall into two main categories:
Declarative (e.g., Terraform, Pulumi, Bicep): Define the desired state, and the tool figures out how to get there.
Imperative (e.g., Ansible, PowerShell, Bash scripts): Define step-by-step instructions to configure infrastructure.
While both approaches have their use cases, declarative IaC is generally preferred for cloud environments because it simplifies state management and makes infrastructure changes predictable.
Main Technologies for Implementing IaC
Several technologies are commonly used to define and deploy infrastructure:
Terraform – A widely adopted declarative IaC tool that works across multiple cloud providers.
Bicep – A domain-specific language (DSL) for defining Azure infrastructure, designed as a more readable alternative to ARM templates.
Pulumi – Allows writing IaC using general-purpose programming languages like Python, TypeScript, and Go.
Ansible – Often used for configuration management but can also provision infrastructure in an imperative way.
Cloud-Native Tools – Each cloud provider offers its own IaC tools (e.g., AWS CloudFormation, Azure Resource Manager).
For Azure-focused IaC, Bicep and Terraform are the most common choices.
Why the Build Pipeline Matters
Writing infrastructure code is just the first step. To make IaC truly effective, it should be integrated into a build pipeline that ensures:
Automated validation – Linting, syntax checks, and security scans.
Plan and review processes – Seeing infrastructure changes before applying them (e.g.,
terraform plan
).Safe deployment – Applying changes incrementally and avoiding downtime.
A typical Azure DevOps or GitHub Actions pipeline for Terraform or Bicep would include:
Linting & validation – Checking for syntax errors.
Plan phase – Generating a preview of the changes.
Approval process – Requiring human approval for critical infrastructure updates.
Apply phase – Deploying changes only after approval.
Without a proper pipeline, IaC can become a manual, error-prone process—defeating its purpose.
IaC in Cloud Environments: Why It’s Critical
Cloud providers like Azure offer highly dynamic environments where infrastructure is created, modified, and destroyed frequently. Manually managing cloud resources is neither scalable nor reliable. IaC is essential for:
Managing multiple environments (Dev, Staging, Production) consistently.
Scaling infrastructure dynamically without manual intervention.
Tracking changes in source control instead of relying on ad-hoc modifications.
Disaster recovery by enabling rapid environment restoration.
Example: Provisioning an Azure AKS Cluster with Terraform
To see how IaC simplifies cloud resource management, consider deploying an Azure Kubernetes Service (AKS) cluster using Terraform:
resource "azurerm_resource_group" "example" {
name = "myResourceGroup"
location = "East US"
}
resource "azurerm_kubernetes_cluster" "example" {
name = "myAKSCluster"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
dns_prefix = "myaks"
default_node_pool {
name = "default"
node_count = 2
vm_size = "Standard_DS2_v2"
}
identity {
type = "SystemAssigned"
}
}
This Terraform configuration defines an Azure resource group and an AKS cluster with a default node pool. Running terraform apply
provisions the infrastructure automatically, ensuring consistency across environments.
Key Considerations When Implementing IaC in the Cloud
When using IaC in cloud environments, there are several things to keep in mind:
1. State Management
Terraform stores state files that track deployed resources.
Use remote state backends (e.g., Azure Storage) instead of local files to avoid conflicts.
Enable state locking to prevent concurrent updates.
2. Security Best Practices
Never hardcode secrets in IaC files; use Azure Key Vault.
Apply least privilege principles with managed identities instead of storing credentials in code.
Scan IaC files for security vulnerabilities before applying changes.
3. Modularization & Reusability
Break infrastructure into reusable modules instead of monolithic files.
Define separate IaC configurations for networking, compute, and applications.
Use parameterization to make configurations flexible across environments.
4. Handling Cloud Drift
Cloud environments can change outside of IaC tools (manual updates, API calls).
Regularly run
terraform plan
or equivalent commands to detect drift.Implement policy enforcement (e.g., Azure Policy) to prevent unauthorized changes.
5. Cost Control
IaC makes it easy to spin up resources, but costs can escalate quickly.
Use resource tagging and budget monitoring to track expenses.
Implement automatic resource cleanup for non-production environments.
Infrastructure as Code is a fundamental practice for managing cloud infrastructure efficiently. By using tools like Terraform or Bicep, integrating IaC into a build pipeline, and following best practices, teams can ensure their infrastructure is consistent, scalable, and secure.
When working in cloud environments—especially Azure—careful consideration of state management, security, and cost control is essential. While IaC simplifies many aspects of infrastructure provisioning, it still requires a well-thought-out approach to avoid pitfalls.
If you're not using IaC yet, now is the time to start!
If you like my content enough to pay me a coffee…
Mention ways on how to understand associated costs for the plan generated? Is it possible to estimate them ( keep track on what the change will save and add up)