Skip to content
Permalink
Branch: master
Find file Copy path
2 contributors

Users who have contributed to this file

@sandrokeil @andreaswittig
676 lines (675 sloc) 24.2 KB
---
# Copyright 2019 widdix GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# FIXME add to cfn-modules
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Fargate: service that runs on a Fargate cluster based on fargate/cluster.yaml with service discovery via Cloud Map, a cloudonaut.io template'
Metadata:
'AWS::CloudFormation::Interface':
ParameterGroups:
- Label:
default: 'Parent Stacks'
Parameters:
- ParentVPCStack
- ParentClusterStack
- ParentAlertStack
- ParentCloudMapStack
- ParentClientStack
- ParentClientStack1
- ParentClientStack2
- ParentClientStack3
- ParentSSHBastionStack
- Label:
default: 'Task Parameters'
Parameters:
- TaskPolicies
- AmbassadorImage
- AmbassadorCommand
- AmbassadorPort
- AmbassadorEnvironment1Key
- AmbassadorEnvironment1Value
- AmbassadorEnvironment2Key
- AmbassadorEnvironment2Value
- AmbassadorEnvironment3Key
- AmbassadorEnvironment3Value
- AppImage
- AppCommand
- AppPort
- AppEnvironment1Key
- AppEnvironment1Value
- AppEnvironment2Key
- AppEnvironment2Value
- AppEnvironment3Key
- AppEnvironment3Value
- SidecarImage
- SidecarCommand
- SidecarPort
- SidecarEnvironment1Key
- SidecarEnvironment1Value
- SidecarEnvironment2Key
- SidecarEnvironment2Value
- SidecarEnvironment3Key
- SidecarEnvironment3Value
- Label:
default: 'Service Parameters'
Parameters:
- Name
- Cpu
- Memory
- SubnetsReach
- AutoScaling
- DesiredCount
- MaxCapacity
- MinCapacity
- LogsRetentionInDays
Parameters:
ParentVPCStack:
Description: 'Stack name of parent VPC stack based on vpc/vpc-*azs.yaml template.'
Type: String
ParentClusterStack:
Description: 'Stack name of parent Cluster stack based on fargate/cluster.yaml template.'
Type: String
ParentAlertStack:
Description: 'Optional but recommended stack name of parent alert stack based on operations/alert.yaml template.'
Type: String
Default: ''
ParentCloudMapStack:
Description: 'Stack name of parent Cloud Map stack based on vpc/cloudmap-private.yaml template.'
Type: String
ParentClientStack:
Description: 'Stack name of parent client stack based on state/client-sg.yaml template.'
Type: String
ParentClientStack1:
Description: 'Optional stack name of parent Client Security Group stack based on state/client-sg.yaml template to allow network access from the service to whatever uses the client security group.'
Type: String
Default: ''
ParentClientStack2:
Description: 'Optional stack name of parent Client Security Group stack based on state/client-sg.yaml template to allow network access from the service to whatever uses the client security group.'
Type: String
Default: ''
ParentClientStack3:
Description: 'Optional stack name of parent Client Security Group stack based on state/client-sg.yaml template to allow network access from the service to whatever uses the client security group.'
Type: String
Default: ''
ParentSSHBastionStack:
Description: 'Optional but recommended stack name of parent SSH bastion host/instance stack based on vpc/vpc-*-bastion.yaml template.'
Type: String
Default: ''
TaskPolicies:
Description: 'Comma-delimited list of IAM managed policy ARNs to attach to the task IAM role'
Type: String
Default: ''
AmbassadorImage:
Description: 'Optional Docker image to use for the ambassador container (https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador). You can use images in the Docker Hub registry or specify other repositories (repository-url/image:tag).'
Type: String
Default: ''
AmbassadorCommand:
Description: 'Optional command used when starting the ambassador container.'
Type: String
Default: ''
AmbassadorPort:
Description: 'The port exposed by the ambassador container that receives traffic from the load balancer (AmbassadorPort <> AppPort <> SidecarPort; ignored if AmbassadorImage is not set).'
Type: Number
Default: 8000
MinValue: 1
MaxValue: 49150
AmbassadorEnvironment1Key:
Description: 'Optional environment variable 1 key for ambassador container.'
Type: String
Default: ''
AmbassadorEnvironment1Value:
Description: 'Optional environment variable 1 value for ambassador container.'
Type: String
Default: ''
AmbassadorEnvironment2Key:
Description: 'Optional environment variable 2 key for ambassador container.'
Type: String
Default: ''
AmbassadorEnvironment2Value:
Description: 'Optional environment variable 2 value for ambassador container.'
Type: String
Default: ''
AmbassadorEnvironment3Key:
Description: 'Optional environment variable 3 key for ambassador container.'
Type: String
Default: ''
AmbassadorEnvironment3Value:
Description: 'Optional environment variable 3 value for ambassador container.'
Type: String
Default: ''
AppImage:
Description: 'The Docker image to use for the app container. You can use images in the Docker Hub registry or specify other repositories (repository-url/image:tag).'
Type: String
Default: 'widdix/hello:v1'
AppCommand:
Description: 'Optional commands (comma-delimited) used when starting the app container.'
Type: String
Default: ''
AppPort:
Description: 'The port exposed by the app container that receives traffic from the load balancer or the ambassador container (AppPort <> AmbassadorPort <> SidecarPort).'
Type: Number
Default: 80
MinValue: 1
MaxValue: 49150
AppEnvironment1Key:
Description: 'Optional environment variable 1 key for app container.'
Type: String
Default: ''
AppEnvironment1Value:
Description: 'Optional environment variable 1 value for app container.'
Type: String
Default: ''
AppEnvironment2Key:
Description: 'Optional environment variable 2 key for app container.'
Type: String
Default: ''
AppEnvironment2Value:
Description: 'Optional environment variable 2 value for app container.'
Type: String
Default: ''
AppEnvironment3Key:
Description: 'Optional environment variable 3 key for app container.'
Type: String
Default: ''
AppEnvironment3Value:
Description: 'Optional environment variable 3 value for app container.'
Type: String
Default: ''
SidecarImage:
Description: 'Optional Docker image to use for the sidecar container (https://docs.microsoft.com/en-us/azure/architecture/patterns/sidecar). You can use images in the Docker Hub registry or specify other repositories (repository-url/image:tag).'
Type: String
Default: ''
SidecarCommand:
Description: 'Optional command used when starting the sidecar container.'
Type: String
Default: ''
SidecarPort:
Description: 'The port exposed by the sidecar container reachable from the app container on host localhost (SidecarPort <> AmbassadorPort <> AppPort).'
Type: Number
Default: 9000
MinValue: 1
MaxValue: 49150
SidecarEnvironment1Key:
Description: 'Optional environment variable 1 key for sidecar container.'
Type: String
Default: ''
SidecarEnvironment1Value:
Description: 'Optional environment variable 1 value for sidecar container.'
Type: String
Default: ''
SidecarEnvironment2Key:
Description: 'Optional environment variable 2 key for sidecar container.'
Type: String
Default: ''
SidecarEnvironment2Value:
Description: 'Optional environment variable 2 value for sidecar container.'
Type: String
Default: ''
SidecarEnvironment3Key:
Description: 'Optional environment variable 3 key for sidecar container.'
Type: String
Default: ''
SidecarEnvironment3Value:
Description: 'Optional environment variable 3 value for sidecar container.'
Type: String
Default: ''
Name:
Description: 'The name of the service used for service discovery (Cloud Map).'
Type: String
Cpu:
Description: 'The minimum number of vCPUs to reserve for the container.'
Type: String
Default: '0.25'
AllowedValues: ['0.25', '0.5', '1', '2', '4']
Memory:
Description: 'The amount (in GB) of memory used by the task.'
Type: String
Default: '0.5'
AllowedValues: ['0.5', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30']
DesiredCount:
Description: 'The number of simultaneous tasks, that you want to run on the cluster.'
Type: Number
Default: 2
ConstraintDescription: 'Must be >= 1'
MinValue: 1
MaxCapacity:
Description: 'The maximum number of simultaneous tasks, that you want to run on the cluster.'
Type: Number
Default: 4
ConstraintDescription: 'Must be >= 1'
MinValue: 1
MinCapacity:
Description: 'The minimum number of simultaneous tasks, that you want to run on the cluster.'
Type: Number
Default: 2
ConstraintDescription: 'Must be >= 1'
MinValue: 1
LogsRetentionInDays:
Description: 'Specifies the number of days you want to retain log events in the specified log group.'
Type: Number
Default: 14
AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
SubnetsReach:
Description: 'Should the service have direct access to the Internet or do you prefer private subnets with NAT?'
Type: String
Default: Public
AllowedValues:
- Public
- Private
AutoScaling:
Description: 'Scale number of tasks based on CPU load?'
Type: String
Default: 'true'
AllowedValues: ['true', 'false']
Mappings:
CpuMap:
'0.25':
Cpu: 256
'0.5':
Cpu: 512
'1':
Cpu: 1024
'2':
Cpu: 2048
'4':
Cpu: 4096
MemoryMap:
'0.5':
Memory: 512
'1':
Memory: 1024
'2':
Memory: 2048
'3':
Memory: 3072
'4':
Memory: 4096
'5':
Memory: 5120
'6':
Memory: 6144
'7':
Memory: 7168
'8':
Memory: 8192
'9':
Memory: 9216
'10':
Memory: 10240
'11':
Memory: 11264
'12':
Memory: 12288
'13':
Memory: 13312
'14':
Memory: 14336
'15':
Memory: 15360
'16':
Memory: 16384
'17':
Memory: 17408
'18':
Memory: 18432
'19':
Memory: 19456
'20':
Memory: 20480
'21':
Memory: 21504
'22':
Memory: 22528
'23':
Memory: 23552
'24':
Memory: 24576
'25':
Memory: 25600
'26':
Memory: 26624
'27':
Memory: 27648
'28':
Memory: 28672
'29':
Memory: 29696
'30':
Memory: 30720
Conditions:
HasAlertTopic: !Not [!Equals [!Ref ParentAlertStack, '']]
HasSubnetsReachPublic: !Equals [!Ref SubnetsReach, Public]
HasAutoScaling: !Equals [!Ref AutoScaling, 'true']
HasClientSecurityGroup1: !Not [!Equals [!Ref ParentClientStack1, '']]
HasClientSecurityGroup2: !Not [!Equals [!Ref ParentClientStack2, '']]
HasClientSecurityGroup3: !Not [!Equals [!Ref ParentClientStack3, '']]
HasSSHBastionSecurityGroup: !Not [!Equals [!Ref ParentSSHBastionStack, '']]
HasTaskPolicies: !Not [!Equals [!Ref TaskPolicies, '']]
HasAppCommand: !Not [!Equals [!Ref AppCommand, '']]
HasAppEnvironment1Key: !Not [!Equals [!Ref AppEnvironment1Key, '']]
HasAppEnvironment2Key: !Not [!Equals [!Ref AppEnvironment2Key, '']]
HasAppEnvironment3Key: !Not [!Equals [!Ref AppEnvironment3Key, '']]
HasAmbassadorImage: !Not [!Equals [!Ref AmbassadorImage, '']]
HasAmbassadorCommand: !Not [!Equals [!Ref AmbassadorCommand, '']]
HasAmbassadorEnvironment1Key: !Not [!Equals [!Ref AmbassadorEnvironment1Key, '']]
HasAmbassadorEnvironment2Key: !Not [!Equals [!Ref AmbassadorEnvironment2Key, '']]
HasAmbassadorEnvironment3Key: !Not [!Equals [!Ref AmbassadorEnvironment3Key, '']]
HasSidecarImage: !Not [!Equals [!Ref SidecarImage, '']]
HasSidecarCommand: !Not [!Equals [!Ref SidecarCommand, '']]
HasSidecarEnvironment1Key: !Not [!Equals [!Ref SidecarEnvironment1Key, '']]
HasSidecarEnvironment2Key: !Not [!Equals [!Ref SidecarEnvironment2Key, '']]
HasSidecarEnvironment3Key: !Not [!Equals [!Ref SidecarEnvironment3Key, '']]
Resources:
ServiceDiscovery:
Type: 'AWS::ServiceDiscovery::Service'
Properties:
Description: !Ref 'AWS::StackName'
DnsConfig:
DnsRecords:
- Type: A
TTL: '30'
- Type: SRV
TTL: '30'
NamespaceId: {'Fn::ImportValue': !Sub '${ParentCloudMapStack}-NamespaceID'}
RoutingPolicy: MULTIVALUE
HealthCheckCustomConfig:
FailureThreshold: 1
Name: !Ref Name
NamespaceId: {'Fn::ImportValue': !Sub '${ParentCloudMapStack}-NamespaceID'}
TaskExecutionRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: 'ecs-tasks.amazonaws.com'
Action: 'sts:AssumeRole'
Policies:
- PolicyName: AmazonECSTaskExecutionRolePolicy # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'ecr:GetAuthorizationToken'
- 'ecr:BatchCheckLayerAvailability'
- 'ecr:GetDownloadUrlForLayer'
- 'ecr:BatchGetImage'
Resource: '*'
- Effect: Allow
Action:
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource: !GetAtt 'LogGroup.Arn'
TaskRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: 'ecs-tasks.amazonaws.com'
Action: 'sts:AssumeRole'
ManagedPolicyArns: !If [HasTaskPolicies, !Split [',', !Ref TaskPolicies], !Ref 'AWS::NoValue']
TaskDefinition:
Type: 'AWS::ECS::TaskDefinition'
Properties:
ContainerDefinitions:
- !If
- HasAmbassadorImage
- Name: ambassador
Image: !Ref AmbassadorImage
Command: !If [HasAmbassadorCommand, !Ref AmbassadorCommand, !Ref 'AWS::NoValue']
PortMappings:
- ContainerPort: !Ref AmbassadorPort
Protocol: tcp
Essential: true
LogConfiguration:
LogDriver: awslogs
Options:
'awslogs-region': !Ref 'AWS::Region'
'awslogs-group': !Ref LogGroup
'awslogs-stream-prefix': ambassador
Environment:
- !If [HasAmbassadorEnvironment1Key, {Name: !Ref AmbassadorEnvironment1Key, Value: !Ref AmbassadorEnvironment1Value}, !Ref 'AWS::NoValue']
- !If [HasAmbassadorEnvironment2Key, {Name: !Ref AmbassadorEnvironment2Key, Value: !Ref AmbassadorEnvironment2Value}, !Ref 'AWS::NoValue']
- !If [HasAmbassadorEnvironment3Key, {Name: !Ref AmbassadorEnvironment3Key, Value: !Ref AmbassadorEnvironment3Value}, !Ref 'AWS::NoValue']
- !Ref 'AWS::NoValue'
- Name: app
Image: !Ref AppImage
Command: !If [HasAppCommand, !Split [',', !Ref AppCommand], !Ref 'AWS::NoValue']
PortMappings:
- ContainerPort: !Ref AppPort
Protocol: tcp
Essential: true
LogConfiguration:
LogDriver: awslogs
Options:
'awslogs-region': !Ref 'AWS::Region'
'awslogs-group': !Ref LogGroup
'awslogs-stream-prefix': app
Environment:
- !If [HasAppEnvironment1Key, {Name: !Ref AppEnvironment1Key, Value: !Ref AppEnvironment1Value}, !Ref 'AWS::NoValue']
- !If [HasAppEnvironment2Key, {Name: !Ref AppEnvironment2Key, Value: !Ref AppEnvironment2Value}, !Ref 'AWS::NoValue']
- !If [HasAppEnvironment3Key, {Name: !Ref AppEnvironment3Key, Value: !Ref AppEnvironment3Value}, !Ref 'AWS::NoValue']
- !If
- HasSidecarImage
- Name: sidecar
Image: !Ref SidecarImage
Command: !If [HasSidecarCommand, !Ref SidecarCommand, !Ref 'AWS::NoValue']
PortMappings:
- ContainerPort: !Ref SidecarPort
Protocol: tcp
Essential: true
LogConfiguration:
LogDriver: awslogs
Options:
'awslogs-region': !Ref 'AWS::Region'
'awslogs-group': !Ref LogGroup
'awslogs-stream-prefix': sidecar
Environment:
- !If [HasSidecarEnvironment1Key, {Name: !Ref SidecarEnvironment1Key, Value: !Ref SidecarEnvironment1Value}, !Ref 'AWS::NoValue']
- !If [HasSidecarEnvironment2Key, {Name: !Ref SidecarEnvironment2Key, Value: !Ref SidecarEnvironment2Value}, !Ref 'AWS::NoValue']
- !If [HasSidecarEnvironment3Key, {Name: !Ref SidecarEnvironment3Key, Value: !Ref SidecarEnvironment3Value}, !Ref 'AWS::NoValue']
- !Ref 'AWS::NoValue'
Cpu: !FindInMap [CpuMap, !Ref Cpu, Cpu]
ExecutionRoleArn: !GetAtt 'TaskExecutionRole.Arn'
Family: !Ref 'AWS::StackName'
Memory: !FindInMap [MemoryMap, !Ref Memory, Memory]
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
TaskRoleArn: !GetAtt 'TaskRole.Arn'
LogGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
RetentionInDays: !Ref LogsRetentionInDays
ServiceSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: !Sub '${AWS::StackName}-service'
VpcId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC'}
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !If [HasAmbassadorImage, !Ref AmbassadorPort, !Ref AppPort]
ToPort: !If [HasAmbassadorImage, !Ref AmbassadorPort, !Ref AppPort]
SourceSecurityGroupId: {'Fn::ImportValue': !Sub '${ParentClientStack}-ClientSecurityGroup'}
ServiceSecurityGroupInSSHBastion:
Type: 'AWS::EC2::SecurityGroupIngress'
Condition: HasSSHBastionSecurityGroup
Properties:
GroupId: !Ref ServiceSecurityGroup
IpProtocol: tcp
FromPort: !If [HasAmbassadorImage, !Ref AmbassadorPort, !Ref AppPort]
ToPort: !If [HasAmbassadorImage, !Ref AmbassadorPort, !Ref AppPort]
SourceSecurityGroupId: {'Fn::ImportValue': !Sub '${ParentSSHBastionStack}-SecurityGroup'}
Service:
Type: 'AWS::ECS::Service'
Properties:
Cluster: {'Fn::ImportValue': !Sub '${ParentClusterStack}-Cluster'}
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DesiredCount: !Ref DesiredCount
LaunchType: FARGATE
ServiceRegistries:
- ContainerName: !If [HasAmbassadorImage, ambassador, app]
ContainerPort: !If [HasAmbassadorImage, !Ref AmbassadorPort, !Ref AppPort]
RegistryArn: !GetAtt 'ServiceDiscovery.Arn'
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: !If [HasSubnetsReachPublic, ENABLED, DISABLED]
SecurityGroups:
- !Ref ServiceSecurityGroup
- !If [HasClientSecurityGroup1, {'Fn::ImportValue': !Sub '${ParentClientStack1}-ClientSecurityGroup'}, !Ref 'AWS::NoValue']
- !If [HasClientSecurityGroup2, {'Fn::ImportValue': !Sub '${ParentClientStack2}-ClientSecurityGroup'}, !Ref 'AWS::NoValue']
- !If [HasClientSecurityGroup3, {'Fn::ImportValue': !Sub '${ParentClientStack3}-ClientSecurityGroup'}, !Ref 'AWS::NoValue']
Subnets: !Split [',', {'Fn::ImportValue': !Sub '${ParentVPCStack}-Subnets${SubnetsReach}'}]
TaskDefinition: !Ref TaskDefinition
CPUUtilizationTooHighAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmDescription: 'Average CPU utilization over last 10 minutes higher than 80%'
Namespace: 'AWS/ECS'
Dimensions:
- Name: ClusterName
Value: {'Fn::ImportValue': !Sub '${ParentClusterStack}-Cluster'}
- Name: ServiceName
Value: !GetAtt 'Service.Name'
MetricName: CPUUtilization
ComparisonOperator: GreaterThanThreshold
Statistic: Average
Period: 300
EvaluationPeriods: 1
Threshold: 80
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
ScalableTargetRole: # based on http://docs.aws.amazon.com/AmazonECS/latest/developerguide/autoscale_IAM_role.html
Condition: HasAutoScaling
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: 'application-autoscaling.amazonaws.com'
Action: 'sts:AssumeRole'
Policies:
- PolicyName: AmazonEC2ContainerServiceAutoscaleRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'ecs:DescribeServices'
- 'ecs:UpdateService'
Resource: '*'
- PolicyName: cloudwatch
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'cloudwatch:DescribeAlarms'
Resource: '*'
ScalableTarget:
Condition: HasAutoScaling
Type: 'AWS::ApplicationAutoScaling::ScalableTarget'
Properties:
MaxCapacity: !Ref MaxCapacity
MinCapacity: !Ref MinCapacity
ResourceId: !Sub
- 'service/${Cluster}/${Service}'
- Cluster: {'Fn::ImportValue': !Sub '${ParentClusterStack}-Cluster'}
Service: !GetAtt 'Service.Name'
RoleARN: !GetAtt 'ScalableTargetRole.Arn'
ScalableDimension: 'ecs:service:DesiredCount'
ServiceNamespace: ecs
ScaleUpPolicy:
Condition: HasAutoScaling
Type: 'AWS::ApplicationAutoScaling::ScalingPolicy'
Properties:
PolicyName: !Sub '${AWS::StackName}-scale-up'
PolicyType: StepScaling
ScalingTargetId: !Ref ScalableTarget
StepScalingPolicyConfiguration:
AdjustmentType: PercentChangeInCapacity
Cooldown: 300
MinAdjustmentMagnitude: 1
StepAdjustments:
- MetricIntervalLowerBound: 0
ScalingAdjustment: 25
ScaleDownPolicy:
Condition: HasAutoScaling
Type: 'AWS::ApplicationAutoScaling::ScalingPolicy'
Properties:
PolicyName: !Sub '${AWS::StackName}-scale-down'
PolicyType: StepScaling
ScalingTargetId: !Ref ScalableTarget
StepScalingPolicyConfiguration:
AdjustmentType: PercentChangeInCapacity
Cooldown: 300
MinAdjustmentMagnitude: 1
StepAdjustments:
- MetricIntervalUpperBound: 0
ScalingAdjustment: -25
CPUUtilizationHighAlarm:
Condition: HasAutoScaling
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmDescription: 'Service is running out of CPU'
Namespace: 'AWS/ECS'
Dimensions:
- Name: ClusterName
Value: {'Fn::ImportValue': !Sub '${ParentClusterStack}-Cluster'}
- Name: ServiceName
Value: !GetAtt 'Service.Name'
MetricName: CPUUtilization
ComparisonOperator: GreaterThanThreshold
Statistic: Average
Period: 300
EvaluationPeriods: 1
Threshold: 60
AlarmActions:
- !Ref ScaleUpPolicy
CPUUtilizationLowAlarm:
Condition: HasAutoScaling
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmDescription: 'Service is wasting CPU'
Namespace: 'AWS/ECS'
Dimensions:
- Name: ClusterName
Value: {'Fn::ImportValue': !Sub '${ParentClusterStack}-Cluster'}
- Name: ServiceName
Value: !GetAtt 'Service.Name'
MetricName: CPUUtilization
ComparisonOperator: LessThanThreshold
Statistic: Average
Period: 300
EvaluationPeriods: 3
Threshold: 30
AlarmActions:
- !Ref ScaleDownPolicy
Outputs:
TemplateID:
Description: 'cloudonaut.io template id.'
Value: 'fargate/service-cloudmap'
TemplateVersion:
Description: 'cloudonaut.io template version.'
Value: '__VERSION__'
StackName:
Description: 'Stack name.'
Value: !Sub '${AWS::StackName}'
You can’t perform that action at this time.