如何在CloudFormation中强制删除AWS ECR?

10
使用CloudFormation删除包含ECR镜像的栈会导致失败消息:
The repository with name 'my-repo' in registry with id '123' cannot be deleted because it still contains images

CLI提供了一种用--force标记来覆盖此设置的方法:
aws ecr delete-repository --repository-name my-repo --force

我该如何仅使用CloudFormation实现相同的结果?

你解决了这个问题吗?因为我也遇到了完全相同的问题。 - slu
很抱歉,虽然我自从遇到这个问题后就没有再去看过它。 - Mark Hobson
1
没有办法使用Cloudformation来做到这一点。S3 bucket也有同样的“问题”。我认为这是一个安全检查,你必须在CF之外清空资源,然后才能使用CF删除它。 - Patrick Chu
https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/224 - Pat Myron
2
研究似乎仍在进行中:https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/515 - Vikas Banage
显示剩余2条评论
2个回答

0

目前无法强制删除 ECR 存储库。实际上,有一个 问题 请求此功能。

作为解决方法,您可以部署一个基于 Lambda 的自定义资源,在堆栈删除时清空 ECR 存储库。

当您将 Lambda 函数与自定义资源关联时,该函数会在创建、更新或删除自定义资源时被调用。AWS CloudFormation 调用 Lambda API 来调用函数并将所有请求数据(例如请求类型和资源属性)传递给函数。

这是一个最小可重现的示例:

{
    "Parameters": {
        "ECRRepositoryName": {
            "Description": "Name of ECR repository",
            "Default": "test-repository",
            "Type": "String"
        }
    },
    "Resources": {
        "ECRRepository": {
            "Type": "AWS::ECR::Repository",
            "Properties": {
                "RepositoryName": {
                    "Ref": "ECRRepositoryName"
                }
            }
        },
        "LambdaEmptyECRRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": "lambda.amazonaws.com"
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "Path": "/",
                "Policies": [
                    {
                        "PolicyName": "ecr-access-policy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "ecr:*"
                                    ],
                                    "Resource": "*"
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "LambdaEmptyECR": {
            "Type": "AWS::Lambda::Function",
            "DependsOn": "ECRRepository",
            "Properties": {
                "Code": {
                    "ZipFile": {
                        "Fn::Join": [
                            "\n",
                            [
                                "import os",
                                "import cfnresponse",
                                "import boto3",
                                "",
                                "def lambda_handler(event, context):",
                                "    response = {}",
                                "    if event['RequestType'] == 'Delete':",
                                "        region = event['ResourceProperties']['Region']",
                                "        repository_name = event['ResourceProperties']['ECRRepositoryName']",
                                "        client = boto3.client('ecr', region_name=region)",
                                "        images = client.list_images(repositoryName=repository_name)",
                                "        image_ids = [image for image in images['imageIds']]",
                                "        try:",
                                "            client.batch_delete_image(repositoryName=repository_name, imageIds=image_ids)",
                                "            while client.list_images(repositoryName=repository_name)['imageIds'] != []:",
                                "                os.sleep(1) # wait for images to be deleted",
                                "            response['output'] = 'Successfully deleted images in ECR repository'",
                                "            cfnresponse.send(event, context, cfnresponse.SUCCESS, response)",
                                "        except Exception as e:",
                                "            response['output'] = 'Error'+ e.__str__()",
                                "            cfnresponse.send(event, context, cfnresponse.FAILED, response)",
                                "    cfnresponse.send(event, context, cfnresponse.SUCCESS, response)"
                            ]
                        ]
                    }
                },
                "Handler": "index.lambda_handler",
                "Role": {
                    "Fn::GetAtt": [
                        "LambdaEmptyECRRole",
                        "Arn"
                    ]
                },
                "Runtime": "python3.8"
            }
        },
        "EmptyECR": {
            "Type": "Custom::LambdaDependency",
            "DependsOn": "ECRRepository",
            "Properties": {
                "ServiceToken": {
                    "Fn::GetAtt": [
                        "LambdaEmptyECR",
                        "Arn"
                    ]
                },
                "ECRRepositoryName": {
                    "Ref": "ECRRepositoryName"
                },
                "Region": {
                    "Ref": "AWS::Region"
                }
            }
        }
    }
}

在堆栈删除时,Lambda函数在删除ECR存储库之前被调用,并删除存储库中包含的所有映像。

有关自定义资源的更多信息:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html


尝试此示例:

  1. 部署 CloudFormation 模板
  2. 将任何图像推送到 ECR 存储库
  3. 删除 CloudFormation 模板

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接