Parameters: ProjectName: Type: String Description: Project name to link stacks Default: am-ecs-multi-account MeshOwner: Type: String Description: Owner of the Mesh MeshName: Type: String Description: Name of the shared mesh Default: yelb VPC: Description: VPC shared from account yellow Type: String PrivateSubnet1: Description: PrivateSubnet1 shared from account yellow Type: String PrivateSubnet2: Description: PrivateSubnet2 shared from account yellow Type: String PublicSubnet1: Description: PublicSubnet1 shared from account yellow Type: String PublicSubnet2: Description: PublicSubnet2 shared from account yellow Type: String VpcCIDR: Description: Please enter the IP range (CIDR notation) for this VPC Type: String Default: 10.0.0.0/16 EnvoyImage: Type: String Description: Envoy container image AppserverImage: Type: String Description: Container image for Appserver Default: mreferre/yelb-appserver:0.5 UIImage: Type: String Description: Container image for UI Default: mreferre/yelb-ui:0.7 Resources: PublicLoadBalancerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Access to the public facing load balancer" VpcId: !Ref VPC SecurityGroupIngress: - CidrIp: 0.0.0.0/0 IpProtocol: tcp FromPort: 80 ToPort: 80 PublicLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing LoadBalancerAttributes: - Key: idle_timeout.timeout_seconds Value: "30" Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 SecurityGroups: - !Ref PublicLoadBalancerSecurityGroup WebTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 6 HealthCheckPath: / HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 TargetType: ip Name: !Sub "${ProjectName}-webtarget" Port: 80 Protocol: HTTP UnhealthyThresholdCount: 2 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 120 VpcId: !Ref VPC PublicLoadBalancerListener: Type: AWS::ElasticLoadBalancingV2::Listener 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: - "*" ListenerArn: !Ref PublicLoadBalancerListener Priority: 1 TaskSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Security group for the tasks" VpcId: !Ref VPC SecurityGroupIngress: - CidrIp: !Ref VpcCIDR IpProtocol: -1 LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub "${ProjectName}-log-group" RetentionInDays: 5 TaskIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: | { "Statement": [{ "Effect": "Allow", "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]}, "Action": [ "sts:AssumeRole" ] }] } ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchFullAccess - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess - arn:aws:iam::aws:policy/AWSAppMeshEnvoyAccess TaskExecutionIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: | { "Statement": [{ "Effect": "Allow", "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]}, "Action": [ "sts:AssumeRole" ] }] } ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Security group for the tasks" VpcId: !Ref VPC SecurityGroupIngress: - CidrIp: !Ref VpcCIDR IpProtocol: -1 AppserverTaskDef: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - "FARGATE" Family: !Sub "${ProjectName}-yelb-appserver" NetworkMode: "awsvpc" Cpu: 256 Memory: 512 TaskRoleArn: !Ref TaskIamRole ExecutionRoleArn: !Ref TaskExecutionIamRole ProxyConfiguration: Type: "APPMESH" ContainerName: "envoy" ProxyConfigurationProperties: - Name: "IgnoredUID" Value: "1337" - Name: "ProxyIngressPort" Value: "15000" - Name: "ProxyEgressPort" Value: "15001" - Name: "AppPorts" Value: "4567" - Name: "EgressIgnoredIPs" Value: "169.254.170.2,169.254.169.254" ContainerDefinitions: - Name: "app" Image: !Ref AppserverImage Essential: true DependsOn: - ContainerName: 'xray-daemon' Condition: 'START' - ContainerName: 'envoy' Condition: 'HEALTHY' Environment: - Name: SEARCH_DOMAIN Value: !Sub "${ProjectName}.local" LogConfiguration: LogDriver: "awslogs" Options: awslogs-group: !Sub "${ProjectName}-log-group" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "yelb-appserver" PortMappings: - ContainerPort: 4567 Protocol: "tcp" - Name: xray-daemon Image: public.ecr.aws/xray/aws-xray-daemon Essential: true User: "1337" PortMappings: - ContainerPort: 2000 Protocol: "udp" LogConfiguration: LogDriver: "awslogs" Options: awslogs-group: !Sub "${ProjectName}-log-group" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "appserver-xray" - 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: !Sub "${ProjectName}-log-group" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "appserver-envoy" Environment: - Name: "APPMESH_RESOURCE_ARN" Value: !Sub "mesh/${MeshName}@${MeshOwner}/virtualNode/yelb-appserver-vn" - Name: "ENVOY_LOG_LEVEL" Value: "debug" - Name: "ENABLE_ENVOY_XRAY_TRACING" Value: "1" AppserverRegistry: Type: AWS::ServiceDiscovery::Service Properties: Name: "yelb-appserver" DnsConfig: NamespaceId: Fn::ImportValue: !Sub "${ProjectName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 AppserverService: Type: AWS::ECS::Service DependsOn: AppserverRegistry Properties: Cluster: Fn::ImportValue: !Sub "${ProjectName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: "FARGATE" ServiceRegistries: - RegistryArn: !GetAtt "AppserverRegistry.Arn" NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - !Ref SecurityGroup Subnets: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 TaskDefinition: !Ref AppserverTaskDef UITaskDef: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - "FARGATE" Family: !Sub "${ProjectName}-yelb-ui" NetworkMode: "awsvpc" Cpu: 256 Memory: 512 TaskRoleArn: !Ref TaskIamRole ExecutionRoleArn: !Ref TaskExecutionIamRole 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: !Ref UIImage Essential: true DependsOn: - ContainerName: 'xray-daemon' Condition: 'START' - ContainerName: 'envoy' Condition: 'HEALTHY' Environment: - Name: SEARCH_DOMAIN Value: !Sub "green.${ProjectName}.local" LogConfiguration: LogDriver: "awslogs" Options: awslogs-group: !Sub "${ProjectName}-log-group" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "yelb-ui" PortMappings: - ContainerPort: 80 Protocol: "tcp" - Name: xray-daemon Image: public.ecr.aws/xray/aws-xray-daemon Essential: true User: "1337" PortMappings: - ContainerPort: 2000 Protocol: "udp" LogConfiguration: LogDriver: "awslogs" Options: awslogs-group: !Sub "${ProjectName}-log-group" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "ui-xray" - 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: !Sub "${ProjectName}-log-group" awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "ui-envoy" Environment: - Name: "APPMESH_RESOURCE_ARN" Value: !Sub "mesh/${MeshName}@${MeshOwner}/virtualNode/yelb-ui-vn" - Name: "ENVOY_LOG_LEVEL" Value: "debug" - Name: "ENABLE_ENVOY_XRAY_TRACING" Value: "1" UIRegistry: Type: AWS::ServiceDiscovery::Service Properties: Name: "yelb-ui" DnsConfig: NamespaceId: Fn::ImportValue: !Sub "${ProjectName}:ECSServiceDiscoveryNamespace" DnsRecords: - Type: A TTL: 300 HealthCheckCustomConfig: FailureThreshold: 1 UIService: Type: AWS::ECS::Service DependsOn: - WebLoadBalancerRule - AppserverService - UIRegistry Properties: Cluster: Fn::ImportValue: !Sub "${ProjectName}:ECSCluster" DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DesiredCount: 1 LaunchType: "FARGATE" ServiceRegistries: - RegistryArn: !GetAtt "UIRegistry.Arn" NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - !Ref SecurityGroup Subnets: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 TaskDefinition: !Ref UITaskDef LoadBalancers: - ContainerName: app ContainerPort: 80 TargetGroupArn: !Ref WebTargetGroup Outputs: PublicEndpoint: Description: "Public endpoint for the color client service" Value: !Join ["", ["http://", !GetAtt "PublicLoadBalancer.DNSName"]] Export: Name: !Sub "${ProjectName}:PublicEndpoint"