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

Terraform与已部署Cognito资源不同步问题咨询

Terraform与AWS Cognito User Pool状态不一致:跳过资源与修复方案

问题背景

我遇到了Terraform管理的Cognito User Pool和已部署资源不一致的问题:Git记录显示管理该用户池的配置文件自上次部署后完全没修改,但terraform plan却检测到差异,提示需要强制重建这个资源。我使用的版本是Terraform 0.11.7、AWS Provider 1.14.1,因为用户池里有用户数据,绝对不能销毁重建。

我的Terraform配置

resource "aws_cognito_user_pool" "my_app" { 
  name = "My App Pool" 

  /* Fields that can work as aliases */ 
  alias_attributes = [ "email" ] 

  /* Auto-verify these fields */ 
  auto_verified_attributes = [ "email" ] 

  /* This is the template used to verify addresses / accounts */ 
  verification_message_template { 
    default_email_option = "CONFIRM_WITH_CODE" 
  } 

  admin_create_user_config { 
    allow_admin_create_user_only = false 
    invite_message_template { 
      email_message = <<EOF 
{####} 
EOF 
      email_subject = "MyApp" 
      sms_message = "Welcome to MyApp. Your username: {username} and password: {####} Thank you!" 
    } 
  } 

  email_verification_subject = "MyApp's Confirmation Code" 
  email_verification_message = "Your confirmation code: {####} Thank you." 

  password_policy { 
    minimum_length = 8 
    require_lowercase = true 
    require_numbers = true 
    require_symbols = true 
    require_uppercase = true 
  } 

  schema { 
    attribute_data_type = "String" 
    developer_only_attribute = false 
    mutable = true 
    name = "email" 
    required = true 
  } 

  schema { 
    attribute_data_type = "String" 
    developer_only_attribute = false 
    mutable = true 
    name = "custom1" 
    required = false 
  } 

  schema { 
    attribute_data_type = "String" 
    developer_only_attribute = false 
    mutable = true 
    name = "custom2" 
    required = false 
  } 

  tags { 
    "name" = "MyApp" 
    "Project" = "Terraform" 
  } 
} 

Terraform Plan输出

schema.3021841581.attribute_data_type: "String" => "" (forces new resource)
 schema.3021841581.developer_only_attribute: "false" => "false"
 schema.3021841581.mutable: "true" => "false" (forces new resource)
 schema.3021841581.name: "custom1" => "" (forces new resource)
 schema.3021841581.number_attribute_constraints.#: "0" => "0"
 schema.3021841581.required: "false" => "false"
 schema.3021841581.string_attribute_constraints.#: "1" => "0" (forces new resource)
 schema.3021841581.string_attribute_constraints.0.max_length: "" => ""
 schema.3021841581.string_attribute_constraints.0.min_length: "" => ""

Terraform State查看结果

schema.3021841581.attribute_data_type = String
 schema.3021841581.developer_only_attribute = false
 schema.3021841581.mutable = true
 schema.3021841581.name = custom1
 schema.3021841581.number_attribute_constraints.# = 0
 schema.3021841581.required = false
 schema.3021841581.string_attribute_constraints.# = 1

我的疑问

  1. 能否忽略或跳过Cognito资源?因需保护用户数据,我不想修改该服务。
  2. 如何排查差异原因并在不销毁用户池的情况下解决问题?

解决方案

问题1:忽略/跳过Cognito资源的几种方法

这里有三个不同层级的方案,你可以根据自己的需求选择:

  1. 临时跳过该资源执行计划/应用
    如果只是想在本次操作中跳过Cognito用户池,只处理其他资源,可以使用-target参数指定要操作的资源:

    terraform plan -target=aws_s3_bucket.your_other_bucket
    terraform apply -target=aws_s3_bucket.your_other_bucket
    

    这样Terraform只会处理你指定的资源,完全忽略Cognito用户池的差异。

  2. 让Terraform忽略该资源的特定字段变化
    如果你还想让Terraform继续管理这个用户池,但忽略schema字段的差异,可以在资源块中添加lifecycle配置:

    resource "aws_cognito_user_pool" "my_app" {
      # 你的所有原有配置...
    
      lifecycle {
        ignore_changes = [schema]
      }
    }
    

    配置后,Terraform会忽略schema字段的任何差异,不会再提示重建用户池,同时依然会管理其他字段(比如tags、password_policy等)。

  3. 彻底移除Terraform对该资源的管理
    如果你确定以后不再用Terraform管理这个用户池,可以把它从状态文件中移除:

    terraform state rm aws_cognito_user_pool.my_app
    

    执行后,Terraform就会完全忘记这个资源,不会再检测它的差异。但要注意:以后如果想重新用Terraform管理,需要用terraform import导入,而且要确保不会误操作删除它。


问题2:排查差异原因并修复(不销毁用户池)

从你提供的plan和state输出来看,差异集中在custom1这个schema字段上——Terraform错误地认为该字段的mutable变为false、attribute_data_type和name为空,还有string_attribute_constraints的数量变化。这大概率是老版本AWS Provider的bug导致的(你用的1.14.1是非常旧的版本,对Cognito schema的处理有不少已知问题)。

按以下步骤排查修复:

  1. 确认AWS控制台的实际配置
    先登录AWS控制台,找到你的Cognito User Pool,进入Attributes页面,查看custom1字段的实际配置:

    • 确认数据类型是String
    • 确认Mutable选项是勾选的(即true)
    • 确认字段名称确实是custom1
      如果控制台的配置和你代码里一致,那肯定是Terraform Provider读取状态的问题。
  2. 升级AWS Provider版本
    Terraform 0.11虽然比较老,但可以升级到兼容的最新AWS Provider版本(最高支持到AWS Provider 2.70.0左右)。修改你的provider "aws"配置,指定更高的版本:

    provider "aws" {
      version = "~> 1.60.0" # 这个版本兼容Terraform 0.11,且修复了很多Cognito的bug
      region  = "your-region"
    }
    

    然后执行terraform init -upgrade升级Provider,之后再跑terraform plan看看差异是否消失。

  3. 手动修正Terraform状态文件
    如果升级Provider后问题依然存在,可以手动修正状态文件(操作前一定要备份状态文件!):

    • 导出状态文件:terraform state pull > state-backup.json
    • 打开state-backup.json,找到aws_cognito_user_pool.my_app对应的schema部分,把错误的字段修正为和控制台一致的值:
      • attribute_data_type设为"String"
      • mutable设为true
      • name设为"custom1"
      • string_attribute_constraints.#设为1
    • 导入修正后的状态文件:terraform state push state-backup.json
      之后再跑terraform plan,应该就不会有差异了。
  4. 调整代码中schema块的顺序
    老版本的Terraform对重复块的顺序比较敏感,可能会因为哈希计算导致状态中的schema索引和代码不匹配。你可以尝试调整代码中三个schema块的顺序(比如把custom1移到email前面),然后执行terraform refresh,看看是否能解决差异问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:09:21