CloudFormation嵌套列表使用/列表追加方法及安全组配置错误排障
嘿,咱们一步步来解决你的两个CloudFormation问题:先说说嵌套列表和列表追加的用法,再搞定你遇到的安全组配置错误~
1. 嵌套列表的使用
CloudFormation支持嵌套列表(也就是List of List类型),前提是对应的资源属性明确接受这种格式。写法很直观,用YAML的嵌套列表语法即可。比如某个资源属性要求传入List of List
Resources: ExampleResource: Type: AWS::Some::ResourceType Properties: NestedListProperty: - ["group1-item1", "group1-item2"] - ["group2-item1", "group2-item2"]
⚠️ 注意:不是所有资源属性都支持嵌套列表,一定要先查阅对应资源的CloudFormation官方文档,确认属性的类型要求。
2. 向列表中追加元素
如果需要合并多个列表(或是给现有列表追加新元素),推荐使用CloudFormation的!Merge短语法(或完整的Fn::Merge函数),它能把多个独立的列表合并成一个一维列表。举个例子:
Parameters: ExistingSecurityGroups: Type: List<String> Description: 栈外已存在的安全组ID列表 Resources: StackInternalSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: 当前栈内创建的安全组 MyEC2Instance: Type: AWS::EC2::Instance Properties: SecurityGroups: !Merge [!Ref ExistingSecurityGroups, [!Ref StackInternalSG]]
这段代码会把参数传入的现有安全组列表,和栈内新创建的安全组ID合并成一个符合要求的列表。
你遇到的Value of property SecurityGroups must be of type List of String for reference错误,几乎肯定是因为不小心创建了嵌套列表——而SecurityGroups属性要求的是一维的字符串列表(每个元素都是安全组ID)。
比如你最初的写法可能类似这样(错误示例):
Mappings: EnvironmentMap: production: ExternalSGs: - sg-12345678 - sg-87654321 Resources: InternalSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: 栈内创建的安全组 MyEC2: Type: AWS::EC2::Instance Properties: SecurityGroups: - !FindInMap [EnvironmentMap, production, ExternalSGs] # 这里返回的是一个列表 - !Ref InternalSG # 这里是单个字符串
这种写法会让SecurityGroups变成嵌套列表:[["sg-12345678", "sg-87654321"], "sg-xxxxxx"],完全不符合属性要求,所以触发了错误。
修正后的完整代码
用!Merge把栈外的安全组列表和栈内的安全组引用合并成一维列表即可:
Mappings: EnvironmentMap: production: ExternalSGs: - sg-12345678 - sg-87654321 Resources: InternalSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: 当前栈内创建的安全组 VpcId: !Ref MyVpc # 替换为你的VPC ID或对应引用 MyEC2Instance: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0c55b159cbfafe1f0 # 示例AMI,按需替换为你区域的可用AMI SecurityGroups: !Merge - !FindInMap [EnvironmentMap, production, ExternalSGs] - [!Ref InternalSG]
!Merge会把两个列表(映射中取出的外部安全组列表、包含内部安全组引用的列表)合并成一个一维字符串列表,完美匹配SecurityGroups的类型要求。
如果你不需要使用映射,直接写死栈外安全组ID,也可以用更简单的写法:
Resources: InternalSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: 当前栈内创建的安全组 MyEC2Instance: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0c55b159cbfafe1f0 SecurityGroups: - sg-12345678 - sg-87654321 - !Ref InternalSG
这种直接将三个字符串(或返回字符串的引用)放在同一列表中的写法也是完全正确的。
内容的提问来源于stack exchange,提问作者Tyler Wanner

