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集群上运行的服务如下。
我们现在可以通过我们创建的域名访问服务。