--- AWSTemplateFormatVersion: 2010-09-09 Description: Multiple Listeners Example ECS Service 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 TellerImageName: Description: The name for the teller 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: FoodTellerServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "foodteller" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 FoodTellerTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-foodteller' 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: '5555,6666' - Name: 'EgressIgnoredIPs' Value: '169.254.170.2,169.254.169.254' ContainerDefinitions: - Name: 'fruit-app' Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${TellerImageName}' 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: 'fruit' PortMappings: - ContainerPort: 5555 Protocol: 'tcp' Environment: - Name: 'PORT' Value: 5555 - Name: 'TELL' Value: 'fruit' - Name: 'vegetable-app' Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${TellerImageName}' 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: 'vegetable' PortMappings: - ContainerPort: 6666 Protocol: 'tcp' Environment: - Name: 'PORT' Value: 6666 - Name: 'TELL' Value: 'vegetable' - 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: 'food-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualNode/foodteller-vn' - Name: 'ENABLE_ENVOY_STATS_TAGS' Value: '1' - Name: 'ENABLE_ENVOY_DOG_STATSD' Value: '1' - Name: 'STATSD_PORT' Value: '8125' - Name: 'ENVOY_LOG_LEVEL' Value: 'debug' - 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 - foodteller - StatsD FoodTellerService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': FoodTellerServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: FoodTellerTaskDefinition } ColorTellerServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-colorteller' 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: '7777' - Name: 'EgressIgnoredIPs' Value: '169.254.170.2,169.254.169.254' ContainerDefinitions: - Name: 'app' Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${TellerImageName}' 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: 'color' PortMappings: - ContainerPort: 7777 Protocol: 'tcp' Environment: - Name: 'PORT' Value: 7777 - Name: 'TELL' Value: 'color' - 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: 'color-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualNode/colorteller-vn' - Name: 'ENABLE_ENVOY_STATS_TAGS' Value: '1' - Name: 'ENABLE_ENVOY_DOG_STATSD' Value: '1' - Name: 'STATSD_PORT' Value: '8125' - Name: 'ENVOY_LOG_LEVEL' Value: 'debug' - 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 - StatsD ColorTellerService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorTellerServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorTellerTaskDefinition } TellerGatewayServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "tellergateway" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 TellerGatewayTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: !Sub '${EnvironmentName}-tellergateway' 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: 1111 Protocol: 'tcp' - ContainerPort: 2222 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/tellergateway-vg' - Name: 'ENABLE_ENVOY_STATS_TAGS' Value: '1' - Name: 'ENABLE_ENVOY_DOG_STATSD' Value: '1' - Name: 'STATSD_PORT' Value: '8125' - Name: 'ENVOY_LOG_LEVEL' Value: 'debug' - 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' TellerGatewayService: Type: 'AWS::ECS::Service' DependsOn: - ColorPublicLoadBalancerListener - FoodPublicLoadBalancerListener Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': TellerGatewayServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: TellerGatewayTaskDefinition } LoadBalancers: - ContainerName: app ContainerPort: 1111 TargetGroupArn: !Ref FoodWebTargetGroup - ContainerName: app ContainerPort: 2222 TargetGroupArn: !Ref ColorWebTargetGroup PublicLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing Subnets: - { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet1" } - { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet2" } Type: network FoodWebTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckPort: 1111 HealthCheckProtocol: TCP HealthCheckTimeoutSeconds: 10 HealthyThresholdCount: 3 TargetType: ip Name: !Sub "${EnvironmentName}-food-web" Port: 1111 Protocol: TCP UnhealthyThresholdCount: 3 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 120 VpcId: 'Fn::ImportValue': !Sub "${EnvironmentName}:VPC" ColorWebTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckPort: 2222 HealthCheckProtocol: TCP HealthCheckTimeoutSeconds: 10 HealthyThresholdCount: 3 TargetType: ip Name: !Sub "${EnvironmentName}-color-web" Port: 2222 Protocol: TCP UnhealthyThresholdCount: 3 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 120 VpcId: 'Fn::ImportValue': !Sub "${EnvironmentName}:VPC" FoodPublicLoadBalancerListener: Type: AWS::ElasticLoadBalancingV2::Listener DependsOn: - PublicLoadBalancer Properties: DefaultActions: - TargetGroupArn: !Ref FoodWebTargetGroup Type: 'forward' LoadBalancerArn: !Ref PublicLoadBalancer Port: 1111 Protocol: TCP ColorPublicLoadBalancerListener: Type: AWS::ElasticLoadBalancingV2::Listener DependsOn: - PublicLoadBalancer Properties: DefaultActions: - TargetGroupArn: !Ref ColorWebTargetGroup Type: 'forward' LoadBalancerArn: !Ref PublicLoadBalancer Port: 2222 Protocol: TCP Outputs: TellerAppEndpoint: Description: Public endpoint for teller App service Value: !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]