AWS CloudFormation Auto Scaling
Overview
Create production-ready Auto Scaling infrastructure using AWS CloudFormation templates. This skill covers Auto Scaling Groups for EC2, ECS, and Lambda, launch configurations, launch templates, scaling policies, lifecycle hooks, and best practices for high availability and cost optimization.
When to Use
Use this skill when:
-
Creating Auto Scaling Groups for EC2 instances
-
Configuring Launch Configurations or Launch Templates
-
Implementing scaling policies (step, target tracking, simple)
-
Adding lifecycle hooks for lifecycle management
-
Creating scaling for ECS services
-
Implementing Lambda provisioned concurrency scaling
-
Organizing templates with Parameters, Outputs, Mappings, Conditions
-
Implementing cross-stack references with export/import
-
Using mixed instances policies for diversity
CloudFormation Template Structure
Base Template with Standard Format
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling group with load balancer
Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Auto Scaling Configuration Parameters: - MinSize - MaxSize - DesiredCapacity - Label: default: Instance Configuration Parameters: - InstanceType - AmiId
Parameters: MinSize: Type: Number Default: 2 Description: Minimum number of instances
MaxSize: Type: Number Default: 10 Description: Maximum number of instances
DesiredCapacity: Type: Number Default: 2 Description: Desired number of instances
InstanceType: Type: String Default: t3.micro AllowedValues: - t3.micro - t3.small - t3.medium - t3.large
AmiId: Type: AWS::EC2::Image::Id Description: AMI ID for instances
Mappings: EnvironmentConfig: dev: InstanceType: t3.micro MinSize: 1 MaxSize: 3 staging: InstanceType: t3.medium MinSize: 2 MaxSize: 6 production: InstanceType: t3.large MinSize: 3 MaxSize: 12
Conditions: IsProduction: !Equals [!Ref Environment, production] UseSpotInstances: !Or [!Equals [!Ref Environment, dev], !Equals [!Ref Environment, staging]]
Resources:
Auto Scaling Group
MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: !Ref MinSize MaxSize: !Ref MaxSize DesiredCapacity: !Ref DesiredCapacity VPCZoneIdentifier: !Ref SubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration LoadBalancerNames: - !Ref MyLoadBalancer HealthCheckType: ELB HealthCheckGracePeriod: 300 TerminationPolicies: - OldestInstance - Default Tags: - Key: Environment Value: !Ref Environment PropagateAtLaunch: true - Key: ManagedBy Value: CloudFormation PropagateAtLaunch: true
Outputs: AutoScalingGroupName: Description: Name of the Auto Scaling Group Value: !Ref MyAutoScalingGroup
Parameters Best Practices
AWS-Specific Parameter Types
Parameters:
AWS-specific types for validation
InstanceType: Type: AWS::EC2::Instance::Type Description: EC2 instance type
AmiId: Type: AWS::EC2::Image::Id Description: AMI ID for instances
SubnetIds: Type: List<AWS::EC2::Subnet::Id> Description: Subnets for Auto Scaling group
SecurityGroupIds: Type: List<AWS::EC2::SecurityGroup::Id> Description: Security groups for instances
LoadBalancerArn: Type: AWS::ElasticLoadBalancingV2::LoadBalancer::Arn Description: Application Load Balancer ARN
TargetGroupArn: Type: AWS::ElasticLoadBalancingV2::TargetGroup::Arn Description: Target Group ARN for ALB
LaunchTemplateId: Type: AWS::EC2::LaunchTemplate::LaunchTemplateId Description: Launch template ID
ScalingPolicyArn: Type: AWS::AutoScaling::ScalingPolicy::Arn Description: Scaling policy ARN
Parameter Constraints
Parameters: MinSize: Type: Number Default: 1 Description: Minimum number of instances MinValue: 0 MaxValue: 1000 ConstraintDescription: Must be between 0 and 1000
MaxSize: Type: Number Default: 10 Description: Maximum number of instances MinValue: 1 MaxValue: 1000 ConstraintDescription: Must be between 1 and 1000
DesiredCapacity: Type: Number Default: 2 Description: Desired number of instances MinValue: 0 MaxValue: 1000
InstanceType: Type: String Default: t3.micro Description: EC2 instance type ConstraintDescription: Must be a valid EC2 instance type
AmiId: Type: AWS::EC2::Image::Id Description: AMI ID
EnvironmentName: Type: String Default: dev Description: Deployment environment AllowedValues: - dev - staging - production ConstraintDescription: Must be dev, staging, or production
SSM Parameter References
Parameters: LatestAmiId: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 Description: Latest Amazon Linux 2 AMI from SSM
InstanceConfiguration: Type: AWS::SSM::Parameter::Value<String> Default: /myapp/instance-configuration Description: Instance configuration from SSM
Outputs and Cross-Stack References
Export/Import Patterns
Stack A - Network and Auto Scaling Stack
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling infrastructure stack
Resources: MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref SubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration
Outputs: AutoScalingGroupName: Description: Name of the Auto Scaling Group Value: !Ref MyAutoScalingGroup Export: Name: !Sub "${AWS::StackName}-AutoScalingGroupName"
AutoScalingGroupArn: Description: ARN of the Auto Scaling Group Value: !Sub "arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/${MyAutoScalingGroup}" Export: Name: !Sub "${AWS::StackName}-AutoScalingGroupArn"
LaunchConfigurationName: Description: Name of the Launch Configuration Value: !Ref MyLaunchConfiguration Export: Name: !Sub "${AWS::StackName}-LaunchConfigurationName"
Stack B - Application Stack (imports from Stack A)
AWSTemplateFormatVersion: 2010-09-09 Description: Application stack using Auto Scaling from infrastructure stack
Parameters: InfraStackName: Type: String Default: infra-stack Description: Name of the infrastructure stack
Resources: ScalingPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-scale-up" PolicyType: StepScaling AdjustmentType: PercentChangeInCapacity Cooldown: 300 StepAdjustments: - MetricIntervalLowerBound: 0 MetricIntervalUpperBound: 10000 ScalingAdjustment: 200 - MetricIntervalLowerBound: 10000 ScalingAdjustment: 400 AutoScalingGroupName: !ImportValue !Sub "${InfraStackName}-AutoScalingGroupName"
Nested Stacks for Modularity
AWSTemplateFormatVersion: 2010-09-09 Description: Main stack with nested Auto Scaling stacks
Resources:
Nested stack for EC2 Auto Scaling
EC2AutoScalingStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/bucket/ec2-asg.yaml TimeoutInMinutes: 15 Parameters: Environment: !Ref Environment InstanceType: !Ref InstanceType MinSize: !Ref MinSize MaxSize: !Ref MaxSize
Nested stack for scaling policies
ScalingPoliciesStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/bucket/scaling-policies.yaml TimeoutInMinutes: 15 Parameters: AutoScalingGroupName: !GetAtt EC2AutoScalingStack.Outputs.AutoScalingGroupName Environment: !Ref Environment
Launch Configurations
Base Launch Configuration
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling with Launch Configuration
Parameters: InstanceType: Type: String Default: t3.micro
AmiId: Type: AWS::EC2::Image::Id
KeyName: Type: AWS::EC2::KeyPair::KeyName
Resources: MyLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: LaunchConfigurationName: !Sub "${AWS::StackName}-lc" ImageId: !Ref AmiId InstanceType: !Ref InstanceType KeyName: !Ref KeyName SecurityGroups: - !Ref InstanceSecurityGroup InstanceMonitoring: Enabled SpotPrice: !If [UseSpot, "0.05", !Ref AWS::NoValue] UserData: Fn::Base64: | #!/bin/bash yum update -y yum install -y httpd systemctl start httpd echo "Hello from Auto Scaling" > /var/www/html/index.html
InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: !Sub "${AWS::StackName}-instance-sg" GroupDescription: Security group for instances VpcId: !Ref VPCId SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0
Conditions: UseSpot: !Equals [!Ref UseSpotInstances, true]
Parameters: UseSpotInstances: Type: String Default: false AllowedValues: - true - false
Launch Templates
Launch Template with Customization
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling with Launch Template
Parameters: InstanceType: Type: String Default: t3.micro
AmiId: Type: AWS::EC2::Image::Id
Resources: MyLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: !Sub "${AWS::StackName}-lt" LaunchTemplateData: ImageId: !Ref AmiId InstanceType: !Ref InstanceType Monitoring: Enabled: true NetworkInterfaces: - DeviceIndex: 0 AssociatePublicIpAddress: false Groups: - !Ref InstanceSecurityGroup TagSpecifications: - ResourceType: instance Tags: - Key: Name Value: !Sub "${AWS::StackName}-instance" - Key: Environment Value: !Ref Environment UserData: Fn::Base64: | #!/bin/bash yum update -y systemctl enable httpd systemctl start httpd
InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: !Sub "${AWS::StackName}-sg" GroupDescription: Security group for instances VpcId: !Ref VPCId
MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref SubnetIds LaunchTemplate: LaunchTemplateId: !Ref MyLaunchTemplate Version: !GetAtt MyLaunchTemplate.LatestVersionNumber
Auto Scaling Groups
ASG with Load Balancer
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling group with Application Load Balancer
Resources: MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref PrivateSubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration TargetGroupARNs: - !Ref MyTargetGroup HealthCheckType: ELB HealthCheckGracePeriod: 300 TerminationPolicies: - OldestInstance - Default InstanceMaintenancePolicy: MinHealthyPercentage: 50 MaxHealthyPercentage: 200 Tags: - Key: Environment Value: !Ref Environment PropagateAtLaunch: true - Key: Name Value: !Sub "${AWS::StackName}-instance" PropagateAtLaunch: true
MyTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Name: !Sub "${AWS::StackName}-tg" Port: 80 Protocol: HTTP VpcId: !Ref VPCId HealthCheckPath: / HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 5 UnhealthyThresholdCount: 2 TargetType: instance
ASG with Launch Template and Mixed Instances
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling with Mixed Instances Policy
Resources: MyLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: !Sub "${AWS::StackName}-lt" LaunchTemplateData: ImageId: !Ref AmiId InstanceType: t3.micro KeyName: !Ref KeyName
MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref SubnetIds LaunchTemplate: LaunchTemplateId: !Ref MyLaunchTemplate Version: !GetAtt MyLaunchTemplate.LatestVersionNumber MixedInstancesPolicy: InstancesDistribution: OnDemandAllocationStrategy: prioritized OnDemandBaseCapacity: 2 OnDemandPercentageAboveBaseCapacity: 50 SpotAllocationStrategy: capacity-optimized SpotInstancePools: 3 SpotMaxPrice: !Ref MaxSpotPrice LaunchTemplate: LaunchTemplateId: !Ref MyLaunchTemplate Overrides: - InstanceType: t3.micro - InstanceType: t3.small - InstanceType: t3.medium
ASG with Lifecycle Hooks
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling with lifecycle hooks
Resources: MyLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: LaunchConfigurationName: !Sub "${AWS::StackName}-lc" ImageId: !Ref AmiId InstanceType: t3.micro
MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref SubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration
Lifecycle Hook - Instance Launch
LifecycleHookLaunch: Type: AWS::AutoScaling::LifecycleHook Properties: LifecycleHookName: !Sub "${AWS::StackName}-launch-hook" AutoScalingGroupName: !Ref MyAutoScalingGroup LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING HeartbeatTimeout: 900 NotificationTargetARN: !Ref SnsTopicArn RoleARN: !GetAtt LifecycleHookRole.Arn
Lifecycle Hook - Instance Termination
LifecycleHookTermination: Type: AWS::AutoScaling::LifecycleHook Properties: LifecycleHookName: !Sub "${AWS::StackName}-termination-hook" AutoScalingGroupName: !Ref MyAutoScalingGroup LifecycleTransition: autoscaling:EC2_INSTANCE_TERMINATING HeartbeatTimeout: 3600 NotificationTargetARN: !Ref SnsTopicArn RoleARN: !GetAtt LifecycleHookRole.Arn
IAM Role for Lifecycle Hooks
LifecycleHookRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-lifecycle-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: autoscaling.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-lifecycle-policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - sns:Publish Resource: !Ref SnsTopicArn
SnsTopic: Type: AWS::SNS::Topic Properties: TopicName: !Sub "${AWS::StackName}-lifecycle"
Scaling Policies
Target Tracking Policy
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling with Target Tracking scaling policy
Resources: MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref SubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration
TargetTrackingPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-target-tracking" PolicyType: TargetTrackingScaling AutoScalingGroupName: !Ref MyAutoScalingGroup TargetTrackingConfiguration: PredefinedMetricSpecification: PredefinedMetricType: ASGAverageCPUUtilization TargetValue: 70 DisableScaleIn: false
Step Scaling Policy
Resources: StepScalingPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-step-scaling" PolicyType: StepScaling AdjustmentType: PercentChangeInCapacity Cooldown: 300 StepAdjustments: - MetricIntervalLowerBound: 0 MetricIntervalUpperBound: 10000 ScalingAdjustment: 200 - MetricIntervalLowerBound: 10000 MetricIntervalUpperBound: 20000 ScalingAdjustment: 400 - MetricIntervalLowerBound: 20000 ScalingAdjustment: 600 AutoScalingGroupName: !Ref MyAutoScalingGroup
Alarm for Step Scaling
HighCpuAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "${AWS::StackName}-high-cpu" AlarmDescription: Alarm when CPU utilization is high MetricName: CPUUtilization Namespace: AWS/EC2 Dimensions: - Name: AutoScalingGroupName Value: !Ref MyAutoScalingGroup Statistic: Average Period: 60 EvaluationPeriods: 3 Threshold: 70 ComparisonOperator: GreaterThanThreshold AlarmActions: - !Ref StepScalingPolicy
Simple Scaling Policy
Resources: SimpleScalingPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-simple-scale-up" PolicyType: SimpleScaling AdjustmentType: ChangeInCapacity ScalingAdjustment: 1 Cooldown: 300 AutoScalingGroupName: !Ref MyAutoScalingGroup
ScaleDownPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-simple-scale-down" PolicyType: SimpleScaling AdjustmentType: ChangeInCapacity ScalingAdjustment: -1 Cooldown: 600 AutoScalingGroupName: !Ref MyAutoScalingGroup
HighCpuAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "${AWS::StackName}-high-cpu" MetricName: CPUUtilization Namespace: AWS/EC2 Dimensions: - Name: AutoScalingGroupName Value: !Ref MyAutoScalingGroup Statistic: Average Period: 120 EvaluationPeriods: 2 Threshold: 80 ComparisonOperator: GreaterThanThreshold AlarmActions: - !Ref SimpleScalingPolicy
LowCpuAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "${AWS::StackName}-low-cpu" MetricName: CPUUtilization Namespace: AWS/EC2 Dimensions: - Name: AutoScalingGroupName Value: !Ref MyAutoScalingGroup Statistic: Average Period: 300 EvaluationPeriods: 2 Threshold: 30 ComparisonOperator: LessThanThreshold AlarmActions: - !Ref ScaleDownPolicy
Scheduled Scaling
Resources: ScheduledScaleUp: Type: AWS::AutoScaling::ScheduledAction Properties: ScheduledActionName: !Sub "${AWS::StackName}-scheduled-scale-up" AutoScalingGroupName: !Ref MyAutoScalingGroup MinSize: 5 MaxSize: 15 DesiredCapacity: 5 StartTime: "2024-01-01T08:00:00Z"
ScheduledScaleDown: Type: AWS::AutoScaling::ScheduledAction Properties: ScheduledActionName: !Sub "${AWS::StackName}-scheduled-scale-down" AutoScalingGroupName: !Ref MyAutoScalingGroup MinSize: 2 MaxSize: 10 DesiredCapacity: 2 StartTime: "2024-01-01T20:00:00Z"
Recurring schedule using cron
RecurringScaleUp: Type: AWS::AutoScaling::ScheduledAction Properties: ScheduledActionName: !Sub "${AWS::StackName}-morning-scale-up" AutoScalingGroupName: !Ref MyAutoScalingGroup MinSize: 5 MaxSize: 15 DesiredCapacity: 5 Recurrence: "0 8 * * *"
ECS Auto Scaling
ECS Service Scaling
AWSTemplateFormatVersion: 2010-09-09 Description: ECS service with Auto Scaling
Resources:
ECS Cluster
EcsCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Sub "${AWS::StackName}-cluster"
Task Definition
TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: !Sub "${AWS::StackName}-task" Cpu: "512" Memory: "1024" NetworkMode: awsvpc RequiresCompatibilities: - FARGATE ContainerDefinitions: - Name: web Image: nginx:latest PortMappings: - ContainerPort: 80 LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref LogGroup awslogs-region: !Ref AWS::Region
ECS Service
EcsService: Type: AWS::ECS::Service Properties: ServiceName: !Sub "${AWS::StackName}-service" Cluster: !Ref EcsCluster TaskDefinition: !Ref TaskDefinition DesiredCount: 2 LaunchType: FARGATE NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - !Ref ServiceSecurityGroup Subnets: !Ref PrivateSubnets LoadBalancers: - ContainerName: web ContainerPort: 80 TargetGroupArn: !Ref TargetGroup
Application Auto Scaling Target
ScalableTarget: Type: AWS::ApplicationAutoScaling::ScalableTarget Properties: MaxCapacity: 10 MinCapacity: 2 ResourceId: !Sub "service/${EcsCluster}/${EcsService.Name}" RoleARN: !GetAtt EcsServiceScalingRole.Arn ScalableDimension: ecs:service:DesiredCount ServiceNamespace: ecs
Target Tracking Scaling Policy
EcsTargetTrackingPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-ecs-target-tracking" PolicyType: TargetTrackingScaling ScalingTargetId: !Ref ScalableTarget TargetTrackingScalingPolicyConfiguration: PredefinedMetricSpecification: PredefinedMetricType: ECSServiceAverageCPUUtilization TargetValue: 70 ScaleInCooldown: 300 ScaleOutCooldown: 60
Log Group
LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub "/ecs/${AWS::StackName}" RetentionInDays: 30
Security Group
ServiceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: !Sub "${AWS::StackName}-service-sg" GroupDescription: Security group for ECS service VpcId: !Ref VPCId
Application Load Balancer Target Group
TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Name: !Sub "${AWS::StackName}-ecs-tg" Port: 80 Protocol: HTTP VpcId: !Ref VPCId TargetType: ip
IAM Role for ECS Service Scaling with Least Privilege
EcsServiceScalingRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-ecs-scaling-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: application-autoscaling.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-ecs-scaling-policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - ecs:DescribeServices - ecs:UpdateService Resource: !Sub "arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:service/${EcsCluster}/*"
Lambda Provisioned Concurrency Scaling
Lambda with Provisioned Concurrency Auto Scaling
AWSTemplateFormatVersion: 2010-09-09 Description: Lambda with Application Auto Scaling for provisioned concurrency
Resources:
Lambda Function
MyLambdaFunction: Type: AWS::Lambda::Function Properties: FunctionName: !Sub "${AWS::StackName}-function" Runtime: python3.11 Handler: app.handler Code: S3Bucket: !Ref CodeBucket S3Key: lambda/function.zip MemorySize: 512 Timeout: 30 Role: !GetAtt LambdaExecutionRole.Arn
Lambda Version
LambdaVersion: Type: AWS::Lambda::Version Properties: FunctionName: !Ref MyLambdaFunction Description: Version for provisioned concurrency
Application Auto Scaling Scalable Target
LambdaScalableTarget: Type: AWS::ApplicationAutoScaling::ScalableTarget Properties: MaxCapacity: 20 MinCapacity: 5 ResourceId: !Sub "function:${MyLambdaFunction}:${LambdaVersion.Version}" RoleARN: !GetAtt LambdaScalingRole.Arn ScalableDimension: lambda:function:ProvisionedConcurrency ServiceNamespace: lambda
Target Tracking Scaling Policy
LambdaTargetTrackingPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy Properties: PolicyName: !Sub "${AWS::StackName}-lambda-target-tracking" PolicyType: TargetTrackingScaling ScalingTargetId: !Ref LambdaScalableTarget TargetTrackingScalingPolicyConfiguration: TargetValue: 90 PredefinedMetricSpecification: PredefinedMetricType: LambdaProvisionedConcurrencyUtilization ScaleInCooldown: 120 ScaleOutCooldown: 60
Lambda Execution Role
LambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-lambda-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
IAM Role for Lambda Scaling with Least Privilege
LambdaScalingRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-lambda-scaling-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: application-autoscaling.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-lambda-scaling-policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - lambda:PutProvisionedConcurrencyConfig - lambda:GetProvisionedConcurrencyConfig Resource: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${MyLambdaFunction}:*"
Conditions and Transform
Conditions for Environment-Specific Scaling
AWSTemplateFormatVersion: 2010-09-09 Description: Auto Scaling with conditional scaling configuration
Parameters: Environment: Type: String Default: dev AllowedValues: - dev - staging - production
Conditions: IsProduction: !Equals [!Ref Environment, production] IsStaging: !Equals [!Ref Environment, staging] UseSpot: !Or [!Equals [!Ref Environment, dev], !Equals [!Ref Environment, staging]] UseAlb: !Not [!Equals [!Ref Environment, dev]] EnableDetailedMonitoring: !Not [!Equals [!Ref Environment, dev]]
Resources: MyLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: LaunchConfigurationName: !Sub "${AWS::StackName}-lc" ImageId: !Ref AmiId InstanceType: !If [IsProduction, t3.large, !If [IsStaging, t3.medium, t3.micro]] InstanceMonitoring: !If [EnableDetailedMonitoring, Enabled, Basic]
MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: !If [IsProduction, 3, !If [IsStaging, 2, 1]] MaxSize: !If [IsProduction, 12, !If [IsStaging, 6, 3]] DesiredCapacity: !If [IsProduction, 3, !If [IsStaging, 2, 1]] VPCZoneIdentifier: !Ref SubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration HealthCheckType: !If [UseAlb, ELB, EC2] HealthCheckGracePeriod: !If [UseAlb, 300, 300]
Transform for Code Reuse
AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::Serverless-2016-10-31
Description: Using SAM for simplified Auto Scaling
Globals: Function: Timeout: 30 Runtime: python3.11 Tracing: Active Environment: Variables: LOG_LEVEL: INFO
Parameters: Environment: Type: String Default: dev
Resources:
Auto Scaling Group using SAM
WebServerGroup: Type: AWS::Serverless::Application Properties: Location: ./asg-template.yaml Parameters: Environment: !Ref Environment
CloudFormation Stack Management Best Practices
Stack Policies
Stack Policies prevent unintentional updates to critical stack resources. Use them to protect Auto Scaling Groups from accidental modifications or deletions.
AWSTemplateFormatVersion: 2010-09-09 Description: Stack with policy to protect Auto Scaling resources
Resources: MyAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${AWS::StackName}-asg" MinSize: 2 MaxSize: 10 DesiredCapacity: 2 VPCZoneIdentifier: !Ref SubnetIds LaunchConfigurationName: !Ref MyLaunchConfiguration
MyLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: LaunchConfigurationName: !Sub "${AWS::StackName}-lc" ImageId: !Ref AmiId InstanceType: t3.micro
Metadata: AWS::CloudFormation::StackPolicy: Statement: - Effect: Allow Resource: "" Action: Update:Modify - Effect: Deny Resource: "" Action: Update:Delete Condition: StringEquals: ResourceType: - AWS::AutoScaling::AutoScalingGroup - AWS::AutoScaling::LaunchConfiguration
Termination Protection
Enable termination protection to prevent accidental deletion of Auto Scaling Groups. This is critical for production environments.
Enable termination protection on an existing stack
aws cloudformation update-termination-protection
--stack-name my-auto-scaling-stack
--enable-termination-protection
Check if termination protection is enabled
aws cloudformation describe-stacks
--stack-name my-auto-scaling-stack
--query "Stacks[0].EnableTerminationProtection"
Drift Detection
Detect when your Auto Scaling infrastructure has been modified outside of CloudFormation.
Detect drift on a stack
aws cloudformation detect-stack-drift
--stack-name my-auto-scaling-stack
Get drift detection status
aws cloudformation describe-stack-drift-detection-status
--stack-name my-auto-scaling-stack
Get drift detection results
aws cloudformation describe-stack-resource-drifts
--stack-name my-auto-scaling-stack
Check specific resource drift
aws cloudformation describe-stack-resource-drifts
--stack-name my-auto-scaling-stack
--stack-resource-drifts-not-in-sync
Change Sets
Use Change Sets to preview and review changes before applying them to your Auto Scaling infrastructure.
Create a change set
aws cloudformation create-change-set
--stack-name my-auto-scaling-stack
--change-set-name my-changeset
--template-body file://template.yaml
--parameters ParameterKey=Environment,ParameterValue=production
List change sets
aws cloudformation list-change-sets
--stack-name my-auto-scaling-stack
Describe change set
aws cloudformation describe-change-set
--stack-name my-auto-scaling-stack
--change-set-name my-changeset
Execute change set
aws cloudformation execute-change-set
--stack-name my-auto-scaling-stack
--change-set-name my-changeset
Automated change set creation in CI/CD pipeline
Resources: ChangeSetRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: cloudformation.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ChangeSetPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - autoscaling:Describe* - cloudwatch:Describe* - ec2:Describe* Resource: "" - Effect: Allow Action: - autoscaling:UpdateAutoScalingGroup - autoscaling:CreateOrUpdateTags - cloudwatch:PutMetricAlarm - cloudwatch:DeleteAlarms Resource: - !Sub "arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup::autoScalingGroupName/" - !Sub "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:"
Best Practices
High Availability
-
Distribute instances across multiple AZs
-
Use ALB with health checks for automatic routing
-
Implement lifecycle hooks for graceful shutdown
-
Configure appropriate termination policies
-
Use mixed instances policies for diversity
Cost Optimization
-
Use Spot Instances for fault-tolerant workloads
-
Implement right-sizing of instances
-
Configure aggressive scale-in policies
-
Use scheduled scaling for predictable patterns
-
Monitor and optimize regularly
Monitoring
-
Create CloudWatch Alarms for key metrics
-
Implement scaling policies based on metrics
-
Use lifecycle hooks for logging and analytics
-
Configure SNS notifications for scaling events
-
Implement detailed monitoring for troubleshooting
Security
-
Use IAM roles with minimum permissions
-
Encrypt EBS volumes with KMS
-
Configure restrictive security groups
-
Use VPC with appropriate subnets
-
Implement parameter store for sensitive configuration
-
Avoid using broad managed policies like CloudWatchFullAccess
-
Use specific permissions instead of broad managed policies
Least Privilege IAM Examples
Instead of CloudWatchFullAccess, use specific permissions
ScalingAlarmRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${AWS::StackName}-scaling-alarm-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: autoscaling.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-cloudwatch-specific-policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - cloudwatch:PutMetricAlarm - cloudwatch:DescribeAlarms - cloudwatch:DeleteAlarms - cloudwatch:EnableAlarmActions - cloudwatch:DisableAlarmActions Resource: !Sub "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
Related Resources
-
Auto Scaling Documentation
-
AWS CloudFormation User Guide
-
Auto Scaling Best Practices
-
Application Auto Scaling
Additional Files
For complete details on resources and their properties, consult:
-
REFERENCE.md - Detailed reference guide for all CloudFormation resources
-
EXAMPLES.md - Complete production-ready examples