AWS ECS:使用任务和服务定义部署容器
本文是在AWS ECS上运行Docker容器的第4部分教程的第3部分。
ECS代表弹性容器服务。
它是可以运行docker容器的托管容器服务。
尽管AWS还使用Kubernetes(EKS)提供了容器管理,但它也有其专有的解决方案(ECS)。
该教程将涵盖以下内容:创建ECS群集,提供镜像注册表(ECR)并将docker镜像推送到注册表,使用任务和服务定义将容器部署到群集,创建管道以更新ECS群集上运行的服务。
将使用从Docker Hub推送到ECR注册表中的简单hello-world镜像。
我们将创建任务和服务定义,并将其部署到ECS集群中。
要求/准备工作
一个AWS账户。
在该账户上创建一个用户,该账户具有配置该账户上的资源的权限;使用自定义域创建了Route 53托管区域(根据用户要求可以是公共区域,也可以是私有区域)。
ACM(Amazon证书管理器)。
提供了一个AWS ECS集群。
将Docker镜像上传到ECR注册表。
创建AWS Application Load Balancer和目标组
ALB(应用程序负载平衡器)是一个AWS托管的负载平衡器,可根据OSI第7层协议路由流量。
我们将使用负载均衡器公开我们的hello-world服务终结点。
我们已经在下面的链接上提供了有关创建应用程序负载均衡器的AWS教程:使用CloudFormationHence创建和配置AWS应用程序负载均衡器,我不会在ALB上介绍太多细节。
我们将使用下面的CloudFormation模板来创建和配置我们的ECS ALB。
模板将设置; ALB(应用程序负载平衡器).ALB安全组。
目标组.ALB侦听器和侦听器规则.N/B:如果读取器/用户希望在内部公开其服务,则应在以下位置创建负载平衡器专用子网。
否则,负载平衡器应面向互联网并在公共子网中创建。
对于高可用性的负载平衡器,用户应在不同可用性区域的不同子网中进行配置。
AWSTemplateFormatVersion: "2010-09-09"
Description: "Create ALB, Target Groups and ALB security group"
Parameters:
VPC:
Type: String
Description: The vpc to launch the service
Default: vpc-ID
PublicSubnet1:
Type: String
Description: The subnet where to launch the service
Default: subnet-ID
PublicSubnet2:
Type: String
Description: the subnet where to Launch the service
Default: subnet-ID
Resources:
ALBSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "security group for ALB"
GroupName: "test-prod-ALB-SG"
Tags:
-
Key: "Project"
Value: "test-blog"
-
Key: "createdBy"
Value: "Maureen Barasa"
-
Key: "Environment"
Value: "test"
-
Key: "Name"
Value: "test-ALB-SG"
VpcId: !Ref VPC
SecurityGroupIngress:
-
CidrIp: "0.0.0.0/0"
FromPort: 80
IpProtocol: "tcp"
ToPort: 80
-
CidrIp: "0.0.0.0/0"
FromPort: 443
IpProtocol: "tcp"
ToPort: 443
ApplicationLoadBalancer:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Name: "test-Application-Load-Balancer"
Scheme: "internet-facing"
Type: "application"
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
SecurityGroups:
- !Ref ALBSecurityGroup
IpAddressType: "ipv4"
LoadBalancerAttributes:
-
Key: "access_logs.s3.enabled"
Value: "true"
-
Key: "idle_timeout.timeout_seconds"
Value: "60"
-
Key: "deletion_protection.enabled"
Value: "false"
-
Key: "routing.http2.enabled"
Value: "true"
-
Key: "routing.http.drop_invalid_header_fields.enabled"
Value: "false"
Tags:
-
Key: "Project"
Value: "test-blog"
-
Key: "createdBy"
Value: "Maureen Barasa"
-
Key: "Environment"
Value: "test"
-
Key: "Name"
Value: "test-Application-Load-Balancer"
HTTPSListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: 443
Protocol: "HTTPS"
SslPolicy: "ELBSecurityPolicy-2015-08"
Certificates:
-
CertificateArn: arn:aws:acm:eu-central-1:** **** **** ***:certificate/** **** **** **
DefaultActions:
-
Order: 1
TargetGroupArn: !Ref TestTargetGroup
Type: "forward"
HTTPListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: 80
Protocol: "HTTP"
DefaultActions:
-
Order: 1
RedirectConfig:
Protocol: "HTTPS"
Port: "443"
Host: "#{host}"
Path: "/#{path}"
Query: "#{query}"
StatusCode: "HTTP_301"
Type: "redirect"
TestTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
Port: 80
Protocol: "HTTP"
HealthCheckPort: "traffic-port"
HealthCheckProtocol: "HTTP"
HealthCheckTimeoutSeconds: 5
UnhealthyThresholdCount: 2
TargetType: "ip"
Matcher:
HttpCode: "200"
HealthyThresholdCount: 5
VpcId: !Ref VPC
Name: "target-group-1"
HealthCheckEnabled: true
TargetGroupAttributes:
-
Key: "stickiness.enabled"
Value: "false"
-
Key: "deregistration_delay.timeout_seconds"
Value: "300"
-
Key: "stickiness.type"
Value: "lb_cookie"
-
Key: "stickiness.lb_cookie.duration_seconds"
Value: "86400"
-
Key: "slow_start.duration_seconds"
Value: "0"
-
Key: "load_balancing.algorithm.type"
Value: "round_robin"
TestListenerRule1:
Type: "AWS::ElasticLoadBalancingV2::ListenerRule"
Properties:
Priority: "1"
ListenerArn: !Ref HTTPSListener
Conditions:
-
Field: "host-header"
Values:
- "test1.helloworld.com"
Actions:
-
Type: "forward"
TargetGroupArn: !Ref TestTargetGroup
Order: 1
ForwardConfig:
TargetGroups:
-
TargetGroupArn: !Ref TestTargetGroup
Weight: 1
TargetGroupStickinessConfig:
Enabled: false
Outputs:
ALB:
Description: The created loadbalancer
Value: !Ref ApplicationLoadBalancer
TargetGroup:
Description: The created TargetGroup
Value: !Ref TestTargetGroup
LoadBalancerSecurityGroup:
Description: the securty group for the ALB
Value: !Ref ALBSecurityGroup
确保在HTTPS侦听器下,用生成的证书ARN替换证书。
同样,根据侦听器规则,我们应该将主机标头替换为用户在Route 53托管区域上创建的记录集。
资源的标签和名称也应根据用户的要求进行自定义。
ECS任务和服务定义
ECS任务定义定义了Docker容器的要求。
它定义要使用的图像,CPU和内存要求等an Service定义定义了如何运行应用程序/服务。
它定义了启动类型,将运行服务的群集,目标组用于ALB,任务定义使用等
创建ECS任务执行角色
n/b:通常已经在AWS帐户上创建了任务执行角色。
一个人可以搜索它 ecsTaskExecutionRole。
如果尚未在帐户创建一个,请使用下面的CloudFormation模板创建一个。
AWSTemplateFormatVersion: "2010-09-09"
Description: "Template to create ECS Task Execution Role"
Resources:
ECSTaskExecutionRole:
Type: 'AWS::IAM::Role'
Properties:
Description: The ECS task execution Role
RoleName: AWSECSTaskExecutionRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Tags:
-
Key: "Project"
Value: "test-blog"
-
Key: "Environment"
Value: "test"
-
Key: "createdBy"
Value: "Maureen Barasa"
-
Key: "Name"
Value: "AWSECSTaskExecutionRole"
Outputs:
IAMRole:
Description: the role created
Value: !Ref ECSTaskExecutionRole
Export:
Name: !Sub "${AWS::StackName}-rolename"
创建ECS任务和服务定义
使用以下模板创建任务和服务定义.n/b:模板为fargate群集创建任务和服务定义。
此外,对于任务角色和任务执行角色ARN,使用ARN for上面创建的角色,或者如果存在,则使用ARN for EcstAskexecutionRole.to为EC2集群创建任务和服务定义,用EC2替换Service Definition上的LaunchType。
在任务定义上,EC2可以使用任何网络模式; AWSVPC,桥梁或者主机。
FARGATE仅适用于AWSVPC模式。
AWSTemplateFormatVersion: "2010-09-09"
Description: "hello-world task and service definition"
Parameters:
VPC:
Type: String
Description: The vpc to launch the service
Default: vpc-ID
Subnet1:
Type: String
Description: The subnet where to launch the service
Default: subnet-ID
Subnet2:
Type: String
Description: The subnet where to launch the service
Default: subnet-ID
Resources:
CWLoggroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: ecs-hello-world-Loggroup
TaskDefinition:
Type: "AWS::ECS::TaskDefinition"
Properties:
ContainerDefinitions:
-
Essential: true
Image: 429758582529.dkr.ecr.eu-central-1.amazonaws.com/hello-world:latest
LogConfiguration:
LogDriver: "awslogs"
Options:
awslogs-group: !Ref CWLoggroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: "ecs"
Name: "Hello_World"
PortMappings:
-
ContainerPort: 80
HostPort: 80
Protocol: "tcp"
Family: "Hello_World"
TaskRoleArn: arn:aws:iam::429758582529:role/AWSECSTaskExecutionRole
ExecutionRoleArn: arn:aws:iam::429758582529:role/AWSECSTaskExecutionRole
NetworkMode: "awsvpc"
RequiresCompatibilities:
- "FARGATE"
Cpu: "256"
Memory: "512"
ServiceDefinition:
Type: "AWS::ECS::Service"
Properties:
ServiceName: "hello-world"
Cluster: "arn:aws:ecs:eu-central-1:429758582529:cluster/eu-central-1-test-ECS-Fargate-Cluster"
LoadBalancers:
-
TargetGroupArn: "arn:aws:elasticloadbalancing:eu-central-1:** **** **** **:targetgroup/test-fargate-hello/** **** ***"
ContainerName: "Hello_World"
ContainerPort: 80
DesiredCount: 1
LaunchType: "FARGATE"
PlatformVersion: "1.4.0"
TaskDefinition: !Ref TaskDefinition
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: "ENABLED"
SecurityGroups:
- "sg-ID"
Subnets:
- !Ref Subnet1
- !Ref Subnet2
HealthCheckGracePeriodSeconds: 300
SchedulingStrategy: "REPLICA"
Outputs:
HelloTaskDefinition:
Description: The created name of the ECS TaskDefinition
Value: !Ref TaskDefinition
HelloService:
Description: The ECS service
Value: !Ref Service
N/B:CloudFormation模板应定制到用户的要求。
我们可以自定义:要配置的资源的名称。
对于容器定义,我们可以更改图像名称,端口映射等。
用户/阅读器还应该替换群集和目标组ARN以反映他/她自己的价值。
完成后,我们应该在ECS集群上运行的服务如下。
我们现在可以通过我们创建的域名访问服务。

