DevOps Journey
Core Concepts

Infrastructure as Code

Infrastructure as Code concepts and tools

Infrastructure as Code

Infrastructure as Code (IaC) is the process of managing infrastructure through code instead of manual configuration.

What is Infrastructure as Code?

IaC:

  • Defines infrastructure in code files
  • Version controls infrastructure
  • Enables automated provisioning
  • Makes infrastructure reproducible
  • Treats infrastructure like application code

Benefits

  1. Reproducibility - Same infrastructure every time
  2. Version Control - Track changes to infrastructure
  3. Documentation - Code documents infrastructure
  4. Automation - Deploy rapidly and consistently
  5. Collaboration - Team can review and discuss changes
  6. Testing - Validate infrastructure before deployment
  7. Cost Control - Spin up/down resources easily
  8. Disaster Recovery - Rebuild infrastructure quickly

IaC Approaches

Declarative (Desired State)

"Tell me what you want, I'll figure out how to get there"

# Terraform (Declarative)
resource "aws_instance" "web" {
    ami = "ami-0c94855ba95c574c8"
    instance_type = "t2.micro"
    tags = {
        Name = "web-server"
    }
}

Benefits: Idempotent, easier to understand

Imperative (How-To)

"Tell me the steps to get there"

#!/bin/bash
# Ansible (Imperative)
ansible-playbook playbook.yml

Benefits: More control, explicit

Terraform

Open-source IaC tool by HashiCorp

# main.tf
terraform {
    required_providers {
        aws = {
            source = "hashicorp/aws"
            version = "~> 4.0"
        }
    }
}

provider "aws" {
    region = "us-east-1"
}

resource "aws_instance" "example" {
    ami = "ami-0c94855ba95c574c8"
    instance_type = "t2.micro"
}

output "instance_ip" {
    value = aws_instance.example.public_ip
}

CloudFormation

AWS native IaC tool

AWSTemplateFormatVersion: "2010-09-09"

Resources:
    MyInstance:
        Type: AWS::EC2::Instance
        Properties:
            ImageId: ami-0c94855ba95c574c8
            InstanceType: t2.micro
            Tags:
                - Key: Name
                  Value: my-instance

Ansible

Agentless configuration management

# playbook.yml
---
- hosts: all
  tasks:
      - name: Install packages
        apt:
            name: "{{ item }}"
            state: present
        loop:
            - nginx
            - docker.io

      - name: Start nginx
        systemd:
            name: nginx
            state: started
            enabled: yes

IaC Workflow

Development

  1. Write infrastructure code
  2. Test locally
  3. Commit to version control
  4. Code review

Deployment

  1. Plan changes (what will be created/modified)
  2. Review plan
  3. Apply changes
  4. Monitor deployment

Example Terraform Workflow

# Initialize Terraform
terraform init

# Format code
terraform fmt

# Validate syntax
terraform validate

# Plan changes
terraform plan -out=tfplan

# Review plan
cat tfplan

# Apply changes
terraform apply tfplan

# Destroy resources
terraform destroy

Infrastructure Components with IaC

Virtual Machines

resource "aws_instance" "web_server" {
    ami = data.aws_ami.ubuntu.id
    instance_type = "t2.micro"
    subnet_id = aws_subnet.main.id
    security_groups = [aws_security_group.web.id]
}

Networks

resource "aws_vpc" "main" {
    cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "public" {
    vpc_id = aws_vpc.main.id
    cidr_block = "10.0.1.0/24"
}

Load Balancers

resource "aws_lb" "main" {
    name = "main-lb"
    internal = false
    load_balancer_type = "application"
    subnets = aws_subnet.public[*].id
}

Databases

resource "aws_db_instance" "default" {
    allocated_storage = 20
    engine = "mysql"
    engine_version = "5.7"
    instance_class = "db.t2.micro"
    db_name = "mydb"
}

Version Control

# Initialize git repo
git init

# Add infrastructure code
git add *.tf

# Commit changes
git commit -m "Add production infrastructure"

# Create branch for new feature
git checkout -b add-autoscaling

# Push changes
git push origin main

Best Practices

  1. Version Control Everything

    • Keep IaC in git
    • Branch for changes
    • Code review before merge
  2. Modular Design

    • Separate concerns
    • Reusable modules
    • DRY (Don't Repeat Yourself)
  3. Document Code

    • Comments explaining why
    • README with examples
    • Changelog tracking modifications
  4. Security

    • Don't hardcode secrets
    • Use environment variables
    • Implement principle of least privilege
  5. Testing

    • Plan before applying
    • Test in development first
    • Automated testing where possible
  6. State Management

    • Use remote state (Terraform Cloud, S3)
    • Enable state locking
    • Backup state files
  7. Naming Conventions

    • Consistent naming
    • Descriptive resource names
    • Environment indicators

Common Pitfalls

  1. Hardcoded Values

    • Use variables instead
    • Create reusable configurations
  2. Missing Documentation

    • Document infrastructure decisions
    • Explain complex configurations
  3. No Version Control

    • Always use git
    • Track all changes
  4. Manual Changes

    • Avoid manual infrastructure changes
    • Everything through code
  5. Insufficient Monitoring

    • Monitor infrastructure
    • Alert on issues
    • Track metrics

Real-World Example

# Production infrastructure
terraform {
    required_version = ">= 1.0"
    backend "s3" {
        bucket = "terraform-state"
        key = "prod/terraform.tfstate"
        region = "us-east-1"
        encrypt = true
    }
}

provider "aws" {
    region = var.aws_region
}

module "vpc" {
    source = "./modules/vpc"
    cidr_block = var.vpc_cidr
    environment = var.environment
}

module "web_servers" {
    source = "./modules/web_servers"
    vpc_id = module.vpc.vpc_id
    instance_count = var.instance_count
    instance_type = var.instance_type
}

output "load_balancer_ip" {
    value = module.web_servers.lb_ip
    description = "Public IP of load balancer"
}

On this page