如何在CloudFormation中使用List和Map参数?解决参数超限问题
Hey there! Let's break down your CloudFormation challenges with practical, hands-on examples to make this clear.
First, let's cover how to define and reference these parameter types in your template.
List Type Parameters
List parameters let you pass an array of values (strings, numbers, etc.) as a single parameter. Here's how to use them:
Example: Defining and Using a List Parameter
Parameters: SubnetIds: Type: List<String> Description: Comma-separated list of subnet IDs for your resources Default: subnet-123,subnet-456,subnet-789 Resources: # Use the entire list for a resource that accepts multiple values MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: VPCZoneIdentifier: !Ref SubnetIds # Passes the full list of subnets # Pick a specific item from the list using !Select MySingleSubnetEC2: Type: AWS::EC2::Instance Properties: SubnetId: !Select [0, !Ref SubnetIds] # Uses the first subnet in the list
When deploying, you can pass the list as a comma-separated string (in the console) or as an array (in CLI/API).
Map Type Parameters
Map parameters let you pass key-value pairs (even nested ones) as a single parameter, which is perfect for grouping related configs. Here's a basic example:
Example: Defining and Using a Simple Map Parameter
Parameters: EC2InstanceConfig: Type: Map Description: Configuration for the EC2 instance Default: InstanceType: t2.micro ImageId: ami-12345678 SubnetId: subnet-123 Resources: MyEC2Instance: Type: AWS::EC2::Instance Properties: InstanceType: !GetAtt EC2InstanceConfig.InstanceType ImageId: !GetAtt EC2InstanceConfig.ImageId SubnetId: !GetAtt EC2InstanceConfig.SubnetId
You can also create nested Maps for more complex configurations (we'll use this for your 60-parameter limit issue next).
When you hit the 60-parameter cap, grouping related parameters into nested Maps is the way to go. Let's turn your scattered parameters into organized Maps with a real-world example.
Step 1: Identify Related Parameters to Group
Suppose you had parameters like WebInstanceType, WebAMI, WebSubnetId, AppInstanceType, AppAMI, AppSubnetId, plus dozens more. Instead of 6+ parameters, you can group them into a single ServiceConfigs Map.
Step 2: Rewrite Parameters as a Nested Map
Parameters: # Group all service-related configs into one Map ServiceConfigs: Type: Map Description: Nested map containing configs for web, app, and database services Default: Web: InstanceType: t2.medium AMI: ami-12345678 SubnetId: subnet-123 SecurityGroupId: sg-123 App: InstanceType: t2.large AMI: ami-87654321 SubnetId: subnet-456 SecurityGroupId: sg-456 DB: InstanceClass: db.t3.medium EngineVersion: 14.7 SubnetGroup: db-subnet-group-123 # Keep other standalone parameters here (e.g., StackName, Environment) Environment: Type: String AllowedValues: [dev, staging, prod]
Step 3: Reference the Nested Map in Resources
To access values from the nested Map, chain !GetAtt calls to drill down into the keys:
Resources: WebEC2Instance: Type: AWS::EC2::Instance Properties: InstanceType: !GetAtt ServiceConfigs.Web.InstanceType ImageId: !GetAtt ServiceConfigs.Web.AMI SubnetId: !GetAtt ServiceConfigs.Web.SubnetId SecurityGroupIds: [!GetAtt ServiceConfigs.Web.SecurityGroupId] AppEC2Instance: Type: AWS::EC2::Instance Properties: InstanceType: !GetAtt ServiceConfigs.App.InstanceType ImageId: !GetAtt ServiceConfigs.App.AMI SubnetId: !GetAtt ServiceConfigs.App.SubnetId SecurityGroupIds: [!GetAtt ServiceConfigs.App.SecurityGroupId] MyRDSInstance: Type: AWS::RDS::DBInstance Properties: DBInstanceClass: !GetAtt ServiceConfigs.DB.InstanceClass EngineVersion: !GetAtt ServiceConfigs.DB.EngineVersion DBSubnetGroupName: !GetAtt ServiceConfigs.DB.SubnetGroup
Step 4: Passing the Map Parameter During Deployment
- Console: Enter the Map as a JSON string, e.g.:
{"Web": {"InstanceType": "t2.large", "AMI": "ami-98765432"}, "App": {"InstanceType": "t2.xlarge"}} - CLI: Use the
--parametersflag with a JSON string:aws cloudformation create-stack \ --stack-name MyServiceStack \ --template-body file://template.yaml \ --parameters ParameterKey=ServiceConfigs,ParameterValue='{"Web": {"InstanceType": "t2.large", "AMI": "ami-98765432"}, "App": {"InstanceType": "t2.xlarge"}}' ParameterKey=Environment,ParameterValue=prod
Best Practices for This Approach
- Group logically: Keep related configs together (e.g., all network params in one Map, all storage in another) to keep your template readable.
- Set defaults: Define sensible defaults for your Map so users only need to override values that differ.
- Validate with constraints: You can use
AllowedValuesorAllowedPatternon individual Map values by combining withFn::GetAttin aConditionsblock, if needed.
内容的提问来源于stack exchange,提问作者Vikas Rathore

