--- 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 ColorGatewayTaskDefinition: Type: String Description: Task definition for ColorGateway Service ColorTellerWhiteTaskDefinition: Type: String Description: Task definition for ColorTeller White Service ColorTellerRedTaskDefinition: Type: String Description: Task definition for ColorTeller Red Service ColorTellerBlueTaskDefinition: Type: String Description: Task definition for ColorTeller Blue Service ColorTellerBlackTaskDefinition: Type: String Description: Task definition for ColorTeller Black Service 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. DeployTester: Type: String Default: false AllowedValues: - true - false Description: Set to "true" to include the TesterService (to generate color history) Conditions: ShouldDeployTester: !Equals [true, !Ref DeployTester] 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 ColorTellerWhiteService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 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-blue.default.svc.cluster.local ColorTellerBlueServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller-blue" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerBlueService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorTellerBlueServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorTellerBlueTaskDefinition } ### colorteller-red.default.svc.cluster.local ColorTellerRedServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "colorteller-red" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 ColorTellerRedService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 ServiceRegistries: - RegistryArn: 'Fn::GetAtt': ColorTellerRedServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: ColorTellerRedTaskDefinition } ### 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 ColorTellerBlackService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 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 ColorGatewayService: Type: 'AWS::ECS::Service' DependsOn: - WebLoadBalancerRule Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 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 ### tester TesterService: Type: 'AWS::ECS::Service' Condition: ShouldDeployTester Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: TesterTaskDefinition } TesterTaskDefinition: Type: 'AWS::ECS::TaskDefinition' Condition: ShouldDeployTester Properties: ContainerDefinitions: - Name: "app" Image: "tstrohmeier/alpine-infinite-curl" Essential: true Command: - !Sub "-h http://colorgateway.${ECSServicesDomain}:9080/color" LogConfiguration: LogDriver: "awslogs" Options: awslogs-group: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: { Ref: "AWS::Region" } awslogs-stream-prefix: "tester-app" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" NetworkMode: "awsvpc" Memory: 256 ### tcpecho.default.svc.cluster.local TcpEchoServiceDiscoveryRecord: Type: 'AWS::ServiceDiscovery::Service' Properties: Name: "tcpecho" DnsConfig: NamespaceId: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 TcpEchoService: Type: 'AWS::ECS::Service' Properties: Cluster: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: EC2 ServiceRegistries: - RegistryArn: 'Fn::GetAtt': TcpEchoServiceDiscoveryRecord.Arn NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceSecurityGroup" Subnets: - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet1" - 'Fn::ImportValue': !Sub "${EnvironmentName}:PrivateSubnet2" TaskDefinition: { Ref: TcpEchoTaskDefinition } TcpEchoTaskDefinition: Type: 'AWS::ECS::TaskDefinition' Properties: ContainerDefinitions: - Name: "app" Image: "cjimti/go-echo" Essential: true LogConfiguration: LogDriver: "awslogs" Options: awslogs-group: 'Fn::ImportValue': !Sub "${EnvironmentName}:ECSServiceLogGroup" awslogs-region: { Ref: "AWS::Region" } awslogs-stream-prefix: "tcpecho-app" PortMappings: - ContainerPort: 2701 HostPort: 2701 Protocol: "tcp" Environment: - Name: "TCP_PORT" Value: "2701" - Name: "NODE_NAME" Value: !Sub "mesh/${AppMeshMeshName}/virtualNode/tcpecho-vn" ExecutionRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskExecutionIamRoleArn" TaskRoleArn: 'Fn::ImportValue': !Sub "${EnvironmentName}:TaskIamRoleArn" NetworkMode: "awsvpc" Memory: 256 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: /ping HealthCheckProtocol: HTTP 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']]