infra-as-code
使用代码定义和管理云基础设施。在编写 Terraform、CloudFormation 或 Pulumi 配置、管理状态、规划部署、设置网络/计算/存储资源或调试基础设施漂移时使用。
安装 / 下载方式
TotalClaw CLI推荐
totalclaw skills install shop:totalclaw:totalclaw~gitgoodordietrying-infra-as-codecURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~gitgoodordietrying-infra-as-code/file -o gitgoodordietrying-infra-as-code.md## 概述(中文)
使用代码定义和管理云基础设施。在编写 Terraform、CloudFormation 或 Pulumi 配置、管理状态、规划部署、设置网络/计算/存储资源或调试基础设施漂移时使用。
## 原文
# Infrastructure as Code
Define, deploy, and manage cloud infrastructure using declarative configuration. Covers Terraform (multi-cloud), AWS CloudFormation, and Pulumi (code-first), with patterns for compute, networking, storage, databases, and state management.
## When to Use
- Setting up cloud infrastructure (VPCs, EC2, Lambda, S3, RDS, etc.)
- Writing or modifying Terraform configurations
- Managing Terraform state (remote backends, workspaces, imports)
- Creating CloudFormation templates
- Using Pulumi for infrastructure in TypeScript/Python/Go
- Planning and previewing infrastructure changes safely
- Debugging drift between declared state and actual resources
- Setting up multi-environment deployments (dev/staging/prod)
## Terraform
### Quick Start
```bash
# Install: https://developer.hashicorp.com/terraform/install
# Initialize a project
mkdir infra && cd infra
terraform init
# Core workflow
terraform plan # Preview changes (safe, read-only)
terraform apply # Apply changes (creates/modifies resources)
terraform destroy # Tear down all resources
# Format and validate
terraform fmt -recursive # Auto-format all .tf files
terraform validate # Check syntax and config validity
```
### Project Structure
```
infra/
main.tf # Primary resources
variables.tf # Input variable declarations
outputs.tf # Output values
providers.tf # Provider configuration
terraform.tfvars # Variable values (don't commit secrets)
backend.tf # Remote state configuration
modules/
vpc/
main.tf
variables.tf
outputs.tf
compute/
main.tf
variables.tf
outputs.tf
```
### Provider Configuration
```hcl
# providers.tf
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
}
```
### Variables and Outputs
```hcl
# variables.tf
variable "aws_region" {
type = string
default = "us-east-1"
description = "AWS region for all resources"
}
variable "environment" {
type = string
description = "Deployment environment"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
variable "instance_type" {
type = string
default = "t3.micro"
}
variable "db_password" {
type = string
sensitive = true
description = "Database password (pass via TF_VAR_db_password env var)"
}
# outputs.tf
output "vpc_id" {
value = aws_vpc.main.id
description = "VPC ID"
}
output "api_endpoint" {
value = aws_lb.api.dns_name
}
```
### VPC + Networking
```hcl
# Networking module
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = { Name = "${var.project_name}-vpc" }
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = { Name = "${var.project_name}-public-${count.index + 1}" }
}
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 10}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = { Name = "${var.project_name}-private-${count.index + 1}" }
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}
resource "aws_route_table_association" "public" {
count = 2
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
resource "aws_security_group" "web" {
name_prefix = "${var.project_name}-web-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
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"]
}
}
data "aws_availability_zones" "available" {
state = "available"
}
```
### Compute (EC2)
```hcl
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
subnet_id = aws_subnet.public[0].id
vpc_security_group_ids = [aws_security_group.web.id]
key_name = var.key_pair_name
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y docker.io
systemctl start docker
docker run -d -p 80:8080 ${var.docker_image}
EOF
tags = { Name = "${var.project_name}-app" }
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-24.04-amd64-server-*"]
}
}
```
### S3 + Static Website
```hcl
resource "aws_s3_bucket" "website" {
bucket = "${var.project_name}-website"
}
resource "aws_s3_bucket_website_configuration" "website" {
bucket = aws_s3_bucket.website.id
index_document { suffix = "index.html" }
error_document { key = "error.html" }
}
resource "aws_s3_bucket_public_access_block" "website" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_policy" "website" {
bucket = aws_s3_bucket.website.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "PublicRead"
Effect = "Allow"
Principal = "*"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.website.arn}/*"
}]
})
depends_on = [aws_s3_bucket_public_access_block.website]
}
```
### RDS Database
```hcl
resource "aws_db_subnet_group" "main" {
name = "${var.project_name}-db"
subnet_ids = aws_subnet.private[*].id
}
resource "aws_security_group" "db" {
name_prefix = "${var.project_name}-db-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.web.id]
}
}
resource "aws_db_instance" "main" {
identifier = "${var.project_name}-db"
engine = "postgres"
engine_version = "16.1"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = var.db_name
username = var.db_username
password = var.db_password
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.db.id]
backup_retention_period = 7
skip_final_snapshot = var.environment != "prod"
deletion_protection = var.environment == "prod"
}
```
### Lambda Function
```hcl
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/lambda"
output_path = "${path.module}/lambda.zip"
}
resource "aws_lambda_function" "api" {
function_name = "${var.project_name}-api"
filename = data.archive_file.lambda_zip.output_path
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
handler = "index.handler"
runtime = "nodejs20.x"
timeout = 30
role = aws_iam_role.lambda_exec.arn
environment {
variables = {
DB_HOST = aws_db_instan