blogs/ecs-canary-deployments-pipeline/setup/templates/ecs-mesh.yaml (245 lines of code) (raw):
Description: >
This template deploys an empty ECS Cluster and a mesh(AppMesh),
Public ALB, Security Groups, CloudMap Namespace and Static entries for Virtual Services.
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
EnvoyImage:
Description: App Mesh Envoy container image. See https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html.
Type: String
Namespace:
Type: String
Default: yelb.local
ContainerPort:
Type: Number
Default: 80
LoadBalancerPort:
Type: Number
Default: 80
CountOfGatewayTasks:
Description: The number of tasks to be instantiated for the Gateway service
Type: Number
Default: 1
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:
#------ ECS Resources ------#
#ECS Cluster
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Ref EnvironmentName
ClusterSettings:
- Name: containerInsights
Value: enabled
#ECS Task Execution Role
ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Join ['-', [!Ref EnvironmentName, ExecutionRole]]
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'
#ECS Task Role
TaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Join ['-', [!Ref EnvironmentName, TaskRole]]
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'
#ECS Container SecurityGroup
ContainerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Join ['-', [!Ref EnvironmentName, ContainerSecurityGroup]]
VpcId:
'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
SecurityGroupIngress:
- IpProtocol: tcp
CidrIp: '0.0.0.0/0'
FromPort: 1025
ToPort: 65535
- IpProtocol: tcp
FromPort: !Ref ContainerPort
ToPort: !Ref ContainerPort
SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
#------ Load Balancing Resources ------#
#Load Balancing Security Group
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Join ['-', [!Ref EnvironmentName, LoadBalancerSecurityGroup]]
VpcId:
'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !Ref LoadBalancerPort
ToPort: !Ref LoadBalancerPort
CidrIp: 0.0.0.0/0
#Load Balancer
PublicLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
Subnets:
- { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet1" }
- { 'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet2" }
SecurityGroups: [!Ref 'LoadBalancerSecurityGroup']
#Load Balancer Listener
PublicLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn:
- PublicLoadBalancer
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: 'forward'
LoadBalancerArn: !Ref 'PublicLoadBalancer'
Port: 80
Protocol: HTTP
#Load Balancer TargetGroup
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: '/'
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
TargetType: ip
Name: !Sub 'yelb-targetgroup'
Port: 80
Protocol: HTTP
UnhealthyThresholdCount: 2
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 120
VpcId:
Fn::ImportValue: !Sub '${EnvironmentName}:VPC'
#Load Balancer Rule(s)
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref TargetGroup
Type: 'forward'
Conditions:
- Field: path-pattern
Values: [!Ref 'LoadBalancerPath']
ListenerArn: !Ref PublicLoadBalancerListener
Priority: 1
#------ CloudMap Resources ------#
#CloudMap Namespace
CloudMapNamespace:
Type: AWS::ServiceDiscovery::PrivateDnsNamespace
Properties:
Name: !Ref 'Namespace'
Vpc:
Fn::ImportValue:
!Sub "${EnvironmentName}:VPC"
Description: !Sub "Service Discovery Namespace for Yelb"
#Mesh Resource
Mesh:
Type: AWS::AppMesh::Mesh
Properties:
MeshName: !Ref EnvironmentName
#To workaround the issue on AppMesh: https://github.com/aws/aws-app-mesh-roadmap/issues/65
YelbUIStaticServiceDiscoveryEntry:
Type: AWS::ServiceDiscovery::Service
Properties:
Name: yelb-ui
DnsConfig:
DnsRecords:
- Type: A
TTL: "10"
NamespaceId: !Ref 'CloudMapNamespace'
YelbUIIPStaticEntry:
Type: AWS::ServiceDiscovery::Instance
Properties:
InstanceAttributes:
AWS_INSTANCE_IPV4: 10.10.10.10
ServiceId: !Ref YelbUIStaticServiceDiscoveryEntry
YelbAppServerStaticServiceDiscoveryEntry:
Type: AWS::ServiceDiscovery::Service
Properties:
Name: yelb-appserver
DnsConfig:
DnsRecords:
- Type: A
TTL: "10"
NamespaceId: !Ref 'CloudMapNamespace'
YelbAppServerIPStaticEntry:
Type: AWS::ServiceDiscovery::Instance
Properties:
InstanceAttributes:
AWS_INSTANCE_IPV4: 10.10.10.10
ServiceId: !Ref YelbAppServerStaticServiceDiscoveryEntry
YelbRedisStaticServiceDiscoveryEntry:
Type: AWS::ServiceDiscovery::Service
Properties:
Name: yelb-redisserver
DnsConfig:
DnsRecords:
- Type: A
TTL: "10"
NamespaceId: !Ref 'CloudMapNamespace'
YelbRedisIPStaticEntry:
Type: AWS::ServiceDiscovery::Instance
Properties:
InstanceAttributes:
AWS_INSTANCE_IPV4: 10.10.10.10
ServiceId: !Ref YelbRedisStaticServiceDiscoveryEntry
YelbDBStaticServiceDiscoveryEntry:
Type: AWS::ServiceDiscovery::Service
Properties:
Name: yelb-db
DnsConfig:
DnsRecords:
- Type: A
TTL: "10"
NamespaceId: !Ref 'CloudMapNamespace'
YelbDBStaticEntry:
Type: AWS::ServiceDiscovery::Instance
Properties:
InstanceAttributes:
AWS_INSTANCE_IPV4: 10.10.10.10
ServiceId: !Ref YelbDBStaticServiceDiscoveryEntry
Outputs:
Mesh:
Description: A reference to the AppMesh Mesh
Value: !GetAtt Mesh.MeshName
Export:
Name: !Sub "${EnvironmentName}:Mesh"
ExecutionRole:
Description: A reference to the Task Execution Role
Value: !GetAtt ExecutionRole.Arn
Export:
Name: !Sub "${EnvironmentName}:ExecutionRole"
TaskRole:
Description: A reference to the TaskRole
Value: !GetAtt TaskRole.Arn
Export:
Name: !Sub "${EnvironmentName}:TaskRole"
ContainerSecurityGroup:
Description: A reference to the ContainerSecurityGroup
Value: !Ref ContainerSecurityGroup
Export:
Name: !Sub "${EnvironmentName}:ContainerSecurityGroup"
Namespace:
Description: A reference to the Namespace
Value: !GetAtt 'CloudMapNamespace.Id'
Export:
Name: !Sub "${EnvironmentName}:CloudMapNamespaceId"
PublicLoadBalancer:
Description: A reference to the LoadBalancer DNSName
Value: !GetAtt PublicLoadBalancer.DNSName
Export:
Name: !Sub "${EnvironmentName}:PublicLoadBalancer"
TargetGroupArn:
Description: A reference to the TargetGroup
Value: !Ref TargetGroup
Export:
Name: !Sub "${EnvironmentName}:TargetGroupArn"