如何在CloudFormation模板中实现Spot实例的无偏好子网设置?
Great question! The console's "no preference" subnet option is a handy feature for getting the best Spot price without manually picking AZs, but you can absolutely replicate this behavior in CloudFormation—even with some extra flexibility the console doesn't offer. Let's break this down:
How to Implement "No Preference" Subnet Selection
The console's "No preference" works by automatically choosing a default subnet in the AZ with the lowest current Spot price for your instance type. Here are two ways to do this in CloudFormation:
1. Use Spot Fleet (Recommended Approach)
This is actually what the console uses behind the scenes for optimal price and availability, and it's the easiest way to replicate the "no preference" behavior. Spot Fleet lets you specify multiple subnets (like all default ones in your region) and uses the lowestPrice allocation strategy to pick the cheapest AZ for your instances.
Here's a simplified CloudFormation snippet to get you started:
Resources: MySpotFleet: Type: AWS::EC2::SpotFleet Properties: SpotFleetRequestConfigData: TargetCapacity: 1 # Adjust to your desired number of instances AllocationStrategy: lowestPrice # Picks the cheapest AZ/subnet LaunchTemplateConfigs: - LaunchTemplateSpecification: LaunchTemplateId: !Ref MySpotLaunchTemplate Version: "$Latest" Overrides: # List all default subnets in your region here, or use a dynamic filter to fetch them - SubnetId: subnet-abc123 - SubnetId: subnet-def456 - SubnetId: subnet-ghi789 MySpotLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateData: InstanceType: t3.micro # Replace with your instance type ImageId: ami-0c55b159cbfafe1f0 # Replace with your AMI ID SecurityGroupIds: - sg-1234567890 # Replace with your security group ID
To automatically fetch all default subnets instead of hardcoding them, you can use a Lambda-backed custom resource or leverage CloudFormation's intrinsic functions with a filter for default subnets (though the latter requires some setup).
2. For Single Spot Instances (Lambda-Backed Custom Resource)
If you need a single Spot instance rather than a fleet, you can create a Lambda function that dynamically finds the cheapest AZ and returns its default subnet ID. Here's the high-level workflow:
- Build a Lambda function that:
- Fetches all default subnets in your region using
describe-subnets. - Gets the latest Spot prices for your instance type with
describe-spot-price-history. - Matches each subnet to its AZ's price and selects the cheapest one.
- Fetches all default subnets in your region using
- Define a CloudFormation custom resource that invokes this Lambda, then use
!GetAttto pull the subnet ID into your EC2 instance resource.
This takes a bit more work but gives you the exact single-instance behavior the console provides.
Is the Console More Advantageous Than CloudFormation?
Nope—if anything, CloudFormation offers more value here. The console's "no preference" is a simplified interface for one-off deployments, but CloudFormation lets you:
- Scale easily: Use Spot Fleet to manage multiple instances across AZs for better availability and price optimization (something the console can't do as seamlessly).
- Automate and reuse: Once your template is defined, you can deploy it across regions, environments, or integrate it into CI/CD pipelines—no manual clicks required.
- Customize constraints: Add rules like excluding specific AZs, prioritizing subnets with certain tags, or combining Spot and On-Demand instances—options the console doesn't expose.
- Ensure consistency: Avoid manual errors by deploying the exact same infrastructure every time.
The only edge the console has is simplicity for quick, one-off instances, but for any production or repeatable setup, CloudFormation is the better choice.
内容的提问来源于stack exchange,提问作者shantanuo

