Description: > This is template creates the task- and service definition of our reactive service. Parameters: VPC: Description: Choose which VPC this ECS cluster should be deployed to Type: AWS::EC2::VPC::Id Subnets: Description: Choose which subnets this ECS cluster should be deployed to Type: List SecurityGroup: Description: Select the Security Group to use for the ECS cluster hosts Type: AWS::EC2::SecurityGroup::Id Cluster: Description: Please provide the ECS Cluster ID that this service should run on Type: String DesiredCount: Description: How many instances of this task should we run across our cluster? Type: Number Default: 2 Listener: Description: The Application Load Balancer listener to register with Type: String Path: Description: The path to register with the Application Load Balancer Type: String Default: / TargetGroup: Description: The reference to the target group Type: String EventStream: Description: The event stream Type: String RedisHost: Description: The Elasticache-endpoint Type: String ECSTaskExecutionRole: Description: The task execution role Type: String TaskRole: Description: The task role Type: String ServiceName: Description: The service name Type: String TargetParameter: Description: The deployment target Type: String Conditions: IsOpenJDKTarget: !Equals [ !Ref TargetParameter, "Fargate-OpenJDK" ] IsGraalVMTarget: !Equals [ !Ref TargetParameter, "Fargate-GraalVM" ] Resources: ListenerRule: Type: AWS::ElasticLoadBalancingV2::ListenerRule Properties: ListenerArn: !Ref Listener Priority: 2 Conditions: - Field: path-pattern Values: - !Ref Path Actions: - TargetGroupArn: !Ref TargetGroup Type: forward Service: Type: AWS::ECS::Service DependsOn: ListenerRule Properties: PlatformVersion: 1.4.0 Cluster: !Ref Cluster LaunchType: FARGATE DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 75 DesiredCount: !Ref DesiredCount TaskDefinition: !Ref TaskDefinition ServiceName: !Ref ServiceName LoadBalancers: - ContainerName: !Ref ServiceName ContainerPort: 8080 TargetGroupArn: !Ref TargetGroup NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - !Ref SecurityGroup Subnets: !Ref Subnets TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: !Ref ServiceName NetworkMode: awsvpc RequiresCompatibilities: ["FARGATE"] Memory: 2048 Cpu: 1024 ExecutionRoleArn: !Ref ECSTaskExecutionRole TaskRoleArn: !Ref TaskRole ContainerDefinitions: - Name: !Ref ServiceName Essential: true Image: !If [IsOpenJDKTarget, 'public.ecr.aws/f8l6y1f6/reactive-vertx:2.0.1', 'public.ecr.aws/f8l6y1f6/reactive-vertx:2.0.1-native'] Memory: 2048 Cpu: 1024 HealthCheck: Command: [ "CMD-SHELL", "curl -f http://localhost:8080/health/check || exit 1" ] Interval: 30 Retries: 5 Timeout: 10 StartPeriod: 30 PortMappings: - ContainerPort: 8080 Environment: - Name: REDIS_HOST Value: !Ref RedisHost - Name: EVENT_STREAM Value: !Ref EventStream - Name: REGION Value: !Ref AWS::Region LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref AWS::StackName awslogs-region: !Ref AWS::Region awslogs-stream-prefix: !Ref AWS::StackName CloudWatchLogsGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Ref AWS::StackName RetentionInDays: 7 ServiceScalingTarget: Type: AWS::ApplicationAutoScaling::ScalableTarget DependsOn: Service Properties: MaxCapacity: 4 MinCapacity: 2 ResourceId: !Join ['/', [service, !Ref Cluster, !Ref ServiceName]] ScalableDimension: ecs:service:DesiredCount ServiceNamespace: ecs RoleARN: !GetAtt AutoscalingRole.Arn ServiceScalingPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy Properties: PolicyName: AStepPolicy PolicyType: StepScaling ScalingTargetId: !Ref 'ServiceScalingTarget' StepScalingPolicyConfiguration: AdjustmentType: PercentChangeInCapacity Cooldown: 60 MetricAggregationType: Average StepAdjustments: - MetricIntervalLowerBound: 0 ScalingAdjustment: 200 CPUPAlarmScaleUp: Type: AWS::CloudWatch::Alarm Properties: EvaluationPeriods: '1' Statistic: Average Threshold: '75' AlarmDescription: Alarm if CPU is > 75% Period: '60' AlarmActions: [!Ref 'ServiceScalingPolicy'] Namespace: AWS/ECS Dimensions: - Name: ECSService Value: !Ref 'Service' ComparisonOperator: GreaterThanThreshold MetricName: CPUUtilization CPUPAlarmScaleDown: Type: AWS::CloudWatch::Alarm Properties: EvaluationPeriods: '1' Statistic: Average Threshold: '10' AlarmDescription: Alarm if CPU is < 10% Period: '60' AlarmActions: [!Ref 'ServiceScalingPolicy'] Namespace: AWS/ECS Dimensions: - Name: ECSService Value: !Ref 'Service' ComparisonOperator: LessThanThreshold MetricName: CPUUtilization # This IAM Role grants the service access to register/unregister with the # Application Load Balancer (ALB). It is based on the default documented here: # http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service_IAM_role.html AutoscalingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: [application-autoscaling.amazonaws.com] Action: ['sts:AssumeRole'] Path: / Policies: - PolicyName: service-autoscaling PolicyDocument: Statement: - Effect: Allow Action: ['application-autoscaling:*', 'cloudwatch:DescribeAlarms', 'cloudwatch:PutMetricAlarm', 'ecs:DescribeServices', 'ecs:UpdateService'] Resource: '*'