Terraform 远程状态 #
什么是远程状态? #
远程状态允许将 Terraform 状态文件存储在远程位置,而不是本地文件系统。这使得团队协作、状态共享和状态安全变得更加容易。
text
┌─────────────────────────────────────────────────────────────┐
│ 远程状态的优势 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 团队协作 │ │ 状态锁定 │ │ 安全存储 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ - 多人共享同一状态 │
│ - 防止并发操作冲突 │
│ - 加密存储敏感信息 │
│ - 自动备份和版本控制 │
│ │
└─────────────────────────────────────────────────────────────┘
后端类型 #
标准后端 #
text
┌─────────────────────────────────────────────────────────────┐
│ 标准后端 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 云存储: │
│ ├── S3 AWS S3 │
│ ├── GCS Google Cloud Storage │
│ ├── Azure Blob Azure Blob Storage │
│ └── OSS Alibaba Cloud OSS │
│ │
│ 服务: │
│ ├── Terraform Cloud HashiCorp 托管服务 │
│ ├── Consul HashiCorp Consul │
│ ├── etcd etcd 键值存储 │
│ └── HTTP HTTP 后端 │
│ │
│ 数据库: │
│ ├── PostgreSQL PostgreSQL 数据库 │
│ └── MySQL MySQL 数据库 │
│ │
└─────────────────────────────────────────────────────────────┘
增强后端 #
text
┌─────────────────────────────────────────────────────────────┐
│ 增强后端 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Terraform Cloud / Enterprise │
│ - 远程操作 │
│ - 状态管理 │
│ - 变量管理 │
│ - 运行历史 │
│ - 策略执行 │
│ │
└─────────────────────────────────────────────────────────────┘
S3 后端 #
基本配置 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
完整配置 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
kms_key_id = "alias/terraform-state-key"
dynamodb_table = "terraform-state-lock"
acl = "private"
workspace_key_prefix = "environments"
skip_metadata_api_check = false
}
}
配置参数 #
text
┌─────────────────────────────────────────────────────────────┐
│ S3 后端参数 │
├─────────────────────────────────────────────────────────────┤
│ │
│ bucket S3 存储桶名称 │
│ key 状态文件路径 │
│ region AWS 区域 │
│ encrypt 启用加密 │
│ kms_key_id KMS 密钥 ID │
│ dynamodb_table DynamoDB 表(状态锁定) │
│ acl 访问控制列表 │
│ workspace_key_prefix 工作空间前缀 │
│ │
└─────────────────────────────────────────────────────────────┘
创建 S3 后端资源 #
hcl
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-terraform-state"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.terraform_state.id
}
}
}
resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_dynamodb_table" "terraform_state_lock" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
resource "aws_kms_key" "terraform_state" {
description = "Terraform state encryption key"
deletion_window_in_days = 10
enable_key_rotation = true
}
Azure Blob 后端 #
基本配置 #
hcl
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate12345"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}
完整配置 #
hcl
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate12345"
container_name = "tfstate"
key = "prod.terraform.tfstate"
subscription_id = "00000000-0000-0000-0000-000000000000"
tenant_id = "00000000-0000-0000-0000-000000000000"
use_azuread_auth = true
}
}
GCS 后端 #
基本配置 #
hcl
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
}
}
完整配置 #
hcl
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
credentials = "service-account.json"
encryption = "google-managed"
}
}
Terraform Cloud 后端 #
配置 #
hcl
terraform {
cloud {
organization = "my-organization"
workspaces {
name = "my-workspace"
}
}
}
多工作空间 #
hcl
terraform {
cloud {
organization = "my-organization"
workspaces {
tags = ["networking", "production"]
}
}
}
Consul 后端 #
hcl
terraform {
backend "consul" {
address = "consul.example.com:8500"
scheme = "https"
path = "terraform/state/prod"
lock = true
}
}
PostgreSQL 后端 #
hcl
terraform {
backend "pg" {
conn_str = "postgres://user:pass@db.example.com/terraform_state"
schema_name = "terraform"
}
}
HTTP 后端 #
hcl
terraform {
backend "http" {
address = "https://example.com/state/my-project"
lock_address = "https://example.com/lock/my-project"
unlock_address = "https://example.com/unlock/my-project"
username = "user"
password = "pass"
}
}
后端配置方法 #
1. 直接配置 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
2. 部分配置 #
hcl
terraform {
backend "s3" {}
}
bash
terraform init \
-backend-config="bucket=my-terraform-state" \
-backend-config="key=prod/terraform.tfstate" \
-backend-config="region=us-east-1"
3. 配置文件 #
创建 backend.hcl:
hcl
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
bash
terraform init -backend-config=backend.hcl
4. 环境变量 #
bash
export TF_CLI_ARGS_init="-backend-config=backend.hcl"
terraform init
状态锁定 #
自动锁定 #
大多数远程后端支持自动状态锁定:
text
┌─────────────────────────────────────────────────────────────┐
│ 状态锁定流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. terraform apply 开始 │
│ 2. 获取状态锁 │
│ 3. 执行操作 │
│ 4. 更新状态 │
│ 5. 释放状态锁 │
│ │
│ 如果锁已被占用: │
│ Error: Error acquiring the state lock │
│ │
└─────────────────────────────────────────────────────────────┘
S3 + DynamoDB 锁定 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-lock"
}
}
手动解锁 #
bash
terraform force-unlock <LOCK_ID>
状态隔离 #
按环境隔离 #
text
┌─────────────────────────────────────────────────────────────┐
│ 环境隔离 │
├─────────────────────────────────────────────────────────────┤
│ │
│ S3 存储桶结构: │
│ my-terraform-state/ │
│ ├── dev/ │
│ │ └── terraform.tfstate │
│ ├── staging/ │
│ │ └── terraform.tfstate │
│ └── prod/ │
│ └── terraform.tfstate │
│ │
│ 每个环境独立的状态文件 │
│ │
└─────────────────────────────────────────────────────────────┘
按组件隔离 #
text
┌─────────────────────────────────────────────────────────────┐
│ 组件隔离 │
├─────────────────────────────────────────────────────────────┤
│ │
│ my-terraform-state/ │
│ ├── networking/ │
│ │ └── terraform.tfstate │
│ ├── compute/ │
│ │ └── terraform.tfstate │
│ └── database/ │
│ └── terraform.tfstate │
│ │
│ 每个组件独立的状态文件 │
│ │
└─────────────────────────────────────────────────────────────┘
读取远程状态 #
terraform_remote_state 数据源 #
hcl
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_instance" "example" {
subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}
输出引用 #
hcl
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "network/terraform.tfstate"
region = "us-east-1"
}
}
locals {
vpc_id = data.terraform_remote_state.network.outputs.vpc_id
subnet_ids = data.terraform_remote_state.network.outputs.subnet_ids
}
迁移状态 #
从本地迁移到远程 #
bash
terraform init -migrate-state
更换后端 #
bash
terraform init -migrate-state
强制迁移 #
bash
terraform init -migrate-state -force-copy
最佳实践 #
1. 启用版本控制 #
hcl
resource "aws_s3_bucket_versioning" "state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
2. 启用加密 #
hcl
resource "aws_s3_bucket_server_side_encryption_configuration" "state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.state.id
}
}
}
3. 阻止公开访问 #
hcl
resource "aws_s3_bucket_public_access_block" "state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
4. 使用状态锁定 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-lock"
}
}
5. 分离状态文件 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
}
}
下一步 #
掌握了远程状态后,接下来学习 状态命令,了解如何使用 Terraform 状态管理命令!
最后更新:2026-03-29