概要
Fargate Spot
はSpotインスタンスのFargate版です。
予期せぬシャットダウンの可能性があるものの、通常の7割引の料金で使えます。
ほとんどの場合、開発/検証環境ではこれが活用可能ではないでしょうか。
実装
1. ECSクラスターにDefaultCapacityProviderStrategy
を設定
ECS-Cluster.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: ECS cluster
Parameters:
EnvironmentName:
Type: String
Default: staging
Resources:
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub ${EnvironmentName}-ecs-cluster
CapacityProviders:
- FARGATE
- FARGATE_SPOT
DefaultCapacityProviderStrategy: # schedule only Fargate_Spot
- CapacityProvider: FARGATE_SPOT
Weight: 1
Outputs:
ECSClusterName:
Description: The Name of the ECS cluster
Value: !Ref ECSCluster
Export:
Name: !Sub ${EnvironmentName}:ECSClusterName
ECSClusterArn:
Description: The ARN of the ECS cluster
Value: !GetAtt ECSCluster.Arn
Export:
Name: !Sub ${EnvironmentName}:ECSClusterArn
2. ECSサービスにオートスケーリング設定を追加
サービスのCapacityProviderStrategy
およびにLaunchType
を指定しない場合、クラスターのDefaultCapacityProviderStrategy
が適用されます。
ECS-Service.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: ECS service and auto scaling
Parameters:
EnvironmentName:
Type: String
Default: staging
ServiceName:
Type: String
Default: my-service
ImageUrl:
Type: String
Default: <your-docker-image-url>
Description: The url of docker image at ECR
ContainerPort:
Type: Number
Default: 3000
Description: What port number the application inside the docker container is binding to
ContainerCpu:
Type: Number
Default: 256
Description: How much CPU to give the container. 1024 is 1 CPU
ContainerMemory:
Type: Number
Default: 512
Description: How much memory in megabytes to give the container
DesiredCount:
Type: Number
Default: 2
Description: How many copies of the service task to run
TaskMaxContainerCount:
Type: Number
Description: Maximum number of containers to run for the service when auto scaling out
Default: 10
MinValue: 1
ConstraintDescription: Value must be at least one
ServiceScaleEvaluationPeriods:
Description: The number of periods over which data is compared to the specified threshold
Type: Number
Default: 2
MinValue: 2
ServiceCpuScaleOutThreshold:
Type: Number
Description: Average CPU value to trigger auto scaling out
Default: 50
MinValue: 0
MaxValue: 100
ConstraintDescription: Value must be between 0 and 100
ServiceCpuScaleInThreshold:
Type: Number
Description: Average CPU value to trigger auto scaling in
Default: 25
MinValue: 0
MaxValue: 100
ConstraintDescription: Value must be between 0 and 100
Resources:
# Service
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub ${EnvironmentName}-service-${ServiceName}
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Ref ServiceName
Cpu: !Ref ContainerCpu
Memory: !Ref ContainerMemory
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !Ref ECSTaskExecutionRole
TaskRoleArn: !Ref ECSTaskRole
ContainerDefinitions:
- Name: !Ref ServiceName
Cpu: !Ref ContainerCpu
Memory: !Ref ContainerMemory
Essential: true
Image: !Ref ImageUrl
PortMappings:
- ContainerPort: !Ref ContainerPort
LinuxParameters:
InitProcessEnabled: true
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Sub ${EnvironmentName}-service-${ServiceName}
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: !Ref ServiceName
Service:
Type: AWS::ECS::Service
Properties:
ServiceName: !Ref ServiceName
Cluster:
Fn::ImportValue: !Sub ${EnvironmentName}:ECSClusterArn
# LaunchType: FARGATE # omit this to use DefaultCapacityProviderStrategy
EnableExecuteCommand: true
DeploymentConfiguration:
DeploymentCircuitBreaker:
Enable: true
Rollback: true
MaximumPercent: 200
MinimumHealthyPercent: 75
DesiredCount: !Ref DesiredCount
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: DISABLED # no public ip is needed
SecurityGroups:
- !Ref EcsTaskSecurityGroupId
Subnets:
- !Ref PrivateSubnet1
TaskDefinition: !Ref TaskDefinition
ServiceRegistries:
- RegistryArn: !GetAtt ServiceDiscovery.Arn
Port: !Ref ContainerPort
# AutoScaling
ServiceScalingTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn:
- Service
Properties:
MinCapacity: !Ref DesiredCount
MaxCapacity: !Ref TaskMaxContainerCount
ResourceId: !Sub
- service/${ECSClusterName}/${ECSServiceName}
- ECSClusterName:
Fn::ImportValue: !Sub ${EnvironmentName}:ECSClusterName
ECSServiceName: !Ref ServiceName
RoleARN: !Ref AutoscalingRole
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs
ServiceScaleOutPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: !Sub ${EnvironmentName}-${ServiceName}-ScaleOutPolicy
PolicyType: StepScaling
ScalingTargetId: !Ref ServiceScalingTarget
StepScalingPolicyConfiguration:
AdjustmentType: ChangeInCapacity
Cooldown: 60
MetricAggregationType: Average
StepAdjustments:
- ScalingAdjustment: 1
MetricIntervalLowerBound: 0
DependsOn: ServiceScalingTarget
ServiceScaleInPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: !Sub ${EnvironmentName}-${ServiceName}-ScaleInPolicy
PolicyType: StepScaling
ScalingTargetId: !Ref ServiceScalingTarget
StepScalingPolicyConfiguration:
AdjustmentType: ChangeInCapacity
Cooldown: 60
MetricAggregationType: Average
StepAdjustments:
- ScalingAdjustment: -1
MetricIntervalUpperBound: 0
DependsOn: ServiceScalingTarget
ServiceScaleOutAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub ${EnvironmentName}-${ServiceName}-ScaleOutAlarm
EvaluationPeriods: !Ref ServiceScaleEvaluationPeriods
Statistic: Average
TreatMissingData: notBreaching
Threshold: !Ref ServiceCpuScaleOutThreshold
AlarmDescription: Alarm to add capacity if CPU is high
Period: 60
AlarmActions:
- !Ref ServiceScaleOutPolicy
Namespace: AWS/ECS
Dimensions:
- Name: ClusterName
Value:
Fn::ImportValue: !Sub ${EnvironmentName}:ECSClusterName
- Name: ServiceName
Value: !Ref ServiceName
ComparisonOperator: GreaterThanThreshold
MetricName: CPUUtilization
DependsOn:
- ServiceScaleOutPolicy
ServiceScaleInAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub ${EnvironmentName}-${ServiceName}-ScaleInAlarm
EvaluationPeriods: !Ref ServiceScaleEvaluationPeriods
Statistic: Average
TreatMissingData: notBreaching
Threshold: !Ref ServiceCpuScaleInThreshold
AlarmDescription: Alarm to reduce capacity if container CPU is low
Period: 300
AlarmActions:
- !Ref ServiceScaleInPolicy
Namespace: AWS/ECS
Dimensions:
- Name: ClusterName
Value:
Fn::ImportValue: !Sub ${EnvironmentName}:ECSClusterName
- Name: ServiceName
Value: !Ref ServiceName
ComparisonOperator: LessThanThreshold
MetricName: CPUUtilization
DependsOn:
- ServiceScaleInPolicy
3. 確認
下記コマンドでタスクのcapacityProvider
を確認できます。
$ aws ecs describe-tasks
--cluster <Cluster_name> \
--tasks <TaskID> \
--region <Region>
参考
下記大変参考にさせていただきました。