Terraform与已部署Cognito资源不同步问题咨询
问题背景
我遇到了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
我的疑问
- 能否忽略或跳过Cognito资源?因需保护用户数据,我不想修改该服务。
- 如何排查差异原因并在不销毁用户池的情况下解决问题?
解决方案
问题1:忽略/跳过Cognito资源的几种方法
这里有三个不同层级的方案,你可以根据自己的需求选择:
临时跳过该资源执行计划/应用
如果只是想在本次操作中跳过Cognito用户池,只处理其他资源,可以使用-target参数指定要操作的资源:terraform plan -target=aws_s3_bucket.your_other_bucket terraform apply -target=aws_s3_bucket.your_other_bucket这样Terraform只会处理你指定的资源,完全忽略Cognito用户池的差异。
让Terraform忽略该资源的特定字段变化
如果你还想让Terraform继续管理这个用户池,但忽略schema字段的差异,可以在资源块中添加lifecycle配置:resource "aws_cognito_user_pool" "my_app" { # 你的所有原有配置... lifecycle { ignore_changes = [schema] } }配置后,Terraform会忽略
schema字段的任何差异,不会再提示重建用户池,同时依然会管理其他字段(比如tags、password_policy等)。彻底移除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的处理有不少已知问题)。
按以下步骤排查修复:
确认AWS控制台的实际配置
先登录AWS控制台,找到你的Cognito User Pool,进入Attributes页面,查看custom1字段的实际配置:- 确认数据类型是String
- 确认Mutable选项是勾选的(即true)
- 确认字段名称确实是custom1
如果控制台的配置和你代码里一致,那肯定是Terraform Provider读取状态的问题。
升级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看看差异是否消失。手动修正Terraform状态文件
如果升级Provider后问题依然存在,可以手动修正状态文件(操作前一定要备份状态文件!):- 导出状态文件:
terraform state pull > state-backup.json - 打开
state-backup.json,找到aws_cognito_user_pool.my_app对应的schema部分,把错误的字段修正为和控制台一致的值:attribute_data_type设为"String"mutable设为truename设为"custom1"string_attribute_constraints.#设为1
- 导入修正后的状态文件:
terraform state push state-backup.json
之后再跑terraform plan,应该就不会有差异了。
- 导出状态文件:
调整代码中schema块的顺序
老版本的Terraform对重复块的顺序比较敏感,可能会因为哈希计算导致状态中的schema索引和代码不匹配。你可以尝试调整代码中三个schema块的顺序(比如把custom1移到email前面),然后执行terraform refresh,看看是否能解决差异问题。
内容的提问来源于stack exchange,提问作者cyram

