You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform S3 Bucket加密配置反复移除再添加问题求助

问题:Terraform管理S3桶加密配置反复被移除/添加

每次执行terraform apply后,S3桶的服务器端加密配置会被移除,再次执行apply又会重新添加。无代码变更时执行terraform plan,会显示要移除aws_s3_bucket.terraform-state内的server_side_encryption_configuration块,下次执行则会添加回来。

Terraform Plan 输出

# aws_s3_bucket.terraform-state will be updated in-place
  ~ resource "aws_s3_bucket" "terraform-state" {
        id                          = "company-terraform-state"
        tags                        = {}
        # (11 unchanged attributes hidden)

      - server_side_encryption_configuration {
          - rule {
              - bucket_key_enabled = false -> null

              - apply_server_side_encryption_by_default {
                  - kms_master_key_id = "arn:aws:kms:us-east-1:123456789012:key/Random-GUID-ABCD-1234" -> null
                  - sse_algorithm     = "aws:kms" -> null
                }
            }
        }

        # (1 unchanged block hidden)
    }

相关配置文件(state.tf)

// This file is based on the writtings here: https://technology.doximity.com/articles/terraform-s3-backend-best-practices
terraform {
  backend "s3" {
    bucket         = "company-terraform-state"
    key            = "state/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    kms_key_id     = "alias/terraform-bucket-key"
    dynamodb_table = "terraform-state"
  }
}
// The backend configuration above is added after the state s3 bucket is created with the rest of the file below

resource "aws_kms_key" "terraform-bucket-key" {
  description             = "This key is used to encrypt bucket objects for terraform state"
  deletion_window_in_days = 10
  enable_key_rotation     = true
}

resource "aws_kms_alias" "key-alias" {
  name          = "alias/terraform-bucket-key"
  target_key_id = aws_kms_key.terraform-bucket-key.key_id
}

resource "aws_s3_bucket" "terraform-state" {
  bucket = "company-terraform-state"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "encryption-config" {
  bucket = aws_s3_bucket.terraform-state.id
  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.terraform-bucket-key.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.terraform-state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_acl" "acl" {
  bucket = aws_s3_bucket.terraform-state.id
  acl    = "private"
}

resource "aws_s3_bucket_public_access_block" "block" {
  bucket = aws_s3_bucket.terraform-state.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

// This table exists to prevent multiple team members from modifying the state file at the same time
resource "aws_dynamodb_table" "terraform-state" {
  name           = "terraform-state"
  read_capacity  = 20
  write_capacity = 20
  hash_key       = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

解决方案

这个问题的根源是Terraform的AWS Provider会读取S3桶的实际属性(包括加密配置)到状态中,但你的代码里aws_s3_bucket资源未定义server_side_encryption_configuration块,同时又用独立的aws_s3_bucket_server_side_encryption_configuration资源管理加密,导致Terraform每次plan时都会认为该块是多余的要移除,而实际API中的配置由独立资源维护,下次plan又会被读取回来,形成循环变更。

有两种可行的解决方法:

方法1:在S3桶资源中声明空的加密配置块

修改aws_s3_bucket.terraform-state资源,添加空的server_side_encryption_configuration块,明确告诉Terraform忽略该属性的状态差异,由独立资源负责管理:

resource "aws_s3_bucket" "terraform-state" {
  bucket = "company-terraform-state"

  # 显式声明空块,避免Terraform检测到API返回的加密配置后试图移除
  server_side_encryption_configuration {}
}

方法2:将加密配置内嵌到S3桶资源中

删除独立的aws_s3_bucket_server_side_encryption_configuration.encryption-config资源,把加密配置直接写入aws_s3_bucket资源内部:

resource "aws_s3_bucket" "terraform-state" {
  bucket = "company-terraform-state"

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = aws_kms_key.terraform-bucket-key.arn
        sse_algorithm     = "aws:kms"
      }
    }
  }
}

两种方法都能解决循环变更问题,推荐方法1,符合Terraform对S3资源的模块化管理最佳实践。

内容的提问来源于stack exchange,提问作者Fir3Chi3f

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:50:24