亚马逊AWS官方博客

从零开始搭建您的CI/CD Pipeline(上)

本教程分为上下两部分,结合上下两部分的内容我们将完成如下功能:

  • 将代码存储在Github代码仓库中
  • 每次代码更新,将会触发Codebuild的CI流程,进行镜像打包,并将最新镜像存储在镜像存储库(例如 Amazon ECR)中。
  • 使用 CodeDeploy 以蓝/绿部署的方式使用负载均衡器将流量路由和部署到 Amazon ECS 集群和负载均衡器。 CodeDeploy 使用侦听器将流量重新路由到 AppSpec 文件中指定的更新容器的端口。
  • 通过Code Pipeline构建完整CI/CD流程,每次代码更新自动触发构建和部署动作。

此流程涉及以下部件:

  • Github/CodeCommit的代码仓库(两者在本例中起到同样的作用,配置方式和使用方式基本一致)。
  • CodeBuild使用的buildspec .yml文件。指明您所需要构建命令和相关设置,以及本次构建的输出结果。
  • 一个自己编写的Dockerfile,用于打包镜像。
  • 一个ECR镜像仓库,存储您的docker镜像。
  • Amazon ECS 集群和ECS 任务定义,在ECS 任务定义中,我们将指明您的容器名称、Amazon ECS 服务名称和负载均衡器配置,ECS将用以上配置运行您的容器服务。
  • CodeDeploy 使用的appspec .yaml文件,它指定Amazon ECS 任务定义文件的名称、更新的应用程序容器的名称以及CodeDeploy 重新路由生产流量的容器端口。

前提

您需要已经创建以下资源:

  • 一个Github或者CodeCommit代码仓库。
  • 一个构筑在多个可用区上的VPC
  • 一个已经安装了AWS CLI version 2的计算环境,可以是您的本地Mac或者云端EC2实例。

Step 1: 创建您自己的代码项目

如果您已经有了Github上的项目,可跳过此步骤。本例中我们使用已经创建好的项目,名为:aws-ecs-cicd-sprinboot-eureka。如果您还没有创建Github的项目,可以参考下图。

Step 2: 创建您自己的ECR镜像仓库

您可以通过AWS控制台或者CLI来创建您的ECR镜像仓库,用于存储docker镜像。请参考创建一个私有镜像仓库文档来创建您自己的镜像仓库。本例中,我们的ECR镜像仓库名为eureka。

当您创建好镜像仓库后,请点击“查看推送命令”按钮来查看您该如何提交您的镜像。

以下推送镜像的命令将会在后续的buildspec.yml文件中被使用。

Step 3: 创建Dockerfile和buildspec.yml文件

提示:本例中代码基于JAVA语言编写

  1. yml文件是构建命令和相关设置的集合,采用 YAML 格式,CodeBuild 使用它们来运行构建。您可以将buildspec.yml文件包含在源代码中,也可以在创建构建项目时定义构建规范。关于buildspec.yml文件的更多解释,请参考:CodeBuild 的工作原理

本例中使用的buildspec.yml文件如下:

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto11
  pre_build:
    commands:
      - echo Doing mvn test...
      - mvn test
      - echo Logging in to Amazon ECR...
      - aws ecr get-login-password --region <region-code> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region-code>.amazonaws.com
  build:
    commands:
      - echo Build started on `date`
      - mvn package
      - docker build -t eureka .
      - docker tag eureka:latest <account-id>.dkr.ecr.<region-code>.amazonaws.com/eureka:latest
  post_build:
    commands:
      - echo Build completed on `date`
      - docker push <account-id>.dkr.ecr.<region-code>.amazonaws.com/eureka:latest
      - echo Writing image definitions file...
      - printf '{"ImageURI":"<account-id>.dkr.ecr.<region-code>.amazonaws.com/eureka:latest"}' > imageDetail.json
artifacts:
  files: 
    - imageDetail.json
    - taskdef.json
    - appspec.yaml
  1. Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。本例中使用的Dockerfile如下:
FROM 190547127216.dkr.ecr.us-west-2.amazonaws.com/jdk11:latest
MAINTAINER jieding
LABEL app="eureka" version="0.0.1" by="jieding"
COPY ./target/eureka-server-1.5.10.RELEASE.jar eurekaserver.jar
CMD java -jar eurekaserver.jar

Step 4: 创建Codebuild项目

本章接我们将会进行持续集成功能的配置。创建Codebuild项目,并通过该项目打包我们的第一个镜像。

首先请进入Codebuild控制台,点击右侧的创建构建项目按钮。

    • 在弹出的Codebuild页面中输入项目名称。
    • 部分,源提供商选择Github。如果您是第一次使用私人Github作为数据源,那么页面将会引导您输入自己的Github地址并进行OAuth认证。此后请根据引导选取我们在Step1中创建的项目作为项目源。
    • 环境中,本例中我们将基于corretto11对以JAVA语言开发的项目进行编译,所以环境是配置如下:

    1. 角色名称部分可以选择新服务角色,并输入相应的角色名称。注意:如果在Codebuild创建好之后提示编译过程中推送镜像失败,有可能是因为该角色没有ECR的权限。可以通过在IAM控制台中找到该角色并添加ECR的读写权限解决该问题。
    2. 在Buildspec选择使用buildspec文件。
    3. 点击创建构建项目,此时您将回到Codebuild的控制台,并在右上角看到开始构建按钮。点击该按钮,您会开始第一次构建您的镜像文件。

截止到目前,我们已经完成了CI/CD通道中CI的部分,当您再次打开ECS控制台,选择存储库,选择我们在Step2中创建好的镜像仓库eureka时,您将会看到自己构建好的第一个镜像,该镜像标签为latest。接下来,我们来创建ECS集群和服务。

Step 5:  创建您的Amazon ECS 集群和服务

在本章节中,我们将创建一个 Amazon ECS 集群,和一个ECS任务定义,和一个ECS服务

5.1 创建ECS集群

  1. 通过链接: https://console.aws.amazon.com/ecs/ 打开 Amazon ECS 控制台.
  2. 在左侧导航栏里找到Amazon ECS选项卡,点击集群.
  3. 选择创建集群.
  4. 选择集群模版中,点击EC2 Linux+联网并点击下一步。
  5. 输入一个集群名称,并根据页面提示选择实例类型,根据实际需求填写实例数量。
  6. 在联网选项卡中选择和您想搭建ECS集群的VPC和子网,并设置好安全组,在容器实例IAM角色中,选择相应的角色或者根据自己的实际需求创建新的角色。这个角色会被添加在您ECS集群中的EC2实例上,用于Amazon ECS 容器代理将调用 Amazon ECS API 操作
  7. 进行以上配置后,点击创建按钮.

5.2 编写ECS服务所使用的任务定义文件

    1. 创建一个名为json 的文件,内容如下。对于image,输入您的镜像名称,您可以在console中如下部分找到对应image字段的内容。

注意:确保任务定义中指定的执行角色包含 AmazonECSTaskExecutionRolePolicy。有关更多信息,请参阅 Amazon ECS 开发人员指南中的 Amazon ECS 任务执行 IAM 角色

{
    "executionRoleArn": "arn:aws:iam:: <account-id>:role/ecsTaskExecutionRole",
    "containerDefinitions": [
        {
            "name": "eureka",
            "image": "<account-id>.dkr.ecr. <region-code>.amazonaws.com/eureka:latest",
            "essential": true,
            "portMappings": [
                {
                    "hostPort": 80,
                    "protocol": "tcp",
                    "containerPort": 80
                }
            ]
        }
    ],
    "requiresCompatibilities": [
        "EC2"
    ],
    "networkMode": "bridge",
    "cpu": "256",
    "memory": "512",
    "family": "eureka"
}
  1. 通过AWS Cli注册您的任务定义,cli参数为我们刚创建好的json。
aws ecs register-task-definition --cli-input-json file://taskdef.json

将配置文件推送至Github代码仓库中

将我们此前编写的yaml文件和json文件推送至您的Github的仓库。截止当前,您的Github项目的目录结构应如下所示:

/my-demo-repo
	 |-- src/…		
    |-- taskdef.json
|-- buildspec.yml
|-- Dockerfile

目前我们已经完成了如下工作:

  • 代码和镜像的创建
  • 构建项目的创建
  • 计算环境搭建(ECS集群创建、任务定义注册)

在本篇博客中,我们完成了持续集成的功能。在下一篇博客中我们将介绍持续部署部分如何进行,以及如何使用CodePipeline完成两个部分的结合。

本篇作者

丁杰

AWS 解决方案架构师,8年以上大型移动互联网研发及技术管理经验,资深云计算行业从业者。对EDA行业上云以及针对云上架构进行优化设计有深入理解。了解云计算及半导体行业技术发展变革方向,能针对云服务特点在行业解决方案上有前瞻性布局