如何通过CloudFormation模板保留AWS Service Catalog产品最新3个版本
解决AWS Service Catalog产品版本留存问题:保留最新3个版本
AWS Service Catalog的原生CloudFormation集成在更新产品时,默认会替换现有版本而非保留历史版本。要实现更新时自动保留最新3个版本的需求,需要结合Lambda自定义资源扩展CloudFormation的逻辑,具体方案如下:
核心实现思路
通过CloudFormation部署一个Lambda函数作为自定义资源,在产品更新流程中触发以下操作:
- 为目标Service Catalog产品创建新版本
- 列出该产品的所有版本,按创建时间降序排序
- 保留最新的3个版本,自动删除更早的冗余版本
CloudFormation模板示例
1. Lambda执行角色(最小权限配置)
Resources: ServiceCatalogVersionCleanerRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: ServiceCatalogVersionManagement PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - servicecatalog:CreateProvisioningArtifact - servicecatalog:ListProvisioningArtifacts - servicecatalog:DeleteProvisioningArtifact Resource: !Ref MyServiceCatalogProduct - Effect: Allow Action: - servicecatalog:DescribeProduct Resource: '*'
2. Lambda函数(版本管理核心逻辑)
ServiceCatalogVersionCleanerFunction: Type: AWS::Lambda::Function Properties: Handler: index.lambda_handler Runtime: python3.11 Role: !GetAtt ServiceCatalogVersionCleanerRole.Arn Code: ZipFile: | import boto3 import cfnresponse import time sc = boto3.client('servicecatalog') def lambda_handler(event, context): try: product_id = event['ResourceProperties']['ProductId'] keep_count = int(event['ResourceProperties']['KeepLatestVersions']) template_url = event['ResourceProperties']['TemplateUrl'] # 创建新版本 create_response = sc.create_provisioning_artifact( ProductId=product_id, Parameters={ 'Name': f"v{int(time.time())}", 'Description': 'Auto-updated version', 'Info': {'LoadTemplateFromURL': template_url}, 'Type': 'CLOUD_FORMATION_TEMPLATE' } ) provisioning_artifact_id = create_response['ProvisioningArtifactDetail']['Id'] # 列出所有版本并按创建时间降序排序 artifacts = sc.list_provisioning_artifacts(ProductId=product_id)['ProvisioningArtifactDetails'] sorted_artifacts = sorted(artifacts, key=lambda x: x['CreatedTime'], reverse=True) # 删除超出保留数量的旧版本 for artifact in sorted_artifacts[keep_count:]: sc.delete_provisioning_artifact( ProductId=product_id, ProvisioningArtifactId=artifact['Id'] ) # 向CloudFormation返回成功状态 cfnresponse.send(event, context, cfnresponse.SUCCESS, {'ProvisioningArtifactId': provisioning_artifact_id}) except Exception as e: # 返回失败状态及错误信息 cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})
3. Service Catalog产品定义
MyServiceCatalogProduct: Type: AWS::ServiceCatalog::CloudFormationProduct Properties: Name: "My Sample Product" Owner: "Engineering Team" Description: "Product with automatic version retention" ProvisioningArtifactParameters: - Name: "Initial Version" Description: "First version of the product" Info: LoadTemplateFromURL: "https://your-bucket.s3.amazonaws.com/initial-template.yaml"
4. 自定义资源(触发版本管理流程)
ServiceCatalogVersionManager: Type: Custom::ServiceCatalogVersionManager Properties: ServiceToken: !GetAtt ServiceCatalogVersionCleanerFunction.Arn ProductId: !Ref MyServiceCatalogProduct KeepLatestVersions: 3 TemplateUrl: "https://your-bucket.s3.amazonaws.com/updated-template.yaml"
关键注意事项
- CloudFormation回调处理:Lambda必须调用
cfnresponse.send()返回状态,否则CloudFormation栈会一直处于等待状态 - 版本排序逻辑:依赖
CreatedTime字段排序,确保最新版本优先保留 - 权限最小化:Lambda角色仅授予必要的Service Catalog操作权限,避免过度授权
- 模板更新触发:每次更新产品时,修改
TemplateUrl参数指向新的CloudFormation模板,自定义资源会自动触发新版本创建和旧版本清理 - 测试验证:先在非生产环境测试逻辑,确认旧版本按预期删除后再推广到生产环境
内容的提问来源于stack exchange,提问作者shadab khan
相关产品推荐
相关产品推荐

