使用CloudFormation将Docker容器自动部署到AWS

当你利用 CloudFormation 在 YAML 模板中定义你的基础设施时,将 Docker 容器部署到 AWS弹性容器服务(ECS)是直接和自动化的。在这里,我们将通过一个简单的例子,我们将设置在 AWS 中运行一个 NGINX 容器并通过互联网访问它所需的一切。

AWS ECS 概述

我们选择运行 NGINX 官方的 Docker 镜像,因为它将允许我们浏览到 80 端口并查看响应,以证明容器正在运行。为了让这个部署到 ECS 中,我们需要以下构件。

  • ECS 任务定义: 你的容器的规范,包括使用什么 Docker 镜像,暴露什么端口,以及分配什么硬件资源
  • ECS 任务: ECS 任务定义的一个运行实例。相当于一个正在运行的 Docker 容器
  • ECS 服务: 负责运行任务定义的实例,包括部署的数量、网络和安全
  • ECS 群组: ECS 服务和任务的分组
  • ECS 任务执行角色: 任务将承担的 IAM 角色,在我们的案例中,允许将日志事件写入CloudWatch
  • 安全组: 可以将安全组附加到 ECS 服务上,我们将用它来定义允许进入 80 端口的容器的规则。我们将用它来定义允许在 80 端口进入容器的规则
    使用CloudFormation将Docker容器自动部署到AWS_第1张图片
  • ECS 任务执行角色: 任务将承担的 IAM 角色,在我们的案例中,允许将日志事件写入CloudWatch

AWS ECS 发射类型

ECS 任务可以根据您的要求,以 2 种模式运行。

  1. EC2:您负责为您的任务运行的 EC2 实例进行配置。
  2. Fargate:AWS 会提供硬件,让你的任务在上面运行。你需要做的就是指定内存和CPU 需求。请注意,Fargate 目前只支持非持久性存储卷。

在这个例子中,我们将使用 Fargate 发射类型,因为它是最快速的入门方式。✔

先决条件

为了使这个例子尽可能的简单,我们将假设你已经有了下面的设置。

  • 设置了 AWS CLI 访问权限的 AWS 账户。
  • 一个默认的 VPC(AWS 在您创建 AWS 帐户时默认创建这个)

使用 CloudForm 构建 ECS

我们将使用 YAML 风味的 CloudFormation,并逐个建立一个堆栈,直到我们有一个 NGINX容器运行,我们可以通过互联网访问。
我推荐 IntelliJ IDEA 来编辑 CloudFormation 模板,因为它有一个插件,可以提供语法验证。

创建 ECS 群集、日志组、执行角色和安全组

首先创建一个文件 ecs.yml,并添加以下定义。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  SubnetID:
    Type: String
Resources:
  Cluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: deployment-example-cluster
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: deployment-example-log-group
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: deployment-example-role
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
  ContainerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: ContainerSecurityGroup
      GroupDescription: Security group for NGINX container
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

参数

我们的模板只需要一个参数,SubnetID,来指定将 ECS 任务部署到哪个子网。在正常的生产设置中,你会希望部署到多个子网的可用性区,以实现高可用性。

集群

AWS::ECS::Cluster资源除了名称外,不需要其他配置。

日志组

ECS 任务将把应用日志记录到这个日志组。

执行作用

这是 ECS 任务在执行过程中要承担的角色。因此,它需要所提供的承担角色策略文档,允许ECS 任务承担这个角色。
它还附加了 AmazonECSTaskExecutionRolePolicy,其中包含了 logs:CreateLogStreamlogs:PutLogEvents 等动作。

安全组

安全组定义了哪些网络流量将被允许访问 ECS 任务。在我们的例子中,我们只需要访问 80 端口,即默认的 NGINX 端口。
让我们使用以下 AWS CLI 命令应用此模板,创建一个 CloudFormation 堆栈来供应上述资源。记住要用自己的子网来代替

$ aws cloudformation create-stack --stack-name example-deployment --template-body file://./ecs.yml --capabilities CAPABILITY_NAMED_IAM --parameters 'ParameterKey=SubnetID,ParameterValue='

最终,如果您在 AWS 控制台中导航到 CloudFormation > Stacks > example-deployment > Resources,您会看到以下资源已经创建。
使用CloudFormation将Docker容器自动部署到AWS_第2张图片

创建任务定义和服务

将以下定义添加到 ecs.yml CloudFormation 模板的末尾。

//previous template code  
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: deployment-example-task
      Cpu: 256
      Memory: 512
      NetworkMode: awsvpc
      ExecutionRoleArn: !Ref ExecutionRole
      ContainerDefinitions:
        - Name: deployment-example-container
          Image: nginx:1.17.7
          PortMappings:
            - ContainerPort: 80
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-region: !Ref AWS::Region
              awslogs-group: !Ref LogGroup
              awslogs-stream-prefix: ecs
      RequiresCompatibilities:
        - EC2
        - FARGATE
  Service:
    Type: AWS::ECS::Service
    Properties:
      ServiceName: deployment-example-service
      Cluster: !Ref Cluster
      TaskDefinition: !Ref TaskDefinition
      DesiredCount: 1
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          Subnets:
            - !Ref SubnetID
          SecurityGroups:
            - !GetAtt ContainerSecurityGroup.GroupId

任务定义

我们正在定义一个 AWS::ECS::TaskDefinition,其重要属性如下。

  • _族_是一种将同一任务定义的不同版本进行分组的方式。
  • 我们指定了多少硬件资源用于这个任务。
  • 我们使用的是网络模式 awsvpc,这是 Fargate 启动类型所需要的。这个网络模式意味着我们的任务将拥有和 EC2 实例一样的网络能力,比如它自己的 IP 地址。
  • 我们之前定义的 执行角色
  • 容器定义,指定映像、容器端口和日志配置,以告诉它使用 awslogs 日志驱动程序进行日志记录(即到 CloudWatch)。
  • 我们指定该任务定义与 EC2 和 Fargate 发射类型兼容(尽管我们将使用 Fargate)。

服务项目

我们正在定义一个AWS::ECS::服务,其属性如下。

  • 该服务将部署任务的 ECS集群
  • 要部署的 任务定义
  • 要运行的实例数量。对于这个简单的例子,我们将运行 1 个,但对于高可用性,你会希望至少运行 2 个。
  • 的_发射类型_,这样我们就不用担心硬件的配置问题了。
  • 网络配置,其中指定了我们想要的公共 IP 地址、服务要使用的子网以及要应用的安全组。

现在让我们用 update-stack 命令更新 CloudFormation 栈。

$ aws cloudformation update-stack --stack-name example-deployment --template-body file://./ecs.yml --capabilities CAPABILITY_NAMED_IAM --parameters 'ParameterKey=SubnetID,ParameterValue='

稍等片刻,然后您可以看到我们的 CloudFormation 堆栈中又创建了一些资源。
使用CloudFormation将Docker容器自动部署到AWS_第3张图片

掌握我们的ecs资源

前往 ECS > 服务,我们来看看有什么创造。
你会看到 deployment-example-cluster,它重要有 1 个服务和 1 个正在运行的任务。
单击群集,然后单击_“任务”_选项卡。
使用CloudFormation将Docker容器自动部署到AWS_第4张图片

这里可以看到我们使用的是我们在 CloudFormation 中定义的任务定义,任务状态为运行,启动类型为 Fargate。
点击任务 id 查看更多详情。这里是详情页的网络部分。
使用CloudFormation将Docker容器自动部署到AWS_第5张图片
你可以看到这里我们已经得到了任务的公共 IP 地址。去试试在浏览器中打这个 IP。
使用CloudFormation将Docker容器自动部署到AWS_第6张图片
看来我们得到了一个 NGINX!

写在最后

要清理的话,只需运行 delete-stack 命令即可。

$ aws cloudformation delete-stack --stack-name example-deployment

希望你已经看到,在 ECS 中运行 Docker 容器是很直接的,而且 AWS 提供了大量的配置选项,可以让事情完全按照你的意愿工作。
使用 CloudFormation,可以直接进行增量更改,是管理 ECS 集群的好选择。

你可能感兴趣的:(aws,运维)