Terraform 资源管理 #

什么是资源? #

资源(Resource)是 Terraform 配置中最重要的组成部分,用于描述基础设施对象,如虚拟机、网络、存储等。每个资源块描述一个或多个基础设施对象。

text
┌─────────────────────────────────────────────────────────────┐
│                    资源结构                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  resource "<PROVIDER>_<TYPE>" "<NAME>" {                    │
│    <CONFIG>                                                 │
│  }                                                          │
│                                                             │
│  示例:                                                     │
│  resource "aws_instance" "web_server" {                     │
│    ami           = "ami-0c55b159cbfafe1f0"                  │
│    instance_type = "t2.micro"                               │
│  }                                                          │
│                                                             │
│  组成:                                                     │
│  - PROVIDER: aws                                            │
│  - TYPE: instance                                           │
│  - NAME: web_server                                         │
│  - CONFIG: 配置参数                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

资源语法 #

基本语法 #

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "example-instance"
  }
}

资源地址 #

text
<资源类型>.<资源名称>

aws_instance.example
aws_security_group.web
aws_subnet.public

资源引用 #

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.public.id
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
}

output "instance_ip" {
  value = aws_instance.example.public_ip
}

资源生命周期 #

生命周期阶段 #

text
┌─────────────────────────────────────────────────────────────┐
│                    资源生命周期                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐              │
│  │  Create  │ -> │  Update  │ -> │  Delete  │              │
│  │  创建    │    │  更新    │    │  删除    │              │
│  └──────────┘    └──────────┘    └──────────┘              │
│                                                             │
│  创建:资源不存在时创建新资源                                │
│  更新:资源存在但配置发生变化                                │
│  删除:资源从配置中移除                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

生命周期配置 #

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  lifecycle {
    create_before_destroy = true
    prevent_destroy       = false
    ignore_changes        = [tags]
    replace_triggered_by  = [aws_security_group.example.id]
  }
}

create_before_destroy #

hcl
lifecycle {
  create_before_destroy = true
}
text
┌─────────────────────────────────────────────────────────────┐
│                    创建后销毁模式                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  默认模式:                                                 │
│  销毁旧资源 → 创建新资源                                    │
│  (可能导致服务中断)                                       │
│                                                             │
│  create_before_destroy 模式:                               │
│  创建新资源 → 销毁旧资源                                    │
│  (减少服务中断时间)                                       │
│                                                             │
│  适用场景:                                                 │
│  - 需要最小化停机时间                                       │
│  - 资源有依赖关系                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

prevent_destroy #

hcl
lifecycle {
  prevent_destroy = true
}

防止资源被意外销毁,当执行 terraform destroy 时会报错。

ignore_changes #

hcl
lifecycle {
  ignore_changes = [
    tags,
    instance_type,
  ]
}

忽略指定属性的变更:

hcl
lifecycle {
  ignore_changes = [
    tags["Environment"],
  ]
}

lifecycle {
  ignore_changes = all
}

replace_triggered_by #

hcl
resource "aws_security_group" "example" {
  name = "example-sg"
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  lifecycle {
    replace_triggered_by = [
      aws_security_group.example.id
    ]
  }
}

资源依赖 #

隐式依赖 #

hcl
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"
}

resource "aws_instance" "web" {
  subnet_id = aws_subnet.public.id
  ami       = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

Terraform 自动检测依赖关系:

text
aws_vpc.main
    │
    └── aws_subnet.public
            │
            └── aws_instance.web

显式依赖 #

hcl
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  depends_on = [
    aws_security_group.web
  ]
}

resource "aws_security_group" "web" {
  name = "web-sg"
}

depends_on 使用场景 #

hcl
resource "aws_s3_bucket" "logs" {
  bucket = "my-logs-bucket"
}

resource "aws_iam_role_policy" "instance_policy" {
  name = "instance-policy"
  role = aws_iam_role.instance.id
  
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = ["s3:PutObject"]
        Effect = "Allow"
        Resource = "${aws_s3_bucket.logs.arn}/*"
      }
    ]
  })
}

resource "aws_instance" "app" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  iam_instance_profile = aws_iam_instance_profile.app.name
  
  depends_on = [
    aws_iam_role_policy.instance_policy
  ]
}

资源元参数 #

count #

hcl
resource "aws_instance" "server" {
  count = 3
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "Server ${count.index + 1}"
  }
}

访问 count 创建的资源:

hcl
output "instance_ids" {
  value = aws_instance.server[*].id
}

output "first_instance_ip" {
  value = aws_instance.server[0].public_ip
}

使用 count 条件创建:

hcl
resource "aws_instance" "server" {
  count = var.create_instance ? 1 : 0
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

for_each #

hcl
variable "servers" {
  default = {
    web = {
      instance_type = "t2.micro"
      name          = "Web Server"
    }
    api = {
      instance_type = "t2.small"
      name          = "API Server"
    }
    db = {
      instance_type = "t2.medium"
      name          = "Database Server"
    }
  }
}

resource "aws_instance" "server" {
  for_each = var.servers
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = each.value.instance_type
  
  tags = {
    Name = each.value.name
  }
}

访问 for_each 创建的资源:

hcl
output "instance_ids" {
  value = {
    for k, v in aws_instance.server : k => v.id
  }
}

output "web_instance_ip" {
  value = aws_instance.server["web"].public_ip
}

count vs for_each #

text
┌─────────────────────────────────────────────────────────────┐
│                    count vs for_each                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  count:                                                    │
│  - 创建相同类型的多个资源                                   │
│  - 资源通过索引访问                                        │
│  - 删除中间元素会影响后续索引                               │
│                                                             │
│  for_each:                                                 │
│  - 创建有差异的多个资源                                     │
│  - 资源通过键访问                                          │
│  - 删除元素不影响其他资源                                   │
│                                                             │
│  推荐:需要创建多个相似资源时优先使用 for_each              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

provider #

hcl
provider "aws" {
  region = "us-east-1"
  alias  = "east"
}

provider "aws" {
  region = "us-west-2"
  alias  = "west"
}

resource "aws_instance" "east_server" {
  provider = aws.east
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

resource "aws_instance" "west_server" {
  provider = aws.west
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

资源行为 #

创建行为 #

text
┌─────────────────────────────────────────────────────────────┐
│                    资源创建                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 检查状态文件,确认资源不存在                            │
│  2. 调用 Provider API 创建资源                              │
│  3. 获取资源属性                                            │
│  4. 更新状态文件                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

更新行为 #

text
┌─────────────────────────────────────────────────────────────┐
│                    资源更新                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  就地更新(In-place update):                              │
│  - 修改资源属性而不重建                                     │
│  - 如修改 tags                                             │
│                                                             │
│  重建更新(Destroy and create):                           │
│  - 必须删除旧资源,创建新资源                               │
│  - 如修改 ami、instance_type                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

删除行为 #

text
┌─────────────────────────────────────────────────────────────┐
│                    资源删除                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 检查依赖关系                                           │
│  2. 按依赖顺序删除                                         │
│  3. 调用 Provider API 删除资源                             │
│  4. 从状态文件中移除                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

资源导入 #

导入现有资源 #

bash
terraform import aws_instance.example i-1234567890abcdef0

导入配置 #

hcl
resource "aws_instance" "example" {
  
}
bash
terraform import aws_instance.example i-1234567890abcdef0

批量导入 #

hcl
import {
  to = aws_instance.example
  id = "i-1234567890abcdef0"
}

import {
  to = aws_security_group.web
  id = "sg-1234567890abcdef0"
}

resource "aws_instance" "example" {
  
}

resource "aws_security_group" "web" {
  
}

资源标记 #

taint 标记 #

bash
terraform taint aws_instance.example

terraform plan
terraform apply

untaint 取消标记 #

bash
terraform untaint aws_instance.example

使用场景 #

text
┌─────────────────────────────────────────────────────────────┐
│                    taint 使用场景                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  - 资源配置正确但运行状态异常                               │
│  - 需要重建资源以应用某些变更                               │
│  - 测试重建流程                                            │
│                                                             │
│  注意:taint 不会立即重建资源,需要在下次 apply 时重建      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

资源定位 #

移动资源 #

bash
terraform state mv aws_instance.old aws_instance.new

在配置中使用 moved 块:

hcl
resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

moved {
  from = aws_instance.example
  to   = aws_instance.web_server
}

删除资源(从状态中移除) #

bash
terraform state rm aws_instance.example

资源最佳实践 #

命名规范 #

hcl
resource "aws_instance" "web_server" {
  
}

resource "aws_security_group" "web_alb" {
  
}

resource "aws_s3_bucket" "log_storage" {
  
}

使用标签 #

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = merge(
    var.common_tags,
    {
      Name = "example-instance"
      Type = "web-server"
    }
  )
}

模块化 #

hcl
module "web_server" {
  source = "./modules/ec2"
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  subnet_id     = module.vpc.public_subnet_id
}

文档注释 #

hcl
resource "aws_instance" "web_server" {
  
  ami           = var.ami_id
  instance_type = var.instance_type
  
  user_data = <<-EOF
    #!/bin/bash
    # Install and configure web server
    yum install -y httpd
    systemctl start httpd
  EOF
}

下一步 #

掌握了资源管理后,接下来学习 变量,了解如何使用变量使配置更加灵活!

最后更新:2026-03-29