Terraform RDS:由于修改而销毁后恢复数据?

Terraform RDS: Restore data after destroy due to modification?

我正在尝试使用 Terraform 在 AWS 中创建一个 RDS Aurora MySQL 集群。但是,我注意到每当我以需要更换集群的方式更改集群时,所有数据都会丢失。我已配置为拍摄最终快照并希望从该快照恢复,或通过替代措施恢复原始数据。

示例:更改集群 -> TF 销毁原集群 -> TF 替换为新集群 -> 从原集群恢复数据

我曾尝试对 aws_rds_cluster.snapshot_identifieraws_rds_cluster.final_snapshot_identifier 使用相同的快照标识符,但 Terraform 失败了,因为被破坏集群的最终快照尚不存在。

我也曾尝试使用 rds-finalsnapshot 模块,但事实证明它主要用于上下旋转环境,保存数据。即销毁整个集群,然后将其重新创建为单独部署的一部分。 (模块:https://registry.terraform.io/modules/connect-group/rds-finalsnapshot/aws/latest

module "snapshot_maintenance" {
  source="connect-group/rds-finalsnapshot/aws//modules/rds_snapshot_maintenance"    
  identifier                    = local.cluster_identifier
  is_cluster                    = true
  database_endpoint             = element(aws_rds_cluster_instance.cluster_instance.*.endpoint, 0)
  number_of_snapshots_to_retain = 3
}

resource "aws_rds_cluster" "provisioned_cluster" {
  cluster_identifier                  = module.snapshot_maintenance.identifier
  engine                              = "aurora-mysql"
  engine_version                      = "5.7.mysql_aurora.2.10.0"
  port                                = 1234
  database_name                       = "example" 
  master_username                     = "example"
  master_password                     = "example"
  iam_database_authentication_enabled = true 
  storage_encrypted                   = true
  backup_retention_period             = 2
  db_subnet_group_name                = "example"
  skip_final_snapshot                 = false
  final_snapshot_identifier           = module.snapshot_maintenance.final_snapshot_identifier
  snapshot_identifier                 = module.snapshot_maintenance.snapshot_to_restore 
  vpc_security_group_ids              = ["example"]
    
}

我发现如果更改需要销毁和重新创建,我没有很好的方法将数据恢复为同一部署的一部分。

我要补充一点,我认为这不是我的代码的问题。它更像是 TF 的生命周期限制。我相信我不会是唯一一个想要在 TF 确定必须重新创建集群的情况下保留集群中数据的人。

如果我想防止由于更改导致销毁的集群而导致数据丢失,我是否需要在 Terraform 之外或通过 cli 销毁集群,同步 Terraform 的状态然后应用?

解决方案最终变得相当简单,尽管晦涩难懂。我尝试了 50 多种不同的方法,将现有资源属性、供应商、空资源(带触发器)和外部数据块与 AWS CLI 命令和 Powershell 脚本结合使用。

这里的挑战是我需要确保按此顺序进行配置以确保不会丢失数据:

  1. 阻止 DMS 复制任务将更多数据复制到数据库中。
  2. 在传入数据停止后,拍摄集群的新快照。
  3. 销毁并重新创建集群,使用 snapshot_identifier 指定在上一步中拍摄的快照。
  4. 销毁并重新创建 DMS 任务。

当然,这些步骤是基于 Terraform 决定它需要应用更新的方式。它可能会确定它只需要执行就地更新;这不是我关心的。我需要处理资源被破坏的情况。

最终的解决方案是消除外部数据块的使用并专门使用本地供应商,因为即使只有 运行ning terraform plan,外部数据块也会执行。我使用本地供应器来利用“创建”和“销毁”等生命周期事件,以确保我的 Powershell 脚本仅在 terraform apply.

期间执行

在我的集群上,我将 final_snapshot_identifiersnapshot_identifier 设置为相同的值。

final_snapshot_identifier           = local.snapshot_identifier
snapshot_identifier    = data.external.check_for_first_run.result.isFirstRun == "true" ? null : local.snapshot_identifier

snapshot_identifier 仅在第一次部署后设置,外部数据块允许我检查资源是否已经存在以实现条件。该条件是必要的,因为在第一次部署时,快照将不存在,并且 Terraform 将因此在“规划”步骤期间失败。

然后我在“销毁”上的本地配置程序中执行 Powershell 脚本以停止任何 DMS 任务,然后删除名为 local.snapshot_identifier 的快照。

  provisioner "local-exec" {
    when    = destroy
     # First, stop the inflow of data to the cluster by stopping the dms tasks.  
     # Next, we've tricked TF into thinking the snapshot we want to use is there by using the same name for old and new snapshots, but before we destroy the cluster, we need to delete the original.
     # Then TF will create the final snapshot immediately following the execution of the below script and it will be used to restore the cluster since we've set it as snapshot_identifier.
    command = "/powershell_scripts/stop_dms_tasks.ps1; aws rds delete-db-cluster-snapshot --db-cluster-snapshot-identifier benefitsystem-cluster"
    interpreter = ["PowerShell"]
  }

这会清除最后一个快照,并允许 Terraform 创建一个与原始快照同名的新最终快照,以便及时用于从中恢复。

现在,我可以 运行 首次进行 Terraform 并获得一个全新的集群。所有后续部署都将使用最终快照进行恢复并保留数据。