LFCA 89 🐧 What Infrastructure as Code Is
Infrastructure as Code (IaC) is the practice of managing and provisioning infrastructure through machine-readable definition files rather than manual configuration or interactive tools. Instead of logging into a server and typing commands, you write a file that describes the desired state of the infrastructure, commit it to version control, and let a tool apply it. The file is the source of truth. The infrastructure is a reflection of the file.
The LFCA exam places IaC under DevOps Fundamentals, which carries 12–16% of the total weight. The study plan lists “Infrastructure as Code” as a core DevOps topic . The exam expects you to understand what IaC is, why it matters, and the principles that make it work.
Key point: IaC treats infrastructure the same way developers treat application code. The infrastructure definitions are stored in version control, reviewed like code, tested before deployment, and deployed through automated pipelines. The infrastructure becomes reproducible: the same configuration produces the same result every time .
Why Infrastructure as Code exists
Before IaC, infrastructure was provisioned manually. An administrator logged into a server, installed packages, edited configuration files, and started services. The process was documented in a runbook — a text file that described the steps. The runbook was often out of date. The person who wrote it was not the person who followed it. The result was inconsistent environments and deployments that failed for reasons no one could reproduce .
The inconsistency problem. Manual provisioning produces drift. Two servers provisioned from the same runbook are not identical. One has a package version that the other does not. One has a firewall rule that the other lacks. The differences accumulate. The environments diverge. The application behaves differently in each one.
The reproducibility problem. A new environment should be a copy of the existing one. With manual provisioning, the new environment is a best-effort approximation. The administrator follows the runbook, but the runbook is incomplete. The gaps are filled with knowledge that lives only in the administrator’s head. When the administrator leaves, the knowledge leaves with them .
The auditability problem. A change is made to the infrastructure. Who made it? When? Why? With manual provisioning, the answers are in the administrator’s memory and the change log of the server. With IaC, the answers are in the commit history. The change is a commit. The author, the timestamp, and the commit message are recorded .
The speed problem. A new server takes hours or days to provision manually. A new environment defined in IaC takes minutes. The tool applies the definition, and the infrastructure is created. The speed is a side effect of the automation .
The trade-off. IaC requires learning the tool. Terraform, Ansible, CloudFormation, and Bicep each have their own syntax, their own model, and their own ecosystem. The learning curve is real. But the alternative — manual provisioning — is a curve that never flattens.
a. Declarative vs Imperative
IaC tools fall into two categories: declarative and imperative. The difference determines how you write the infrastructure definition and how the tool applies it.
Declarative tools ask you to specify what you want. You describe the desired state of the infrastructure — “three web servers, one load balancer, one database” — and the tool figures out how to create it. If the infrastructure already matches the desired state, the tool does nothing. If it differs, the tool makes the changes needed to reach the desired state. The tool is idempotent by design .
Imperative tools ask you to specify how to reach the desired state. You write the steps — “create a server, install nginx, start the service” — and the tool executes them in order. The tool does not know the desired state. It only knows the steps. If the steps are run twice, the result may be duplicated resources or errors .
The two approaches are not mutually exclusive. Many teams use declarative tools for provisioning — Terraform, CloudFormation, Bicep — and imperative tools for configuration — Ansible, shell scripts. The provisioning defines the infrastructure. The configuration defines what runs on it .
| Aspect | Declarative | Imperative |
|---|---|---|
| Specification | What you want | How to get there |
| Idempotency | By design | Manual |
| Examples | Terraform, CloudFormation, Bicep | Ansible, shell scripts |
| Re-run behavior | No-op if state matches | May duplicate or fail |
b. Idempotency
Idempotency is the property that an operation produces the same result regardless of how many times it is executed. Running an idempotent operation once is the same as running it ten times. The infrastructure is in the same state after each execution .
Idempotency is what makes declarative IaC safe. A Terraform apply that creates three servers can be run again. If the three servers exist, Terraform does nothing. If one was deleted, Terraform creates it. The desired state is restored. The operation is safe to repeat.
Idempotency is also what makes imperative IaC fragile. A shell script that creates a user will fail the second time it runs because the user already exists. The script must be written to check whether the user exists before creating it. The check is the developer’s responsibility, not the tool’s.
Why idempotency matters. A deployment fails halfway through. The tool is run again. If the operations are idempotent, the second run completes the deployment. If they are not, the second run may fail or duplicate resources. Idempotency is the property that makes retries safe .
c. The IaC Workflow
The IaC workflow mirrors the software development workflow. The infrastructure definition is code. It goes through the same stages as application code.
Write. The developer writes the infrastructure definition in a file. The file is written in the tool’s language — HCL for Terraform, YAML for CloudFormation and Ansible, TypeScript for AWS CDK.
Version. The file is committed to version control. Git records the change. The commit message explains the why. The history is the audit log .
Review. A pull request is opened. The other developers review the change. They check whether the change is correct, whether it follows the conventions, and whether it has unintended consequences.
Test. The change is validated before deployment. Terraform has terraform plan, which shows what the change will do. CloudFormation has change sets. The tools provide a preview of the changes without applying them .
Deploy. The change is applied. The tool reads the definition, compares it to the current state, and makes the changes needed to reach the desired state. The deployment is automated. The pipeline runs the tool .
Monitor. The infrastructure is monitored. The monitoring detects drift — a change made outside of IaC. The drift is corrected by re-applying the definition. The infrastructure returns to the desired state .
Complete Example Session
This session demonstrates IaC concepts with a simple Terraform configuration and an Ansible playbook.
# ============================================
# PART 1: THE TERRAFORM CONFIGURATION
# ============================================
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web" {
count = 3
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Name = "web-server-${count.index + 1}"
Environment = "production"
}
}
# The configuration is declarative.
# It describes the desired state: three web servers.
# Terraform creates them if they do not exist.
# Terraform does nothing if they already exist.
# ============================================
# PART 2: THE TERRAFORM WORKFLOW
# ============================================
# Initialize the working directory
terraform init
# Preview the changes
terraform plan
# Output:
# Plan: 3 to add, 0 to change, 0 to destroy.
# Apply the changes
terraform apply
# Output:
# Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
# Run again — nothing happens
terraform apply
# Output:
# No changes. Your infrastructure matches the configuration.
# The operation is idempotent.
# ============================================
# PART 3: THE ANSIBLE PLAYBOOK
# ============================================
# playbook.yml
---
- name: Configure web servers
hosts: webservers
become: yes
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: yes
- name: Copy configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted
# The playbook is idempotent.
# Running it twice produces the same result.
# ============================================
# PART 4: THE ANSIBLE RUN
# ============================================
ansible-playbook -i inventory.ini playbook.yml
# Output:
# PLAY [Configure web servers] ***************************
# TASK [Install nginx] ***********************************
# ok: [web1]
# ok: [web2]
# ok: [web3]
# ...
# The "ok" status means no change was needed.
# The playbook is idempotent.
Quick Reference
The IaC Principles
| Principle | Description |
|---|---|
| Version control | Infrastructure definitions stored in Git |
| Automated testing | Changes validated before deployment |
| Continuous monitoring | Infrastructure state tracked and managed |
| Reproducibility | Same configuration produces identical results |
| Idempotency | Same operation produces the same result |
The IaC Tools
| Tool | Type | Language |
|---|---|---|
| Terraform | Declarative | HCL |
| CloudFormation | Declarative | YAML/JSON |
| Bicep | Declarative | Bicep |
| Ansible | Imperative/Declarative | YAML |
| Puppet | Declarative | Puppet DSL |
| Chef | Imperative | Ruby DSL |
| SaltStack | Declarative | YAML |
The Declarative vs Imperative
| Aspect | Declarative | Imperative |
|---|---|---|
| Specification | What you want | How to get there |
| Idempotency | By design | Manual |
| Examples | Terraform, CloudFormation | Ansible, shell |
| Re-run behavior | No-op if state matches | May fail or duplicate |
Best Practices
✅ Do This:
# Store infrastructure definitions in version control
resource "aws_instance" "web" { ... } # ✅
# Preview changes before applying
terraform plan # ✅
# Write idempotent playbooks
- name: Install nginx
apt: { name: nginx, state: present } # ✅
# Use modules for reusable infrastructure
module "web_server" { source = "./modules/web" } # ✅
❌ Don’t Do This:
# Don't provision manually without documenting
ssh server "apt install nginx" # ❌
# Don't hardcode secrets in IaC files
password = "hardcoded" # ❌
# Don't write non-idempotent shell scripts
- shell: useradd alice # fails on second run # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Drift | Manual changes outside IaC | Re-apply the definition |
| State out of sync | State file lost or corrupt | Use remote state backend |
| Secrets in code | Hardcoded credentials | Use a secrets manager |
| Slow apply | Too many resources in one state | Split into smaller states |
Real-World Examples
1. Terraform Resource
resource "aws_instance" "web" { ami = "ami-123" instance_type = "t3.micro" }
2. Terraform Plan
terraform plan
3. Ansible Playbook
- name: Install nginx
apt: { name: nginx, state: present }
4. CloudFormation Template
Resources:
WebServer:
Type: AWS::EC2::Instance
5. Bicep Resource
resource webServer 'Microsoft.Compute/virtualMachines@2023-01-01' = { ... }
6. Idempotent Ansible
- service: { name: nginx, state: started }
7. Terraform Output
output "web_ips" { value = aws_instance.web[*].public_ip }
8. Ansible Inventory
[webservers]
web1 ansible_host=10.0.0.1
9. Terraform Module
module "vpc" { source = "terraform-aws-modules/vpc/aws" }
10. Version Control
git add main.tf && git commit -m "Add web servers"
Visual
The IaC Workflow
┌──────────────────────────────────────────────┐
│ IaC WORKFLOW │
│ │
│ Write ──> Version ──> Review ──> Test │
│ │ │
│ ▼ │
│ Deploy ──> Monitor ──> Correct Drift │
│ │
│ The infrastructure definition is code. │
│ It goes through the same stages as │
│ application code. │
│ │
└──────────────────────────────────────────────┘
Declarative vs Imperative
┌──────────────────────────────────────────────┐
│ DECLARATIVE │
│ "I want three web servers." │
│ Tool creates three if missing. │
│ Tool does nothing if they exist. │
│ │
│ IMPERATIVE │
│ "Create a server. Install nginx." │
│ Tool runs the steps in order. │
│ Running twice may duplicate. │
│ │
└──────────────────────────────────────────────┘
Idempotency
┌──────────────────────────────────────────────┐
│ IDEMPOTENCY │
│ │
│ Run 1: Create server ──> Server exists │
│ Run 2: Create server ──> Server exists │
│ Run 3: Create server ──> Server exists │
│ │
│ The result is the same. │
│ The operation is safe to repeat. │
│ │
└──────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| IaC definition | Managing infrastructure through code |
| Core principle | Infrastructure as version-controlled files |
| Declarative | Specify what you want |
| Imperative | Specify how to get there |
| Idempotency | Same operation, same result |
| Tools | Terraform, CloudFormation, Ansible, Bicep |
| Benefits | Reproducibility, auditability, speed |
| LFCA weight | DevOps Fundamentals, 12–16% |
Key takeaways:
- IaC treats infrastructure the same way developers treat application code. The definitions are stored in version control, reviewed like code, tested before deployment, and deployed through automated pipelines .
- The infrastructure definition is the source of truth. The infrastructure is a reflection of the definition. Changes are made to the definition, not to the infrastructure directly .
- Declarative tools specify what you want; imperative tools specify how to get there. Declarative tools are idempotent by design. Imperative tools require the developer to implement idempotency manually .
- Idempotency makes retries safe. An idempotent operation produces the same result regardless of how many times it is executed. A deployment that fails halfway can be re-run without duplicating resources .
- The workflow mirrors software development. Write, version, review, test, deploy, monitor. The infrastructure definition goes through the same stages as application code .
- The benefits are reproducibility, auditability, and speed. The same configuration produces the same result every time. The commit history is the audit log. The deployment is automated and fast .
- The LFCA exam tests the concepts, not the tools. The exam expects you to understand what IaC is, why it matters, and the principles that make it work. The specific tools are secondary.
Remember: Infrastructure as Code is the practice of managing infrastructure through code. The definition is version-controlled. The deployment is automated. The result is reproducible. The principles are declarative specification, idempotency, and the same rigor as application code. The tools are Terraform, CloudFormation, Ansible, and Bicep. The benefit is infrastructure that is consistent, auditable, and fast to provision.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!