Infrastructure as Code
Infrastructure as Code (IaC) is the practice of managing and provisioning computing infrastructure through configuration files instead of manual processes.
What is IaC?
IaC is the process of managing and provisioning computing infrastructure through configuration files that can be versioned, reused, and shared.
IaC Benefits
Automation
- **Automated deployment": Infrastructure deployed automatically
- **Consistency": Consistent configuration across environments
- **Reproducibility": Same infrastructure in different environments
- **Efficiency": Reduced deployment time
Version Control
- **Versioning": Infrastructure version control
- **Rollback": Ability to revert changes
- **History": Change traceability
- **Collaboration": Multiple developers working together
Security
- **Secure configuration": Secure configuration by default
- **Audit": Change traceability
- **Compliance": Regulatory compliance
- **Validation": Configuration validation
- **Multi-cloud": Support for multiple providers
- **State": Infrastructure state management
- **Plan": Change planning
- **Apply": Change application
Ansible
- **Agentless": No agents required
- **YAML": YAML configuration
- **Idempotency": Idempotent execution
- **Orchestration": Task orchestration
- **AWS native": Native AWS service
- **JSON/YAML": JSON or YAML configuration
- **Stacks": Stack management
- **Drift detection": Drift detection
Pulumi
- **Multi-language": Multiple programming languages
- **Real-time": Real-time updates
- **Testing": Testing capabilities
- **CI/CD": CI/CD integration
Basic Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| # main.tf
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1d0"
instance_type = "t3.micro"
tags = {
Name = "Web Server"
Environment = "production"
}
}
resource "aws_security_group" "web_sg" {
name_prefix = "web-"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
|
Modules
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| # modules/web-server/main.tf
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t3.micro"
}
variable "environment" {
description = "Environment name"
type = string
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
tags = {
Name = "Web Server"
Environment = var.environment
}
}
# modules/web-server/outputs.tf
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.web.id
}
|
Using Modules
1
2
3
4
5
6
7
| # main.tf
module "web_server" {
source = "./modules/web-server"
instance_type = "t3.small"
environment = "production"
}
|
Example with Ansible
Basic Playbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # playbook.yml
---
- name: Configure web server
hosts: web_servers
become: yes
vars:
nginx_port: 80
tasks:
- name: Install nginx
package:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: yes
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
|
Inventory
1
2
3
4
5
6
7
| # inventory.ini
[web_servers]
web1 ansible_host=10.0.1.10
web2 ansible_host=10.0.1.11
[db_servers]
db1 ansible_host=10.0.2.10
|
Security in IaC
Secure Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # Secure S3 configuration
resource "aws_s3_bucket" "secure_bucket" {
bucket = "my-secure-bucket"
versioning {
enabled = true
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
public_access_block {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
}
|
Secret Management
1
2
3
4
5
6
7
8
9
10
| # Using secrets
resource "aws_db_instance" "database" {
identifier = "my-database"
engine = "mysql"
username = var.db_username
password = var.db_password
vpc_security_group_ids = [aws_security_group.db.id]
}
|
Validation
1
2
3
4
5
6
7
8
9
10
| # Input validation
variable "instance_type" {
description = "EC2 instance type"
type = string
validation {
condition = contains(["t3.micro", "t3.small", "t3.medium"], var.instance_type)
error_message = "Instance type must be t3.micro, t3.small, or t3.medium."
}
}
|
Best Practices
Project Structure
project/
βββ main.tf
βββ variables.tf
βββ outputs.tf
βββ terraform.tfvars
βββ modules/
β βββ web-server/
β βββ main.tf
β βββ variables.tf
β βββ outputs.tf
βββ environments/
βββ dev/
βββ staging/
βββ production/
Versioning
- **Git": Use Git for version control
- **Tags": Tag versions
- **Branches": Use branches for different environments
- **Commits": Descriptive commit messages
Testing
- **Unit tests": Unit tests
- **Integration tests": Integration tests
- **Security tests": Security tests
- **Compliance tests": Compliance tests
CI/CD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # .github/workflows/terraform.yml
name: Terraform
on:
push:
branches: [main]
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Terraform Init
run: terraform init
- name: Terraform Plan
run: terraform plan
- name: Terraform Apply
run: terraform apply -auto-approve
|
Monitoring and Auditing
Logs
- **Terraform logs": Execution logs
- **Cloud logs": Cloud provider logs
- **Application logs": Application logs
- **Security logs": Security logs
Metrics
- **Deployment time": Deployment time
- **Success rate": Success rate
- **Error rate": Error rate
- **Resource usage": Resource usage
Alerts
- **Deployment failures": Deployment failures
- **Configuration drift": Configuration drift
- **Security issues": Security issues
- **Performance issues": Performance issues
References