Ansible Cloudformation,如果资源已经存在,如何不中断?

Ansible Cloudformation, how to not break if Resource already exists?

我有以下 AWS Cloudformation 配置,它设置了 S3、存储库。

当我 运行 通过 ansible 剧本时,第二次 运行 剧本发生这种情况

AWS::ECR::Repository Repository CREATE_FAILED: production-app-name already exists
etc

我怎样才能让它在 运行 多次时,它会保留现有的 s3 和存储库,而不是直接崩溃? (我假设参数 "DeletionPolicy": "Retain", 会这样做)

我想达到的目标:

如果我 运行 这 100 倍,我想要与 运行 #1 之后相同的资源状态。我不想要任何数据的任何资源 deleted/wiped。

{


 "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Pre-reqs for Elastic Beanstalk application",
  "Parameters": {
    "BucketName": {
      "Type": "String",
      "Description": "S3 Bucket name"
    },
    "RepositoryName": {
      "Type": "String",
      "Description": "ECR Repository name"
    }
  },
  "Resources": {
    "Bucket": {
      "Type": "AWS::S3::Bucket",
      "DeletionPolicy": "Retain",
      "Properties": {
        "BucketName": { "Fn::Join": [ "-", [
          { "Ref": "BucketName" },
          { "Ref": "AWS::Region" }
        ]]}
      }
    },
    "Repository": {
      "Type": "AWS::ECR::Repository",
      "DeletionPolicy": "Retain",
      "Properties": {
        "RepositoryName": { "Ref": "RepositoryName" }
      }
    }
  },
  "Outputs": {
    "S3Bucket": {
      "Description": "Full S3 Bucket name",
      "Value": { "Ref": "Bucket" }
    },
    "Repository": {
      "Description": "ECR Repo",
      "Value": { "Fn::Join": [ "/", [
        {
          "Fn::Join": [ ".", [
            { "Ref": "AWS::AccountId" },
            "dkr",
            "ecr",
            { "Ref": "AWS::Region" },
            "amazonaws.com"
          ]]
        },
        { "Ref": "Repository" }
      ]]}
    }
  }
}

编辑:

DB 在 运行 两次

时出现类似问题
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "DBPassword": {
            "MinLength": "8",
            "NoEcho": true,
            "Type": "String"
        },
        "Environment": {
            "MinLength": "1",
            "Type": "String"
        },
        "DBName": {
            "Type": "String",
            "Description": "DBName"
        },
        "DBInstanceIdentifier": {
            "Type": "String",
            "Description": "DBInstanceIdentifier"
        },
        "DBPort": {
            "Type": "String",
            "Description": "DBPort"
        },
        "DBUsername": {
            "Type": "String",
            "Description": "DBName"
        }
    },
    "Outputs": {
        "Url": {
            "Value": {
                "Fn::Sub": "postgres://${DBUsername}:${DBPassword}@${Instance.Endpoint.Address}:${Instance.Endpoint.Port}/${DBName}"
            }
        }
    },
    "Resources": {
        "Instance": {
            "Type": "AWS::RDS::DBInstance",
            "DeletionPolicy": "Retain",
            "Properties": {
                "AllocatedStorage": "10",
                "DBInstanceClass": "db.t2.micro",
                "DBInstanceIdentifier": {"Ref": "DBInstanceIdentifier"},
                "DBName": {
                    "Ref": "DBName"
                },
                "Engine": "postgres",
                "EngineVersion": "9.6.6",
                "MasterUsername": {
                    "Ref": "DBUsername"
                },
                "MasterUserPassword": {
                    "Ref": "DBPassword"
                },
                "MultiAZ": "false",
                "Port": {
                    "Ref": "DBPort"
                },
                "PubliclyAccessible": "false",
                "StorageType": "gp2"
            }
        }
    }
}

AWS::ECR::Repository 中的字段 RepositoryName 实际上不是必需的,我建议不要指定一个。通过让 CloudFormation 为存储库动态分配一个唯一的名称,您将避免冲突。

如果您稍后想使用存储库名称,例如:在任务定义中,您可以像这样使用 "Ref" 函数 { "Ref": "Repository" } 来提取由 [=31 生成的唯一名称=]CloudFormation。

至于 RDS 实例 的问题,tt 归结为硬编码资源名称的相同问题。

使用 retain 将使资源保持活动状态,但它将不再由 CloudFormation 管理,这是一个大问题。

只需确保在进行更新时永远不要修改需要资源的参数 "replacement"。文档总是说明参数更改将导致哪种更新。

图片取自 (here)

如果您确实需要更改需要更换的参数。使用适配器参数创建新资源,迁移数据库或 ECR 存储库 中的任何数据,然后从模板中删除旧资源。如果您不需要迁移任何内容,请确保您没有硬编码名称并让 CloudFormation 执行替换。