mcpField
T
terraform-iac-expert

terraform-iac-expert

github.com/curiositech云与 DevOps257165 次安装2 天前更新
代码仓库

关于 terraform-iac-expert

terraform-iac-expert 是面向基础设施工程师的 Terraform 和 OpenTofu 技能,涵盖模块设计、状态管理及多云部署。它也提供多环境、安全实践和 CI/CD 集成方面的指导。

主要功能

  1. 01设计可复用 Terraform 模块
  2. 02配置远程状态与锁定
  3. 03管理多环境基础设施
  4. 04处理状态迁移与漂移
  5. 05规划机密信息和 IAM 安全
  6. 06集成 CI/CD 工作流

适用场景

  1. 01搭建 Terraform 项目结构
  2. 02为开发、预发布和生产环境配置基础设施
  3. 03将现有资源导入状态
  4. 04排查状态漂移或计划失败

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/curiositech/some_claude_skills --skill terraform-iac-expert

安装后在 Claude Code 中输入/terraform-iac-expert确认已加载。

附带文件.claude-plugin/plugin.json

详细介绍

Terraform IaC 专家

概述

精通使用 Terraform 和 OpenTofu 实现基础设施即代码。专长包括模块设计、状态管理、多云部署和 CI/CD 集成。能够处理复杂的基础设施模式,包括多环境配置、远程状态后端和安全的密钥管理。

适用场景

  • 设置新的 Terraform 项目和工作区
  • 设计可复用的 Terraform 模块
  • 管理状态文件和远程后端
  • 实现多环境(开发/预发布/生产)基础设施
  • 将现有基础设施迁移到 Terraform
  • 排查状态漂移和计划失败问题
  • 将 Terraform 集成到 CI/CD 流水线
  • 实施安全最佳实践(密钥、IAM、策略)

能力

项目结构
  • 基于模块的架构设计
  • 工作区与目录结构策略
  • 变量和输出组织
  • Provider 配置和版本约束
  • 远程状态的后端配置
模块开发
  • 可复用的模块模式
  • 输入验证和类型约束
  • 用于模块组合的输出设计
  • 本地模块与 Registry 模块
  • 模块版本管理和发布
状态管理
  • 远程状态后端(S3、GCS、Azure Blob、Terraform Cloud)
  • 状态锁定机制
  • 状态迁移和操作
  • 导入现有资源
  • 处理状态漂移
多环境模式
  • 基于工作区的环境
  • 基于目录的环境
  • 使用 Terragrunt 实现 DRY 基础设施
  • 特定环境的变量
  • 推广工作流
安全
  • 敏感变量处理
  • Terraform 的 IAM 角色设计
  • 策略即代码(Sentinel、OPA)
  • 密钥管理集成(Vault、AWS Secrets Manager)
  • 最小权限原则
CI/CD 集成
  • 使用 GitHub Actions 运行 Terraform
  • 基于 PR 工作流的 Atlantis
  • Terraform Cloud/Enterprise
  • Plan/Apply 自动化
  • 成本估算集成

依赖项

配合以下工具效果良好:

  • aws-solutions-architect - AWS 资源模式
  • kubernetes-orchestrator - K8s 基础设施
  • github-actions-pipeline-builder - CI/CD 自动化
  • site-reliability-engineer - 生产环境基础设施

示例

项目结构
terraform/
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── eks/
│   └── rds/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   ├── staging/
│   └── prod/
└── shared/
    └── provider.tf
含 Locals 的根模块
# environments/prod/main.tf
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket         = "mycompany-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

locals {
  environment = "prod"
  project     = "myapp"

  common_tags = {
    Environment = local.environment
    Project     = local.project
    ManagedBy   = "terraform"
  }
}

module "vpc" {
  source = "../../modules/vpc"

  environment = local.environment
  cidr_block  = "10.0.0.0/16"
  tags        = local.common_tags
}

module "eks" {
  source = "../../modules/eks"

  environment       = local.environment
  vpc_id            = module.vpc.vpc_id
  private_subnet_ids = module.vpc.private_subnet_ids
  cluster_version   = "1.29"
  tags              = local.common_tags
}
带验证的可复用模块
# modules/vpc/variables.tf
variable "environment" {
  type        = string
  description = "Environment name (dev, staging, prod)"

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

variable "cidr_block" {
  type        = string
  description = "VPC CIDR block"

  validation {
    condition     = can(cidrhost(var.cidr_block, 0))
    error_message = "Must be a valid CIDR block."
  }
}

variable "availability_zones" {
  type        = list(string)
  description = "List of AZs to use"
  default     = ["us-west-2a", "us-west-2b", "us-west-2c"]
}

variable "enable_nat_gateway" {
  type        = bool
  description = "Enable NAT Gateway for private subnets"
  default     = true
}

variable "tags" {
  type        = map(string)
  description = "Tags to apply to all resources"
  default     = {}
}
含动态块的模块
# modules/security-group/main.tf
resource "aws_security_group" "this" {
  name        = var.name
  description = var.description
  vpc_id      = var.vpc_id

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
      description = ingress.value.description
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(var.tags, {
    Name = var.name
  })
}
远程状态数据源
# Reference another environment's state
data "terraform_remote_state" "shared" {
  backend = "s3"

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

# Use outputs from shared state
resource "aws_instance" "app" {
  ami           = data.terraform_remote_state.shared.outputs.base_ami_id
  instance_type = "t3.medium"
  subnet_id     = data.terraform_remote_state.shared.outputs.private_subnet_id
}
GitHub Actions CI/CD
# .github/workflows/terraform.yml
name: Terraform

on:
  pull_request:
    paths:
      - 'terraform/**'
  push:
    branches: [main]
    paths:
      - 'terraform/**'

env:
  TF_VERSION: 1.6.0
  AWS_REGION: us-west-2

jobs:
  plan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
      id-token: write  # For OIDC

    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/terraform-github-actions
          aws-region: ${{ env.AWS_REGION }}

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ env.TF_VERSION }}

      - name: Terraform Init
        working-directory: terraform/environments/prod
        run: terraform init

      - name: Terraform Plan
        working-directory: terraform/environments/prod
        run: terraform plan -out=tfplan

      - name: Upload Plan
        uses: actions/upload-artifact@v4
        with:
          name: tfplan
          path: terraform/environments/prod/tfplan

  apply:
    needs: plan
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment: production

    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/terraform-github-actions
          aws-region: ${{ env.AWS_REGION }}

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ env.TF_VERSION }}

      - name: Download Plan
        uses: actions/download-artifact@v4
        with:
          name: tfplan
          path: terraform/environments/prod

      - name: Terraform Apply
        working-directory: terraform/environments/prod
        run: terraform apply -auto-approve tfplan
导入现有资源
# Import existing AWS resource into state
terraform import aws_s3_bucket.existing my-existing-bucket

# Import using for_each key
terraform import 'aws_iam_user.users["alice"]' alice

# Generate configuration from import (Terraform 1.5+)
terraform plan -generate-config-out=generated.tf
处理敏感值
# Reference secrets from AWS Secrets Manager
data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = "prod/db/password"
}

resource "aws_db_instance" "main" {
  # ... other config ...
  password = data.aws_secretsmanager_secret_version.db_password.secret_string
}

# Mark outputs as sensitive
output "db_connection_string" {
  value     = "postgres://admin:${aws_db_instance.main.password}@${aws_db_instance.main.endpoint}"
  sensitive = true
}

最佳实践

  1. 使用远程状态 - 团队项目绝不要将状态存储在本地
  2. 启用状态锁定 - 防止并发修改
  3. 锁定 Provider 版本 - 使用 ~> 约束,而不是 >=
  4. 分离环境 - 使用目录或工作区,而不是分支
  5. 将所有可复用内容模块化 - 但不要过度抽象
  6. 验证输入 - 使用变量验证块
  7. 使用数据源 - 引用现有资源,而不是硬编码
  8. 为所有资源添加标签 - 应用一致的标签以跟踪成本
  9. 仔细审查计划 - 尤其是销毁操作

常见陷阱

  • 状态文件冲突 - 多人同时运行 terraform
  • 硬编码值 - 未使用变量处理环境差异
  • 循环依赖 - 资源之间相互依赖
  • 缺少依赖项 - 隐式依赖不足时未使用 depends_on
  • 状态文件过大 - 未拆分大型基础设施
  • 状态中包含密钥 - 状态中含有敏感值,需在静态存储时加密
  • Provider 版本漂移 - 团队成员使用不同版本
  • 未谨慎使用 -target - 可能导致漂移,应谨慎使用

评论

支持 Markdown