CloudFormation Auto Scaling Group sample template for mixed X86 (Intel, AMD) and AWS Graviton instances
You can take advantage of multiple processor families when building Amazon EC2 Auto Scaling Groups, including X86-based instances and Arm64-based instances including AWS Graviton. This provides you with maximum flexibility for workloads that can run on multiple instance families and types, especially workloads suited to running on EC2 Spot.
If you use Amazon EC2 for compute, you may choose to adopt a highly-flexible approach to instance provisioning. If availability and price are key factors, you can utilize any instance type available while minimizing cost. And if your application is flexible enough to run on different processor architectures - for example, Java, Python, Node.JS, Ruby, and PHP applications - you can also take advantage of different CPU architectures including X86 (used by EC2 instances powered by Intel and AMD processors) and Arm64 (used by AWS Graviton processors).
This flexibility is made possible by two features of EC2 Auto Scaling Groups: Mixed Instance Policies and Attribute-Based Instance selection. Mixed Instance Policies allow you to use different instance types and even different EC2 Launch Templates within the same Auto Scaling Group. And Attribute-Based Instance Selection allows you to choose a set of instance types by attributes such as the number of vCPUs and amount of memory provided by the instance, which frees you from the burden of enumerating specific instance types and having to keep pace with new instance types as they are made available.
You can use the following CloudFormation YAML template excerpt as a starting point for your EC2 Auto Scaling Group configuration:
Parameters:
VpcId:
Description: AWS VPC ID into which the instances will be deployed.
Type: String
SubnetIds:
Description: A list of comma-separated VPC subnet IDs into which the instances will be deployed.
Type: CommaDelimitedList
MinSize:
Description: The minimum number of instances in the Auto Scaling Group.
Type: Number
MinValue: "0"
Default: "1"
MaxSize:
Description: The maximum number of instances in the Auto Scaling Group.
Type: Number
MinValue: "0"
Default: "100"
OnDemandPercentage:
Description: The percentage of On-Demand instances to use. Setting this to 0 will utilize only Spot capacity.
Type: Number
MinValue: "0"
MaxValue: "100"
Default: "0"
AllowedX86AppInstanceTypes:
Description: >-
The instance types to apply your specified attributes against. All other instance types are ignored, even if they match your specified attributes.
You can use strings with one or more wild cards, represented by an asterisk (*), to allow an instance type, size, or generation. The following are examples: m5.8xlarge, c5*.*, m5a.*, r*, *3*.
For example, if you specify c5*, Amazon EC2 Auto Scaling will allow the entire C5 instance family, which includes all C5a and C5n instance types. If you specify m5a.*, Amazon EC2 Auto Scaling will allow all the M5a instance types, but not the M5n instance types.
Type: CommaDelimitedList
Default: ""
ExcludedX86AppInstanceTypes:
Description: >-
The instance types to exclude. You can use strings with one or more wild cards, represented by an asterisk (*), to exclude an instance family, type, size, or generation. The following are examples: m5.8xlarge, c5*.*, m5a.*, r*, *3*.
For example, if you specify c5*, you are excluding the entire C5 instance family, which includes all C5a and C5n instance types. If you specify m5a.*, Amazon EC2 Auto Scaling will exclude all the M5a instance types, but not the M5n instance types.
Type: CommaDelimitedList
Default: ""
AllowedGravitonAppInstanceTypes:
Description: >-
The instance types to apply your specified attributes against. All other instance types are ignored, even if they match your specified attributes.
You can use strings with one or more wild cards, represented by an asterisk (*), to allow an instance type, size, or generation. The following are examples: m6g.8xlarge, c6g.*, m5g.*.
For example, if you specify c6g*, Amazon EC2 Auto Scaling will allow the entire C6g instance family, which includes all C6gd and C6gn instance types. If you specify c6g.*, Amazon EC2 Auto Scaling will allow all the C6g instance types, but not the C6gn instance types.
Type: CommaDelimitedList
Default: ""
ExcludedGravitonAppInstanceTypes:
Description: >-
The instance types to exclude. You can use strings with one or more wild cards, represented by an asterisk (*), to exclude an instance family, type, size, or generation. The following are examples: m6g.8xlarge, c6g.*, m5g.*.
For example, if you specify c6g*, you are excluding the entire C6g instance family, which includes all C6gd and C6gn instance types. If you specify m6g.*, Amazon EC2 Auto Scaling will exclude all the M6g instance types, but not the M6gd instance types.
Type: CommaDelimitedList
Default: "a1.*"
AppInstanceGenerations:
Description: Indicates whether current or previous generation instance types are included.
Type: CommaDelimitedList
Default: "current"
AllowedValues: ["current", "previous"]
AppInstanceMinVCPUs:
Type: Number
MinValue: "0"
Default: "0"
AppInstanceMaxVCPUs:
Type: Number
MinValue: "0"
Default: "64"
AppInstanceMinMemoryMiB:
Type: Number
MinValue: "0"
Default: "0"
AppInstanceMaxMemoryMiB:
Type: Number
MinValue: "0"
Default: "0"
LoadBalancerInstanceType:
Type: String
Description: EC2 instance type to use for load balancer
Default: c6g.large
GravitonInstanceImageId:
Description: An AWS Systems Manager Parameter Store key whose value contains the EC2 AMI ID for Graviton instances.
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64
X86InstanceImageId:
Description: An AWS Systems Manager Parameter Store key whose value contains the EC2 AMI ID for X86 (Intel, AMD) instances.
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64
Conditions:
HasMaxMemory: !Not [!Equals [!Ref AppInstanceMaxMemoryMiB, "0"]]
HasMaxVCPUs: !Not [!Equals [!Ref AppInstanceMaxVCPUs, "0"]]
HasAllowedX86AppInstanceTypes:
!Not [!Equals [!Join ["", !Ref AllowedX86AppInstanceTypes], ""]]
HasExcludedX86AppInstanceTypes:
!Not [!Equals [!Join ["", !Ref ExcludedX86AppInstanceTypes], ""]]
HasAllowedGravitonAppInstanceTypes:
!Not [!Equals [!Join ["", !Ref AllowedGravitonAppInstanceTypes], ""]]
HasExcludedGravitonAppInstanceTypes:
!Not [!Equals [!Join ["", !Ref ExcludedGravitonAppInstanceTypes], ""]]
Resources:
InstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ec2.amazonaws.com]
Action: ["sts:AssumeRole"]
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref InstanceRole
AppInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: App Instance
VpcId: !Ref VpcId
SecurityGroupEgress:
- IpProtocol: "-1"
CidrIp: "0.0.0.0/0"
# Launch templates. Note that the instance types are not explicitly provided in them -
# these will be chosen by EC2 Auto Scaling. The only significant difference between them is the
# Image ID (AMI) because each CPU architecture (x86-64 and arm64) requires a different
# image.
X86AppLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
EbsOptimized: true
IamInstanceProfile:
Arn: !GetAtt InstanceProfile.Arn
ImageId: !Ref X86InstanceImageId
Monitoring:
Enabled: true
SecurityGroupIds:
- !Ref AppInstanceSecurityGroup
GravitonAppLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
EbsOptimized: true
IamInstanceProfile:
Arn: !GetAtt InstanceProfile.Arn
ImageId: !Ref GravitonInstanceImageId
Monitoring:
Enabled: true
SecurityGroupIds:
- !Ref AppInstanceSecurityGroup
AppAutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
# This is just an example UpdatePolicy - you can also use an AutoScalingRollingUpdate
# if you prefer.
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: true
Properties:
# These are just example sizes - substitute your own, or consider making these parameter
# references for maximum flexibility.
MinSize: !Ref MinSize
MaxSize: !Ref MaxSize
MixedInstancesPolicy:
LaunchTemplate:
# Since there must be a base Launch Template specification, we will use the X86
# instance Launch Template as the base. It will be inherited by the first
# element of Overrides (for the `intel` and `amd` manufacturers) but we will
# override it in the second element of Overrides.
LaunchTemplateSpecification:
LaunchTemplateId: !Ref X86AppLaunchTemplate
Version: !GetAtt X86AppLaunchTemplate.LatestVersionNumber
Overrides:
# X86 Instances (Intel/AMD)
- InstanceRequirements:
CpuManufacturers: ["intel", "amd"] # x86-64/amd64 architecture
AllowedInstanceTypes:
!If [
HasAllowedX86AppInstanceTypes,
!Ref AllowedX86AppInstanceTypes,
!Ref AWS::NoValue,
]
ExcludedInstanceTypes:
!If [
HasExcludedX86AppInstanceTypes,
!Ref ExcludedX86AppInstanceTypes,
!Ref AWS::NoValue,
]
VCpuCount:
Min: !Ref AppInstanceMinVCPUs
Max:
!If [
HasMaxVCPUs,
!Ref AppInstanceMaxVCPUs,
!Ref AWS::NoValue,
]
MemoryMiB:
Min: !Ref AppInstanceMinMemoryMiB
Max:
!If [
HasMaxMemory,
!Ref AppInstanceMaxMemoryMiB,
!Ref AWS::NoValue,
]
InstanceGenerations: !Ref AppInstanceGenerations
# Graviton Instances
# Note here that we override the Launch Template to point to the one that
# refers to the arm64 Machine Image (AMI).
- LaunchTemplateSpecification:
LaunchTemplateId: !Ref GravitonAppLaunchTemplate
Version: !GetAtt GravitonAppLaunchTemplate.LatestVersionNumber
InstanceRequirements:
CpuManufacturers: ["amazon-web-services"] # Graviton/Arm64
AllowedInstanceTypes:
!If [
HasAllowedGravitonAppInstanceTypes,
!Ref AllowedGravitonAppInstanceTypes,
!Ref AWS::NoValue,
]
ExcludedInstanceTypes:
!If [
HasExcludedGravitonAppInstanceTypes,
!Ref ExcludedGravitonAppInstanceTypes,
!Ref AWS::NoValue,
]
VCpuCount:
Min: !Ref AppInstanceMinVCPUs
Max:
!If [
HasMaxVCPUs,
!Ref AppInstanceMaxVCPUs,
!Ref AWS::NoValue,
]
MemoryMiB:
Min: !Ref AppInstanceMinMemoryMiB
Max:
!If [
HasMaxMemory,
!Ref AppInstanceMaxMemoryMiB,
!Ref AWS::NoValue,
]
InstanceGenerations: !Ref AppInstanceGenerations
InstancesDistribution:
SpotAllocationStrategy: price-capacity-optimized
OnDemandPercentageAboveBaseCapacity: !Ref OnDemandPercentage
VPCZoneIdentifier: !Ref SubnetIds
Just a note, the CpuManufacturers: ["amazon-web-services"]
parameter isn't necessary. Per the note in the CloudFormation documentation for InstanceRequirements
:
Don't confuse the CPU hardware manufacturer with the CPU hardware architecture. Instances will be launched with a compatible CPU architecture based on the Amazon Machine Image (AMI) that you specify in your launch template.
The arm64 AMI contained in the launch template will automatically limit to the compatible arm64 instance types. Technically, setting CpuManufacturers: ["amazon-web-services"]
means only AWS chips which can include x86 inf1 instance types.
Relevant content
- asked 8 months agolg...
- asked 4 months agolg...
- asked 9 months agolg...
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated 5 months ago
- AWS OFFICIALUpdated 2 months ago