Claude
Skills
Sign in
Back

terraform-infrastructure-as-code

Included with Lifetime
$97 forever

Comprehensive Terraform Infrastructure as Code skill covering resources, modules, state management, workspaces, providers, and advanced patterns for cloud-agnostic infrastructure deployment

Infrastructureterraforminfrastructure-as-codeclouddevopsautomationawsazuregcp

What this skill does


# Terraform Infrastructure as Code - Comprehensive Guide

## Table of Contents

1. [Introduction to Terraform](#introduction-to-terraform)
2. [Core Concepts](#core-concepts)
3. [Resources](#resources)
4. [Data Sources](#data-sources)
5. [Variables and Outputs](#variables-and-outputs)
6. [Modules](#modules)
7. [State Management](#state-management)
8. [Workspaces](#workspaces)
9. [Provider Configuration](#provider-configuration)
10. [Advanced Features](#advanced-features)
11. [Dependencies](#dependencies)
12. [Provisioners](#provisioners)
13. [Best Practices](#best-practices)
14. [CI/CD Integration](#cicd-integration)

## Introduction to Terraform

Terraform is an open-source Infrastructure as Code (IaC) tool created by HashiCorp that enables you to define and provision infrastructure using a declarative configuration language called HashiCorp Configuration Language (HCL). Terraform manages external resources such as public cloud infrastructure, private cloud infrastructure, network appliances, and software as a service.

### Key Benefits

- **Declarative Configuration**: Define what your infrastructure should look like, not how to create it
- **Cloud-Agnostic**: Works with multiple cloud providers and services
- **Version Control**: Infrastructure code can be versioned and reviewed
- **Plan Before Apply**: Preview changes before applying them
- **Resource Graph**: Automatically manages dependencies between resources
- **State Management**: Tracks the current state of your infrastructure

### Terraform Workflow

```bash
# Initialize Terraform working directory
terraform init

# Initialize and upgrade provider versions
terraform init -upgrade

# Initialize with backend configuration
terraform init -backend-config="bucket=my-state-bucket"

# Generate a plan
terraform plan

# Save plan to file for later apply
terraform plan -out=tfplan

# Plan with specific variable values
terraform plan -var="region=us-west-2" -var="instance_type=t2.micro"

# Apply with interactive approval
terraform apply

# Auto-approve without confirmation
terraform apply -auto-approve

# Apply a saved plan file
terraform apply tfplan

# Destroy with confirmation prompt
terraform destroy

# Auto-approve destruction
terraform destroy -auto-approve
```

## Core Concepts

### 1. Resources

Resources are the most fundamental elements in Terraform. They represent infrastructure objects like virtual machines, networks, databases, or DNS records.

```hcl
# Basic resource declaration
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  tags = {
    Name = "WebServer"
    Environment = "production"
  }
}
```

### 2. Providers

Providers are plugins that allow Terraform to interact with cloud platforms, SaaS providers, and other APIs.

```hcl
# AWS provider configuration
provider "aws" {
  region = "us-west-2"

  default_tags {
    tags = {
      ManagedBy = "Terraform"
      Project   = "MyApp"
    }
  }
}
```

### 3. State

Terraform stores information about your infrastructure in a state file. This state is used to map real-world resources to your configuration and track metadata.

### 4. Configuration Language (HCL)

HCL is designed to be both human-readable and machine-friendly, making it ideal for infrastructure configuration.

## Resources

Resources are the building blocks of Terraform configurations. Each resource block describes one or more infrastructure objects.

### Basic Resource Syntax

```hcl
resource "resource_type" "resource_name" {
  argument1 = "value1"
  argument2 = "value2"

  nested_block {
    nested_argument = "nested_value"
  }
}
```

### Resource Examples

#### AWS EC2 Instance

```hcl
resource "aws_instance" "app_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  key_name      = "my-keypair"

  vpc_security_group_ids = [aws_security_group.app.id]
  subnet_id              = aws_subnet.public.id

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, World!" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF

  tags = {
    Name        = "AppServer"
    Environment = "production"
    ManagedBy   = "Terraform"
  }
}
```

#### AWS VPC

```hcl
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-west-2a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet"
  }
}

resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-west-2a"

  tags = {
    Name = "private-subnet"
  }
}
```

#### AWS S3 Bucket

```hcl
resource "aws_s3_bucket" "data" {
  bucket = "my-app-data-bucket-12345"

  tags = {
    Name        = "Data Bucket"
    Environment = "production"
  }
}

resource "aws_s3_bucket_versioning" "data" {
  bucket = aws_s3_bucket.data.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
  bucket = aws_s3_bucket.data.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}
```

#### AWS Security Group

```hcl
resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group for web servers"
  vpc_id      = aws_vpc.main.id

  ingress {
    description = "HTTP from anywhere"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "HTTPS from anywhere"
    from_port   = 443
    to_port     = 443
    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"]
  }

  tags = {
    Name = "web-security-group"
  }
}
```

### Resource Lifecycle

```hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  lifecycle {
    create_before_destroy = true
    prevent_destroy       = true
    ignore_changes        = [tags]
  }
}
```

**Lifecycle options:**
- `create_before_destroy`: Create new resource before destroying the old one
- `prevent_destroy`: Prevent accidental destruction of resources
- `ignore_changes`: Ignore changes to specified attributes
- `replace_triggered_by`: Force replacement when specific resources change

```hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  lifecycle {
    replace_triggered_by = [
      aws_iam_policy.example.id
    ]
  }
}
```

## Data Sources

Data sources allow Terraform to use information defined outside of Terraform, or defined by another separate Terraform configuration.

### Data Source Syntax

```hcl
data "resource_type" "name" {
  # Query parameters
}
```

### Data Source Examples

```hcl
# Query existing AWS resources
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

# Use data source in resource
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"
}

# Query availability zones
data "aws_availability_zones" "available" {
  state = "available"
}

# Query VPC
data "aws_vpc" "default" {
  default = true
}

# Query remote state
data "terraform_remote_state" "network" {
  backend = "s3"

  config = {
    bucket = "terraform-state"
    key    = "network/terraform.tfstate"
    region = "us-west-2"
  }
}

# Use remote state outputs
resource "aws_instance" "app" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"
  subnet_id     = data.terraform_remote_state.network.outputs.subnet_id

  availability_zon