docker service create 卡住_使用AWS Devops工具结合ECS实现自动化Docker容器部署

451d4f1623ef1c39e846753a97b834b9.png

作者:Ray,神州数码云基地开发人员。

本文介绍了使用AWS Devops工具:AWS Codecommit、AWS Codebuild以及AWS Pipeline进行代码编译、打包、部署的基本流程与操作。

本文要点

本文主要使用的AWS Devops工具有AWS CodecommitAWS Codebuild以及AWS Pipeline

  • AWS Codecommit是一项安全的、可高度扩展的托管型源代码控制服务,可用于托管私有Git存储库。Codecommit可以存储从代码到二进制文件的一切内容,可以与现有的基于Git的工具无缝协作。
  • AWS Codebuild是一项完全托管的生成服务,可编译源代码、运行测试以及生成可供部署的软件包。Codebuild可以持续扩展并同时处理多项构建任务,因此构建任务不会在队列中等待。
  • AWS Codepipeline是一种持续集成与持续交付服务,可以实现快速而可靠的应用程序和基础设施更新。根据自定义的发布流程模型,只要满足触发条件,Codepipeline便会根据流程来构建、测试以及部署代码。

而Docker容器化部署,则主要是利用Amazon Elastic Container Service(ECS)以及Amazon Elastic Container Registry(ECR)

  • ECS是一项高度可扩展的高性能容器管理服务,支持Docker容器,并且能够在托管的Amazon EC2实例集群上轻松运行应用程序。ECS还提供了FARGATE运行类型,这是一种Serverless平台,借助这个平台,容器服务能够运行在Docker容器中,而不是EC2实例中。
  • ECR是完全托管的Docker容器注册表,可以使开发人员能够轻松存储、管理和部署Docker容器映像。并且ECR与ECS集成,从而简化生产工作流程的开发。

问题

作为一个只会写代码的懒人,我的想做的只有生产Bug,至于写代码生产Bug之外的,如编译、打包、部署等等,都太复杂了,所以就想,能不能我每次写完代码,提交合并之后,剩下的都由机器自动帮我完成呢?

加上最近容器化部署又是一大热门,用最少的资源,干最多的活儿,这就绕不开Docker了。但是由于Docker镜像源码或代码构建的变更,Docker容器的部署可能需要更新或修改。Docker镜像中任何代码修改都需要重新构建Docker镜像,Docker服务也需要重新部署。那么问题来了,重新部署可能会导致原来的服务出现停止服务的情况。也就是说,直到新的服务运行起来,这中间是不能提供任何服务的,你的服务是有一个空档期的,这肯定不合适。

解决方案

为了解决上面提出的几个问题,我们需要去引入Devops自动化流程,这时候就考虑到了使用AWS的Devops工具来解决我们的问题。

首先,AWS Codepipeline是一个用于持续集成、持续交付和持续部署的Devops服务,它适用于各种AWS平台上的应用,其中包括Amazon ECS和Fargate平台。其次,通过Codepipeline控制的ECS服务在更新和修改时,可以不用停止ECS服务任务。Pipeline在一个动态的环境中提供了ECS服务的高可用性,所以即便Docker镜像的源码变更需要重新部署ECS服务,也不会出现ECS服务宕机的情况。

AWS Codepipeline简单来说,由三个阶段组成:源代码集成、源代码构建和部署,如下图所示:

a607b4abfac7d3c313da4b88e234e695.png

在源码方面,使用AWS的Codecommit仓库,在源码构建阶段,采用AWS Codebuild项目。在部署方面,选择ECS服务的Fargate启动形式。

搭建环境

要使用AWS上的服务,前提就是需要一个AWS的账号。

第一步,创建一个Codecommit存储库,来存放源代码;

第二步,创建一个Amazon ECR存储库。本文最终目的是需要在ECS Fargate上部署Docker应用,这里选择Amazon ECR作为Docker镜像存储的位置,当然,其余的Docker镜像存储也可以。

第三步,创建一个Amazon ECS集群,用来管理和部署推进ECR仓库重的镜像。

创建Codecommit仓库

进入Codecommit管理界面,点击Create Repository,创建Codecommit存储库。在Repository Name输入存储库名称,接着在Description中写上合适的描述,最后点击Create,即可完成存储库的创建。

39d441a27b6093f1785cff1aca80772c.png

然后根据Connection Steps的步骤,通过Git工具连接上Codecommit存储库,将代码推送进去。

需要注意的是,在源代码中,我们需要编写一个Dockerfile文件,它是将代码打包成Docker镜像的配置文件,到后面会用到。

创建ECR存储库

这一过程就比较简单了,进入ECR管理界面的Repositories,点击右上角的Create Repository创建存储库,进入创建存储库配置页面。存储库的配置分为三个部分,第一部分General Settings,该部分主要是配置基础设置,存储库名称、类型(私有、公有)、标签是否唯一;第二部分,Image Scan Settings,开启之后,则会对每一个推送进来的镜像进行扫描;第三部分,Encryption Settings,这一部分则是KMS加密设置,开启之后会利用KMS(AWS Key Management Service)对存储库中的Images镜像进行加密处理。设置完成之后,点击Create Repository即可完成存储库的创建。

58d3fc6a153635f0f9854a8544c7400f.png

创建和配置S3 Bucket

Codepipeline在构建Node 服务器应用的源码并将其以 Docker 镜像的形式部署为 ECS服务时,需要Codebuild项目生成“输出制件(Output Artifacts)”。输出制件会保存在S3 Bucket中,在创建Codepipeline的时候要选择这个Bucket。在 S3 控制台中创建一个新的S3 Bucket,或者选择之前运行Codepipeline时所创建的S3 Bucket。

进入S3管理控制台,点击侧边栏的Buckets,进入Buckets管理界面,点击右上角的Create Bucket进入创建Bucket配置界面,如下图所示:

191118d5695f57bacd8beec3b9ff1376.png

在Bucket Name一栏写上Bucket名称,其余保持默认就行。创建完成之后,在Bucket界面就会出现一条记录,如下图所示:

d0c2f6ff4d53d76a9f30d4001c185f8f.png

创建Codebuild 中的Build Project

进入Codebuild 管理控制台,点击侧边栏的Build Projects,进入Build Projects管理界面。点击右上角的Create Build Project橙色按钮,进入创建Create Build Project配置界面。在这个界面,可以很清楚的看到,一个完整的Build Project分为7个部分:Project Configuration、Source、Environment、Buildspec、Batch Configuration、Artifacts、Logs。

Project Configuration

这里主要是配置Build Project的基本信息,例如Project Name、Description等。

34fc68d42720f7dbfe367238e5c8b9f8.png

Source

在Source一栏中主要选择是源代码Git存储库以及想要编译的代码。在Source Provider中选择Codecommit,Repository中选择前面创建的源代码仓库,Reference Type选择Branch,然后在下面的Branch选择Master,Commit ID选择最近的一次提交。

f3e38acc63dd2f3bd2f4b727004c6de4.png

Environment

环境根据官方文档的说法来,因为我们Build Project的最终产物是一个Docker镜像,那么环境配置和官方文档上说的保持一致就可以了,也就是我下图所展示的。

这里需要注意的有两点,第一个是Privileged,如果期望Build的产物是Docker镜像,那么就需要将Privileged这一栏勾上,而且其后面解释也很清楚了。第二个是Service Role。在我的配置图中,选择的是New Service Role,意味着它自动的在IAM中去创建一个规则,默认的规则权限是很小的,如果要实现我们的期望——将源码编译打包成Docker镜像并推送到ECR中,后面还需要对这个规则进行修改。

99dae0a30fc91ac4fe8bda4cdcb1e0bc.png

Buildspec

这一步涉及到一个叫做Build Spec,即构建规范的文件,它使用的是YAML语法编写的一系列Build命令,Codebuild会根据这个文件来运行构建步骤。有两种方式存放该文件的内容,第一种,存储在源代码仓库中,在此种方式下,该文件就必须被命名为“Buildspec.yml”并且存在源码仓库的根路径下;第二种就是直接在Build创建的过程中,将Build Commands插进Build过程中。

eeb58243ed2920d887b89e849f2cd9f9.png

Build Spec中主要包括Build的步骤,包括连接ECR存储库,运行Docker打包步骤,推送Docker镜像等。当然,Build还能干更多的事,可以查看适用于 CodeBuild 的构建规范参考

本次示例选择第二种方式,Buildspec文件示例:

version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxx.dkr.ecr.ap-northeast-1.amazonaws.com
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image... 
      - cd ./service
      - docker build -t xxx/backend:latest .
      - docker tag xxx/backend:latest xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx/service:latest    
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx/service:latest
      - cd ..
      - printf '[{"name":"service","imageUri":"xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx/service:latest"}]' > imagedefinitions.json
artifacts:
  files: 
   - ./service/imagedefinitions.json
   - '**/*'
  name: BuildService

在示例中有一个比较重要的东西就是,Imagedefinitions.json这个文件,这是ECS部署的镜像配置文件,它会根据这个文件去寻找镜像。

Batch Configuration

这个配置提供了一个可以将一组构建作为一次执行来运行的选项。当开始构建时,批处理配置在高级选项中也可用。本案例中没有使用,就默认不选。

d2b1ea4a72598b1c8ed53881c52ce701.png

Artifacts

配置Artifacts,主要是配置将Build产物输出到S3中进行存储,在Codepipeline中作为Deploy的输入,这一步是十分重要的。配置参考我下图就可以了。

25a9085ca040d77449dd51f8c3b71e8f.png

关于其详细信息,参阅What is AWS Codeartifact? - Codeartifact (Amazon.com)。

Logs

这是一个收集Build日志的服务,它会将Build过程中的日志信息存储到Cloudwatch中。

fb381a1200fbe90a1e788a567f9e667b.png

测试Codebuild

dd690b7d319018c080e913bbcd5318e2.png

如上图所示,进入Build Projects管理界面,选中想要运行的Project,点击上方的Start Build按钮,即可开始Build项目。点击Project,进入Build Project内部,可以查看该项Project的Build历史,点击每一条构建历史,还能看到该条构建的日志信息。

8a269aa1f5ea59579a36ac9d72def371.png

9b99b46204f7c13ad5f1549c1cdcfe29.png

创建Task Definition

ECS集群中的任务定义(Task Definition)描述了ECS部署环境中的容器。每一个服务都是根据任务定义中的配置来运行的。接下来,为前面Codebuild的产物Docker镜像创建一个任务定义,以便将其部署到ECS Fargate中。

首先进入ECS控制台,然后点击左侧导航栏中的Task Definitions,进入Task Definitions管理界面。点击Create New Task Definition蓝色按钮进入Task Definition配置界面。选择FARGATE,然后点击Next Step,接下来就是配置任务和容器定义。

ec4a82c628b1f99b71b10873a95d3488.png

如图,在Task Definition Name中写上合适的名字,然后在Task Role这一栏中选择ecsTaskExecutionRole,接下来,在Taks Size根据容器服务实际需要的资源选择配置,这里我内存选的0.5GB,CPU选的0.25 vcpu。

配置完任务之后,找到Container Definitions,点击Add Container蓝色按钮,添加容器定义。在Container Name中填上合适的名字,如:Web;在Image一栏中填上镜像URI,这里使用的是ECR存储库,那么URI就类似于http://80xxxxxxxx2174.dkr.ecr.ap-northeast-1.amazonaws.com/repository/web:latest,这里具体的根据实际情况来确定。最后将容器运行服务的端口映射出来,剩下的,根据实际情况配置,这里都选择默认。定义完成之后,点击Add,完成容器定义的添加。

b7910b83e617e5c3825bca17a721fe82.png

最后点击Create即可完成创建Task Definition。如果是和我的配置一样来进行操作的,创建Task Definition的同时还会创建一个Cloudwatch服务。Cloudwatch可以用来监控容器运行时,使用资源的情况。

f3396474b60c2de39c656a3787a8d78d.png

根据Task Definition创建ECS Service

进入ECS Cluster管理界面,选择进入到某个集群中,如下图所示,点击蓝色的Create按钮,创建Services。

dc566eb11b1cd505cb66686c0742dece.png

进入到Create Service配置界面,Service的配置比较简单,这里就不做过多阐述,直接贴图好了。

2c80961b332e5bd286bb9f60afa4ab18.png

需要特别注意的是在Deployment Type这儿,需要选择第一个,Rolling Update,剩下的步骤可以直接参考官方文档,官方文档链接:创建服务 - Amazon Elastic Container Service。

创建完成之后,可以对刚刚创建的Service进行简单的测试,返回最开始创建Service的位置,点击刚刚创建的Service链接,进入其详细界面,有一个Tasks选项栏,点击,如下所示:

c5bfd669424fc95ea05d6e7d00731cd2.png

在这一栏中会展示运行该项Service的所有Tasks,在最开始本实例配置的Task实例是1,所以这里只会有1个Task,以此类推。

点击Task的链接,进入Task详情页,这里会有两个IP地址,如下所示:

7c7cd4f3bb4b38ebbbcd4b2bc8d96924.png

Private IP就是属于VPC网络中的IP地址,只有处于VPC网络中才能访问,Public IP就是属于公网IP了,访问这个IP来验证一下是否创建成功:

70f094e6dfad1b912f4788ee2b08e0ca.png

访问API,会返回结果。

创建Codepipeline

将上面的所有准备工作做完之后,就可以创建Codepipeline了。创建Pipeline的过程会十分简单,只要前面的步骤没有出现错误。

进入Codepipeline管理界面,点击侧边栏的Pipelines进入Pipelines管理页面,然后点击右上角的Create Pipeline创建Pipeline。

Step1,Choose Pipeline Settings,对Pipeline进行一个简单的全局配置。

33c6c5ee00f4673a17923adac91bfaa6.png

在Pipeline Name中输入名称,我这里其余保持默认配置。如果有自己创建S3 Bucket,需要去更改Advanced Settings中的Artifact Store,需要更改为Custom Location,并选择自己创建的S3 Bucket。然后点击Next。

Step2,Add Source Stage,添加源。

c4752a57294a619eab22bc06229f921b.png

本实例中使用的是存放在Codecommit中的存储库,其余保持默认配置。

Step3,Add Build Stage,增加Build步骤。

f2f9a0d735078a622e3b43c42b8d0b5a.png

选择在Codebuild中创建的Buildproject,其余保持默认。

Step4,Add Deploy Stage,增加Deploy步骤。

8db90fd40ecdff3bd8c10edde2f29347.png

Deploy方式选择ECS部署,选择之前在ECS中创建配置的Service,唯一需要注意的,就是Image Definitions File这一栏,默认就是我图中展示的,在根路径下,这个文件根据实际情况更改。

Step5,Review,检查一下,确认无误后点击Create Pipeline就行。

创建完成之后,它会自动触发第一次运行,同时,这也可以检查你Pipeline是否会出现问题。

8ed2e3c38a0aad4d52400ff9d2b25cca.png

没有问题,那当然是一路绿灯啦。

测试Pipeline

接下来,对刚刚创建的Codepipeline进行简单的测试。

18b79577d2e0f5a017ea6d4f0e04ec2e.png

Pipeline当前的状态,是Succeeded,最近一次运行是两个小时之前,接下来,我们随便更改某个文件,对这个Pipeline进行一个简单的测试。修改代码,提交之后,稍等一会,发现Pipeline的状态已经发生了改变,变成了In Progress状态,并且Source也发生了变化,变成了我刚刚的提交。

5e20018d0100aafd76ae9e3aef4fdf9a.png

等待一会儿,它会自己触发配置的步骤,重新编译和更新代码,知道状态变为Succeeded,访问方式在前文创建ECS 服务中已经说过了,这里就不重复了。

fbd061462465383a66a540181629fba2.png

小结

在本文中,我们主要是讨论了如何将源代码利用Devops工具,实现源代码的自动化打包、编译、部署,以及如何将Docker容器应用部署到ECS FARGATE中,并在不停止容器服务的情况下将新的 Docker 镜像部署到正在运行的容器服务中,所有这些都使用 AWS Codepipeline 完成的。用好Devops工具可以很好地利用机器去完成流水线式的工作,极大地节省人力,解放人手,让开发者更专注于开发。


推荐文章传送门:

神州数码云基地:TiKV源码略读-Config​zhuanlan.zhihu.com
6c9f29dcaa6f7eaf729bddee0a713dc5.png
神州数码云基地:微软Canvas App实战之事件驱动 or 数据绑定​zhuanlan.zhihu.com
432dcb99369ea4f412d997e0d7d7c968.png
神州数码云基地:TiDB源码学习笔记:启动TiDB​zhuanlan.zhihu.com
3ba6fbcdb1d06e7bdf282dacc8ecb862.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值