--- Parameters: EnvironmentName: Type: String Description: Environment name that joins all the stacks AppMeshMeshName: Type: String Description: Name of mesh ECSServicesDomain: Type: String Description: DNS namespace used by services e.g. default.svc.cluster.local EnvoyImage: Type: String Description: The image to use for the Envoy container ColorTellerImageName: Description: The name for the color teller image Type: String WrkToolImageName: Description: The name for the wrk tool image Type: String LoadBalancerPath: Type: String Default: "*" Description: A path on the public load balancer that this service should be connected to. Use * to send all load balancer traffic to this service. Resources: ### colorteller-white.default.svc.cluster.local ColorTellerWhiteServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller-white" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerWhiteTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-colorteller-white' NetworkMode: 'awsvpc' Cpu: 4096 Memory: 8192 TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" ProxyConfiguration: Type: 'APPMESH' ContainerName: 'envoy' ProxyConfigurationProperties: - Name: 'IgnoredUID' Value: '1337' - Name: 'ProxyIngressPort' Value: '15000' - Name: 'ProxyEgressPort' Value: '15001' - Name: 'AppPorts' Value: '9080' - Name: 'EgressIgnoredIPs' Value: '169.254.170.2,169.254.169.254' ContainerDefinitions: - Name: 'app' Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ColorTellerImageName}' Essential: true Ulimits: - Name: "nofile" HardLimit: 15000 SoftLimit: 15000 DependsOn: - ContainerName: 'envoy' Condition: 'HEALTHY' LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'white' PortMappings: - ContainerPort: 9080 Protocol: 'tcp' Environment: - Name: 'PORT' Value: 9080 - Name: 'COLOR' Value: 'white' - Name: envoy Image: !Ref EnvoyImage Essential: true User: '1337' Ulimits: - Name: "nofile" HardLimit: 15000 SoftLimit: 15000 PortMappings: - ContainerPort: 9901 Protocol: 'tcp' - ContainerPort: 15000 Protocol: 'tcp' - ContainerPort: 15001 Protocol: 'tcp' HealthCheck: Command: - 'CMD-SHELL' - 'curl -s http://localhost:9901/server_info | grep state | grep -q LIVE' Interval: 5 Timeout: 2 Retries: 3 LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'white-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualNode/colorteller-white-vn' - Name: 'ENABLE_ENVOY_STATS_TAGS' Value: '1' - Name: 'ENABLE_ENVOY_DOG_STATSD' Value: '1' - Name: 'STATSD_PORT' Value: '8125' - Name: 'cw-agent' Image: 'amazon/cloudwatch-agent:latest' Essential: true PortMappings: - ContainerPort: 8125 Protocol: 'udp' Environment: - Name: CW_CONFIG_CONTENT Value: Fn::Sub: - "{ \"metrics\": { \"namespace\":\"${MetricNamespace}\", \"metrics_collected\": { \"statsd\": { \"metrics_aggregation_interval\": 0}}}}" - MetricNamespace: Fn::Join: - '/' - - !Ref EnvironmentName - colorteller-white - StatsD ColorTellerWhiteService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorTellerWhiteServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorTellerWhiteTaskDefinition } ### colorteller-black.default.svc.cluster.local ColorTellerBlackServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller-black" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerBlackTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-colorteller-black' NetworkMode: 'awsvpc' Cpu: 4096 Memory: 8192 TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" ProxyConfiguration: Type: 'APPMESH' ContainerName: 'envoy' ProxyConfigurationProperties: - Name: 'IgnoredUID' Value: '1337' - Name: 'ProxyIngressPort' Value: '15000' - Name: 'ProxyEgressPort' Value: '15001' - Name: 'AppPorts' Value: '9080' - Name: 'EgressIgnoredIPs' Value: '169.254.170.2,169.254.169.254' ContainerDefinitions: - Name: 'app' Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ColorTellerImageName}' Essential: true Ulimits: - Name: "nofile" HardLimit: 15000 SoftLimit: 15000 DependsOn: - ContainerName: 'envoy' Condition: 'HEALTHY' LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'black' PortMappings: - ContainerPort: 9080 Protocol: 'tcp' Environment: - Name: 'PORT' Value: 9080 - Name: 'COLOR' Value: 'black' - Name: envoy Image: !Ref EnvoyImage Essential: true User: '1337' Ulimits: - Name: "nofile" HardLimit: 15000 SoftLimit: 15000 PortMappings: - ContainerPort: 9901 Protocol: 'tcp' - ContainerPort: 15000 Protocol: 'tcp' - ContainerPort: 15001 Protocol: 'tcp' HealthCheck: Command: - 'CMD-SHELL' - 'curl -s http://localhost:9901/server_info | grep state | grep -q LIVE' Interval: 5 Timeout: 2 Retries: 3 LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'black-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualNode/colorteller-black-vn' - Name: 'ENABLE_ENVOY_STATS_TAGS' Value: '1' - Name: 'ENABLE_ENVOY_DOG_STATSD' Value: '1' - Name: 'STATSD_PORT' Value: '8125' - Name: 'cw-agent' Image: 'amazon/cloudwatch-agent:latest' Essential: true PortMappings: - ContainerPort: 8125 Protocol: 'udp' Environment: - Name: CW_CONFIG_CONTENT Value: Fn::Sub: - "{ \"metrics\": { \"namespace\":\"${MetricNamespace}\", \"metrics_collected\": { \"statsd\": { \"metrics_aggregation_interval\": 0}}}}" - MetricNamespace: Fn::Join: - '/' - - !Ref EnvironmentName - colorteller-black - StatsD ColorTellerBlackService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorTellerBlackServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorTellerBlackTaskDefinition } ### colorgateway.default.svc.cluster.local ColorGatewayServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorgateway" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorGatewayTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-colorgateway' NetworkMode: 'awsvpc' Cpu: 4096 Memory: 8192 TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" ContainerDefinitions: - Name: 'app' Image: !Ref EnvoyImage Essential: true Ulimits: - Name: "nofile" HardLimit: 15000 SoftLimit: 15000 PortMappings: - ContainerPort: 9901 Protocol: 'tcp' - ContainerPort: 9080 Protocol: 'tcp' HealthCheck: Command: - 'CMD-SHELL' - 'curl -s http://localhost:9901/server_info | grep state | grep -q LIVE' Interval: 5 Timeout: 2 Retries: 3 StartPeriod: 60 LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'gateway-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualGateway/colorgateway-vg' - Name: 'ENABLE_ENVOY_STATS_TAGS' Value: '1' - Name: 'ENABLE_ENVOY_DOG_STATSD' Value: '1' - Name: 'STATSD_PORT' Value: '8125' - Name: 'cw-agent' Image: 'amazon/cloudwatch-agent:latest' Essential: true PortMappings: - ContainerPort: 8125 Protocol: 'udp' Environment: - Name: CW_CONFIG_CONTENT Value: Fn::Sub: - "{ \"metrics\": { \"namespace\":\"${MetricNamespace}\", \"metrics_collected\": { \"statsd\": { \"metrics_aggregation_interval\": 0}}}}" - MetricNamespace: Fn::Join: - '/' - - !Ref EnvironmentName - gateway-envoy - StatsD LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'gateway-cw-agent' ColorGatewayService: Type: 'AWS::ECS::Service' DependsOn: - PublicLoadBalancerListener Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorGatewayServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorGatewayTaskDefinition } LoadBalancers: - ContainerName: app ContainerPort: 9080 TargetGroupArn: !Ref WebTargetGroup ### wrk-tool.default.svc.cluster.local WrkToolServiceDiscoveryRecord: Type: AWS::ServiceDiscovery::Service Properties: Name: "wrk-tool" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 WrkToolTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-wrk-tool' NetworkMode: awsvpc Cpu: 4096 Memory: 8192 TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" ContainerDefinitions: - Name: wrk Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${WrkToolImageName}' Essential: true Ulimits: - Name: nofile HardLimit: 15000 SoftLimit: 15000 LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'wrk' PortMappings: - ContainerPort: 80 Protocol: tcp HealthCheck: Command: [ 'CMD-SHELL', 'curl -f http://localhost:80/ || exit 1' ] Interval: 5 Timeout: 2 Retries: 3 WrkToolECSService: Type: AWS::ECS::Service Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': WrkToolServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: WrkToolTaskDefinition } PublicLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing Subnets: - { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet1" } - { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet2" } Type: network WebTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckPort: 9080 HealthCheckProtocol: TCP HealthCheckTimeoutSeconds: 10 HealthyThresholdCount: 3 TargetType: ip Name: !Sub "${EnvironmentName}-web" Port: 80 Protocol: TCP UnhealthyThresholdCount: 3 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 120 VpcId: 'Fn::ImportValue': !Sub "${EnvironmentName}:VPC" PublicLoadBalancerListener: Type: AWS::ElasticLoadBalancingV2::Listener DependsOn: - PublicLoadBalancer Properties: DefaultActions: - TargetGroupArn: !Ref WebTargetGroup Type: 'forward' LoadBalancerArn: !Ref PublicLoadBalancer Port: 80 Protocol: TCP Outputs: ColorAppEndpoint: Description: Public endpoint for Color App service Value: !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]