--- 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 ColorAppEnvoyImageName: Description: The name for the color app envoy 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.default.svc.cluster.local ColorTellerWhiteServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerWhiteTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: 'white' NetworkMode: 'awsvpc' Cpu: 256 Memory: 512 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: '80' - 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 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: 80 Protocol: 'http' Environment: - Name: 'SERVER_PORT' Value: 80 - Name: 'COLOR' Value: 'white' - Name: envoy Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ColorAppEnvoyImageName}' 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/ColorTellerWhite' - Name: CERTIFICATE_NAME Value: 'colorteller_white' 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-green.default.cluster.svc.cluster.local ColorTellerGreenServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller-green" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerGreenTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - 'FARGATE' Family: 'green' NetworkMode: 'awsvpc' Cpu: 256 Memory: 512 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: '80' - 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 DependsOn: - ContainerName: 'envoy' Condition: 'HEALTHY' LogConfiguration: LogDriver: 'awslogs' Options: awslogs-group: Fn::ImportValue: !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: 'green' PortMappings: - ContainerPort: 80 Protocol: 'http' Environment: - Name: 'SERVER_PORT' Value: 80 - Name: 'COLOR' Value: 'green' - Name: envoy Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ColorAppEnvoyImageName}' 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: 'green-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualNode/ColorTellerGreen' - Name: CERTIFICATE_NAME Value: 'colorteller_green' ColorTellerGreenService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: FARGATE ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorTellerGreenServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorTellerGreenTaskDefinition } ### 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: 'gateway' NetworkMode: 'awsvpc' Cpu: 256 Memory: 512 TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" ContainerDefinitions: - Name: envoy Image: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ColorAppEnvoyImageName}' Essential: true Ulimits: - Name: "nofile" HardLimit: 15000 SoftLimit: 15000 PortMappings: - ContainerPort: 9901 Protocol: 'tcp' - ContainerPort: 15000 Protocol: 'tcp' - ContainerPort: 15001 Protocol: 'tcp' - ContainerPort: 80 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: 'gateway-envoy' Environment: - Name: 'APPMESH_RESOURCE_ARN' Value: !Sub 'mesh/${AppMeshMeshName}/virtualGateway/ColorGateway' - Name: CERTIFICATE_NAME Value: 'colorgateway' ColorGatewayService: Type: 'AWS::ECS::Service' DependsOn: - WebLoadBalancerRule 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: envoy ContainerPort: 80 TargetGroupArn: !Ref WebTargetGroup PublicLoadBalancerSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Access to the public facing load balancer VpcId: 'Fn::ImportValue': !Sub "${EnvironmentName}:VPC" SecurityGroupIngress: - CidrIp: 0.0.0.0/0 IpProtocol: tcp FromPort: 80 ToPort: 80 # public ALB for color gateway PublicLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing LoadBalancerAttributes: - Key: idle_timeout.timeout_seconds Value: '30' Subnets: - { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet1" } - { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet2" } SecurityGroups: [!Ref 'PublicLoadBalancerSG'] WebTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 6 HealthCheckPath: /ready HealthCheckProtocol: HTTP HealthCheckPort: 9901 HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 TargetType: ip Name: !Sub "${EnvironmentName}-web" Port: 80 Protocol: HTTP UnhealthyThresholdCount: 2 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: HTTP WebLoadBalancerRule: Type: AWS::ElasticLoadBalancingV2::ListenerRule Properties: Actions: - TargetGroupArn: !Ref WebTargetGroup Type: 'forward' Conditions: - Field: path-pattern Values: [!Ref 'LoadBalancerPath'] ListenerArn: !Ref PublicLoadBalancerListener Priority: 1 Outputs: ColorAppEndpoint: Description: Public endpoint for Color App service Value: !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]