December 4, 2024

AWS ECS, EC2, and Warm Pools: advantages and gotchas

  • tutorial
Warmed up and ready to join the game

Fargate vs. EC2 Auto Scaling groups

Fantastic warm pools and where to find them

Configuring warm pools

Create warm pool button
Warm pool settings
Warm pool instances
EC2AutoScalingGroupWarmPool:
Type: AWS::AutoScaling::WarmPool
Properties:
AutoScalingGroupName: !Ref 'EC2AutoScalingGroup'
InstanceReusePolicy:
ReuseOnScaleIn: false

Gotcha #1: Premature registration in ECS

Agent disconnected warning
echo "ECS_WARM_POOLS_CHECK=true" >> /etc/ecs/ecs.config
[settings.autoscaling]
should-wait = true

Gotcha #2: The trap of the "Reuse on scale in" option

Admiral Ackbar: It's A Trap

Gotcha #3: AWS CloudFormation and UpdatePolicy

The first try: AutoScalingRollingUpdate

EC2AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
...
UpdatePolicy:
AutoScalingRollingUpdate:
MinInstancesInService: 1
MaxBatchSize: 1
PauseTime: PT15M
SuspendProcesses:
- HealthCheck
- ReplaceUnhealthy
- AZRebalance
- AlarmNotification
- ScheduledActions
WaitOnResourceSignals: true
Christopher Walken: I don't know

The second try: AutoScalingReplacingUpdate

EC2AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
...
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: true

A moment of despair

The third try: A custom resource

# The IAM role for the Lambda function.
# It should have permission to start instance refreshes.
InstanceRefresherLambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-instance-refresher"
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
Policies:
- PolicyName: "autoscaling-start-instance-refresh"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- autoscaling:StartInstanceRefresh
Resource: "*"
# The Lambda function that will start the instance refresh on update or create.
# It will be triggered by the custom resource and requires the
# AutoScalingGroupName parameter.
InstanceRefresherLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-instance-refresher"
Runtime: "python3.12"
Handler: "index.handler"
Role: !GetAtt "InstanceRefresherLambdaRole.Arn"
Timeout: 30
Code:
ZipFile: |
import cfnresponse
import json
import boto3
client = boto3.client('autoscaling')
def handler(event, context):
response_data = {}
try:
if event['RequestType'] != 'Create' and event['RequestType'] != 'Update':
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data, 'InstanceRefresher')
return
response = client.start_instance_refresh(
AutoScalingGroupName=event['ResourceProperties']['AutoScalingGroupName'],
Preferences={
'MinHealthyPercentage': 100,
'MaxHealthyPercentage': 200,
'SkipMatching': True,
'ScaleInProtectedInstances': 'Ignore',
'StandbyInstances': 'Ignore'
}
)
response_data['InstanceRefreshId'] = response['InstanceRefreshId']
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data, 'InstanceRefresher')
except Exception as e:
response_data['exception'] = e.__str__()
cfnresponse.send(event, context, cfnresponse.FAILED, response_data, 'InstanceRefresher')
EC2InstanceRefresher:
Type: Custom::InstanceRefresher
Properties:
ServiceToken: !GetAtt "InstanceRefresherLambda.Arn"
ServiceTimeout: '60'
AutoScalingGroupName: !Ref "EC2AutoScalingGroup"
# The Lambda function doesn't actually need EC2LaunchTemplate.
# But we include it here to force the custom resource to run
# when the Launch Template is updated.
LaunchTemplate: !Ref "EC2LaunchTemplate"
LaunchTemplateVersion: !GetAtt "EC2LaunchTemplate.LatestVersionNumber"

Resizeable image

Start your free trial today:

Get imgproxy Pro on Cloud Marketplace: