Terraform 状态命令 #

状态命令概述 #

Terraform 提供了一系列命令来管理状态文件,这些命令允许你查看、修改和操作状态。

text
┌─────────────────────────────────────────────────────────────┐
│                    状态命令                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  terraform state list      列出状态中的资源                 │
│  terraform state show      显示资源详情                     │
│  terraform state mv        移动/重命名资源                   │
│  terraform state rm        从状态中移除资源                  │
│  terraform state pull      拉取远程状态                      │
│  terraform state push      推送状态到远程                    │
│  terraform import          导入已有资源                      │
│  terraform taint           标记资源为需重建                  │
│  terraform untaint         取消标记                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

terraform state list #

列出所有资源 #

bash
terraform state list

输出:

text
aws_instance.example
aws_security_group.web
aws_subnet.public[0]
aws_subnet.public[1]
aws_vpc.main

过滤资源 #

bash
terraform state list aws_instance

输出:

text
aws_instance.example
aws_instance.web[0]
aws_instance.web[1]

使用通配符 #

bash
terraform state list 'aws_subnet.*'

输出:

text
aws_subnet.public[0]
aws_subnet.public[1]
aws_subnet.private[0]

terraform state show #

显示资源详情 #

bash
terraform state show aws_instance.example

输出:

text
# aws_instance.example:
resource "aws_instance" "example" {
    ami                          = "ami-0c55b159cbfafe1f0"
    arn                          = "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0"
    associate_public_ip_address  = true
    availability_zone            = "us-east-1a"
    cpu_core_count               = 1
    cpu_threads_per_core         = 1
    id                           = "i-1234567890abcdef0"
    instance_state               = "running"
    instance_type                = "t2.micro"
    private_ip                   = "10.0.1.10"
    public_ip                    = "54.123.45.67"
    subnet_id                    = "subnet-12345678"
    tags                         = {
        "Name" = "example-instance"
    }
    vpc_security_group_ids       = [
        "sg-12345678",
    ]
}

显示模块资源 #

bash
terraform state show module.vpc.aws_vpc.main

terraform state mv #

重命名资源 #

bash
terraform state mv aws_instance.example aws_instance.web_server

移动到模块 #

bash
terraform state mv aws_instance.example module.web.aws_instance.main

批量移动 #

bash
terraform state mv 'aws_instance.web[*]' 'module.web.aws_instance.web[*]'

使用 moved 块 #

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

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

移动场景 #

text
┌─────────────────────────────────────────────────────────────┐
│                    移动场景                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 重命名资源                                             │
│     aws_instance.old -> aws_instance.new                   │
│                                                             │
│  2. 移动到模块                                             │
│     aws_instance.web -> module.web.aws_instance.main       │
│                                                             │
│  3. 重组代码结构                                           │
│     重新组织模块和资源                                     │
│                                                             │
│  注意:                                                    │
│  - 移动后需要更新配置文件                                  │
│  - 使用 moved 块更安全                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

terraform state rm #

移除单个资源 #

bash
terraform state rm aws_instance.example

移除多个资源 #

bash
terraform state rm 'aws_instance.web[*]'

移除模块 #

bash
terraform state rm module.vpc

移除场景 #

text
┌─────────────────────────────────────────────────────────────┐
│                    移除场景                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 不再管理资源                                           │
│     - 从 Terraform 管理中移除                              │
│     - 资源不会被删除                                       │
│                                                             │
│  2. 资源已被手动删除                                       │
│     - 清理状态文件中的无效引用                             │
│                                                             │
│  3. 迁移到其他配置                                         │
│     - 从当前状态移除                                       │
│     - 在新配置中导入                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

terraform state pull #

拉取状态 #

bash
terraform state pull > terraform.tfstate

查看远程状态 #

bash
terraform state pull | jq '.resources[] | select(.type=="aws_instance")'

terraform state push #

推送状态 #

bash
terraform state push terraform.tfstate

强制推送 #

bash
terraform state push -force terraform.tfstate

terraform import #

导入资源 #

bash
terraform import aws_instance.example i-1234567890abcdef0

导入到模块 #

bash
terraform import module.vpc.aws_vpc.main vpc-12345678

导入带 count 的资源 #

bash
terraform import 'aws_instance.web[0]' i-1234567890abcdef0

导入带 for_each 的资源 #

bash
terraform import 'aws_instance.web["server1"]' i-1234567890abcdef0

使用配置块导入 #

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

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

批量导入 #

hcl
import {
  to = aws_instance.web[0]
  id = "i-1234567890abcdef0"
}

import {
  to = aws_instance.web[1]
  id = "i-0987654321fedcba0"
}

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

resource "aws_instance" "web" {
  count = 2
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

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

导入流程 #

text
┌─────────────────────────────────────────────────────────────┐
│                    导入流程                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 创建资源配置                                           │
│     resource "aws_instance" "example" { }                  │
│                                                             │
│  2. 执行导入命令                                           │
│     terraform import aws_instance.example i-xxx            │
│                                                             │
│  3. 验证导入结果                                           │
│     terraform state show aws_instance.example              │
│                                                             │
│  4. 补充配置参数                                           │
│     添加必要的配置参数                                     │
│                                                             │
│  5. 验证配置                                               │
│     terraform plan 应该没有变更                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

常见导入示例 #

bash
terraform import aws_vpc.main vpc-12345678

terraform import aws_subnet.public subnet-12345678

terraform import aws_security_group.web sg-12345678

terraform import aws_s3_bucket.logs my-logs-bucket

terraform import aws_db_instance.main my-database

terraform import aws_lb.main arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/1234567890abcdef

terraform taint #

标记资源 #

bash
terraform taint aws_instance.example

标记模块资源 #

bash
terraform taint module.web.aws_instance.main

标记效果 #

bash
terraform plan

输出:

text
# aws_instance.example is tainted, so must be replaced
-/+ resource "aws_instance" "example" {
    ...
}

使用场景 #

text
┌─────────────────────────────────────────────────────────────┐
│                    taint 使用场景                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 资源状态异常                                           │
│     - 配置正确但运行状态有问题                             │
│     - 需要重建资源                                         │
│                                                             │
│  2. 强制更新                                               │
│     - 需要重新创建资源                                     │
│     - 触发依赖资源更新                                     │
│                                                             │
│  3. 测试重建流程                                           │
│     - 验证重建流程是否正常                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

terraform untaint #

取消标记 #

bash
terraform untaint aws_instance.example

取消模块资源标记 #

bash
terraform untaint module.web.aws_instance.main

terraform state replace-provider #

替换 Provider #

bash
terraform state replace-provider hashicorp/aws custom/aws

批量替换 #

bash
terraform state replace-provider \
  -auto-approve \
  registry.terraform.io/-/aws \
  registry.terraform.io/hashicorp/aws

状态管理最佳实践 #

1. 操作前备份 #

bash
terraform state pull > backup.tfstate

terraform state mv aws_instance.old aws_instance.new

2. 使用 moved 块 #

hcl
moved {
  from = aws_instance.old
  to   = aws_instance.new
}

3. 验证变更 #

bash
terraform state mv aws_instance.old aws_instance.new

terraform plan

4. 分步操作 #

bash
terraform state list

terraform state show aws_instance.example

terraform state mv aws_instance.example aws_instance.web

5. 记录操作 #

bash
terraform state mv aws_instance.old aws_instance.new >> state-operations.log

故障排除 #

状态锁定错误 #

text
Error: Error acquiring the state lock

解决方案:

bash
terraform force-unlock <LOCK_ID>

资源不存在 #

text
Error: Invalid resource address

解决方案:

bash
terraform state list
terraform state rm <invalid-resource>

状态损坏 #

text
Error: State locked by another

解决方案:

bash
terraform state pull > backup.tfstate

terraform state push -force backup.tfstate

下一步 #

掌握了状态命令后,接下来学习 模块基础,了解如何使用模块组织和复用配置!

最后更新:2026-03-29