CloudFormation StackSet如何根据VPC标签动态指定安全组所属VPC
方案指导
你的实现思路是可行的,核心要解决的是CloudFormation模板在各账号本地执行时,动态查询符合标签要求的VPC ID,目前有两种成熟的实现方案:
方案一:SSM参数存储动态引用(推荐,运维成本更低)
这个方案不需要额外维护运行时资源,仅需提前完成一次全局配置:
- 先通过StackSet批量在所有托管账号的SSM参数存储中创建统一路径的String类型参数,比如路径为
/common/service-vpc-id,值为对应账号带ServiceName:True标签的VPC ID - 直接修改你的模板中安全组的
VpcId字段,使用CloudFormation动态引用语法直接读取该SSM参数即可:
"VpcId" : "{{resolve:ssm:/common/service-vpc-id:1}}"
注意你需要为StackSet的栈执行角色添加
ssm:GetParameter权限,允许读取该路径的参数。
方案二:CloudFormation自定义资源+Lambda(灵活度更高)
如果你的VPC标签可能后续变更,不想手动维护SSM参数,可以选择这个方案:
- 先通过StackSet批量在所有托管账号部署Lambda执行角色和查询函数:
- Lambda执行角色需要添加
ec2:DescribeVpcs权限,以及CloudFormation自定义资源的调用权限 - Lambda代码参考:
import boto3 import json import cfnresponse def lambda_handler(event, context): try: ec2 = boto3.client('ec2') resp = ec2.describe_vpcs(Filters=[{'Name': 'tag:ServiceName', 'Values': ['True']}]) if len(resp['Vpcs']) != 1: raise Exception(f"查询到{len(resp['Vpcs'])}个符合要求的VPC,预期为1个") vpc_id = resp['Vpcs'][0]['VpcId'] cfnresponse.send(event, context, cfnresponse.SUCCESS, {'VpcId': vpc_id}) except Exception as e: cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})
- 修改你的栈模板,添加自定义资源调用该Lambda获取VPC ID,不需要额外定义
MyValidVPCID参数:
{ "Resources": { "GetValidVpc": { "Type": "AWS::CloudFormation::CustomResource", "Properties": { "ServiceToken": {"Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:query-service-vpc"} } }, "SG": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Security Group Desc.", "Tags": [ { "Key": "Key1", "Value": "ABC" }, { "Key": "Key2", "Value": "DEF" } ], "VpcId" : { "Fn::GetAtt": [ "GetValidVpc", "VpcId" ] } } }, "SGIngressRule01": { "Type": "AWS::EC2::SecurityGroupIngress", "DependsOn": "SG", "Properties": { "GroupId" : { "Fn::GetAtt": [ "SG", "GroupId" ] }, "Description": "Rule 1 description", "IpProtocol": "tcp", "FromPort": 123, "ToPort": 456, "CidrIp": "0.0.0.0/0" } } } }
两种方案都支持跨账号跨区域的StackSet部署,不需要手动指定每个账号的VPC ID。
内容的提问来源于stack exchange,提问作者Tribalinius
相关产品推荐
相关产品推荐

