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
- Reproducibility - Same infrastructure every time
- Version Control - Track changes to infrastructure
- Documentation - Code documents infrastructure
- Automation - Deploy rapidly and consistently
- Collaboration - Team can review and discuss changes
- Testing - Validate infrastructure before deployment
- Cost Control - Spin up/down resources easily
- 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.ymlBenefits: More control, explicit
Popular IaC Tools
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-instanceAnsible
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: yesIaC Workflow
Development
- Write infrastructure code
- Test locally
- Commit to version control
- Code review
Deployment
- Plan changes (what will be created/modified)
- Review plan
- Apply changes
- 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 destroyInfrastructure 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 mainBest Practices
-
Version Control Everything
- Keep IaC in git
- Branch for changes
- Code review before merge
-
Modular Design
- Separate concerns
- Reusable modules
- DRY (Don't Repeat Yourself)
-
Document Code
- Comments explaining why
- README with examples
- Changelog tracking modifications
-
Security
- Don't hardcode secrets
- Use environment variables
- Implement principle of least privilege
-
Testing
- Plan before applying
- Test in development first
- Automated testing where possible
-
State Management
- Use remote state (Terraform Cloud, S3)
- Enable state locking
- Backup state files
-
Naming Conventions
- Consistent naming
- Descriptive resource names
- Environment indicators
Common Pitfalls
-
Hardcoded Values
- Use variables instead
- Create reusable configurations
-
Missing Documentation
- Document infrastructure decisions
- Explain complex configurations
-
No Version Control
- Always use git
- Track all changes
-
Manual Changes
- Avoid manual infrastructure changes
- Everything through code
-
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"
}