AWS上的无服务器CI / CD



如果复制粘贴部署已成为过去,那将很酷,但是,情况有所不同。 碰巧开发人员更喜欢这种交付方式。 尽管现在写了一篇关于为什么不引起关注的文章,但是没有我,您什么都知道。 随着无服务器架构的趋势,CI / CD管道在应用程序交付中扮演着重要角色。 我还在“ 下一个无服务器项目的3个最佳技巧 ”一文中对此进行了介绍。


很久以前,我一直对CI和CD感兴趣,而几年前我第一次遇到它-感谢TeamCity。 目前,TeamCity仍用于我们的大多数CI / CD管道。 TeamCity的工作很棒,我对此没有反对,但我一直在努力改善工作。 例如,以代码形式收集管道会很好-这是TeamCity不太擅长的领域之一。


我前一段时间在AWS上学习了集成和交付工具,尽管我们将CodeDeploy用于可在EC2上运行的另一个项目,但我尚未与它们一起部署无服务器项目。 在再次查看这些工具之后,我注意到了这一点:现在有一个内置的集成功能,用于部署CloudFormation和Lambda(大概基于SAM AWS); 我们使用无服务器框架 -它生成CloudFormation模板,但无法与AWS工具一起使用。


准备工作


我使用以下AWS服务:EC2,Docker,ECR,S3,IAM,CodeBuild,CodePipeline,CloudWatch,CloudTrail。 为了跟上步伐,您至少需要基本了解这些服务的功能。


基本上,我在.NET中编写服务器端代码,并且本指南也依赖于此平台。 没有一个预构建的CodeBuild映像同时具有.NET和NodeJS运行时(无服务器框架需要NodeJS)。 如果您的Lambda函数是用NodeJS编写的,则配置部署管道要简单得多,因为这是安装Docker映像所需的唯一运行时环境(如果需要,请跳过大多数手册)。 第二,这是我第一次使用容器,我很高兴学习新知识。


我敢于假设您的代码在某个存储库中,例如git。 作为指导,我们只需将包含一包用于部署的代码包的文件上传到S3; 您如何获得它取决于您。 以我的工作为基础,可以始终通过将管道连接到诸如github或CodeCommit之类的存储库来走得更远。


1.创建一个EC2实例并安装Docker


运行AWS Linux 2 EC2的标准实例-应该清楚而无需解释。 使用以下命令登录并安装Docker:


sudo yum update -y sudo amazon-linux-extras install docker sudo service docker start 

您还需要将用户ec2添加到docker组中,以在不使用sudo的情况下执行Docker命令:


 sudo usermod -a -G docker ec2-user 

命令完成后,注销并重新登录到EC2实例,以便ec2用户获得新的权限。 确保ec2用户在不使用sudo的情况下运行Docker命令:


 docker info 


docker info输出


2.创建一个Docker映像并将其放置在ECR中


假设上一步成功; 下一步是创建适合ECR的Docker映像。 AWS 在github上CodeBuild提供了基本映像,这使创建自己的映像变得容易。


我还将图像发布在github上-以防您不想按照以下步骤创建自己的图像: https : //github.com/effectivedigital/serverless-deployment-image


复制图像并转到.NET Core 2.1目录:


 git clone https://github.com/aws/aws-codebuild-docker-images.git cd aws-codebuild-docker-images cd ubuntu/dot-net/core-2.1/ 

在首选的文本编辑器中打开Dockerfile:


 nano Dockerfile 

在Dockerfile中已经可用的其他命令的末尾添加用于安装NodeJS和无服务器框架的命令。 这些命令大部分来自同一AWS存储库中的NodeJS Docker映像:


 # Install Node Dependencies ENV NODE_VERSION="10.14.1" # gpg keys listed at https://github.com/nodejs/node#release-team RUN set -ex \ && for key in \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ 77984A986EBC2AA786BC0F66B01FBB92821C587A \ 56730D5401028683275BD23C23EFEFE93C4CFFFE \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ 4ED778F539E3634C779C87C6D7062848A1AB005C \ A48C2BEE680E841632CD4E44F07496B3EB3C1762 \ ; do \ gpg - keyserver hkp://p80.pool.sks-keyservers.net:80 - recv-keys "$key" || \ gpg - keyserver hkp://ipv4.pool.sks-keyservers.net - recv-keys "$key" || \ gpg - keyserver hkp://pgp.mit.edu:80 - recv-keys "$key" ; \ done RUN set -ex \ && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VER$ && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc \ && gpg - batch - decrypt - output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local - strip-components=1 \ && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN npm set unsafe-perm true CMD [ "node" ] # Install Serverless Framework RUN set -ex \ && npm install -g serverless 

现在,我们收集并标记图像:


 docker build -t aws/codebuild/dot-net . 

完成组装后,运行映像-确保一切正常,并且正确安装了无服务器框架:


 docker run -it --entrypoint sh aws/codebuild/dot-net -c bash sls -v 


在全新的容器中运行sls -v


然后使用AWS CLI在ECR中创建存储库。 运行命令后,新的存储库将显示在AWS控制台中:


 aws ecr create-repository --repository-name codebuild-dotnet-node 


AWS CLI响应以在ECR中创建存储库



现在,使用上一步中值repositoryUri标记先前创建的aws / codebuild / dot-net映像:


 docker tag aws/codebuild/dot-net <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node 

运行get-login命令以获取容器注册表的docker登录认证命令行:


 aws ecr get-login --no-include-email 


在最后一步中,运行由get-login命令发出的docker login命令。


 docker login -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhJT1c0WWpOZEcxamJFeFJOK2VvT0Y5[...] https://<ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com 

如果登录成功,则将Docker映像放入ECR中创建的存储库中。 这可能需要几分钟(取决于完整图像的大小)。


 docker push <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node 


EC2上的Docker创建了我们的映像



ECR中的Docker映像


然后,我们可以向任何人开放从ECR访问图像的权限。 该权限必须在工作环境中被阻止,但是在本示例中,我们将打开它。 转到AWS控制台中的权限选项卡,选择“更改JSON策略”,然后将以下元素插入该策略:


 { "Version": "2008-10-17", "Statement": [ { "Sid": "EnableAccountAccess", "Effect": "Allow", "Principal": "*", "Action": [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr:DescribeImages", "ecr:DescribeRepositories", "ecr:GetAuthorizationToken", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:ListImages" ] } ] } 

3.创建管道


现在该收集管道了。 为了简化流程,使其可多次部署并坚持灾难性的无服务器架构形式,我使用无服务器框架构建了管道。 您可以通过在CloudFormation中构建来达到相同的结果。


我不会从我的serverless.yml文件复制整个源-从github复制它: https : //github.com/effectivedigital/serverless-deployment-pipeline


签出无服务器模板,以确切地了解它会做什么,但是简而言之,它设置了以下各项:


  • 3段S3
  • 1个区隔政策
  • 3个IAM角色
  • 1个CodeBuild项目
  • 1条管道CodePipeline
  • 1个CloudWatch事件
  • 1条CloudTrail痕迹

然后在ECR中为您的映像更新DockerImageArn 。 如果要使用Deployment.zip以外的名称创建部署程序包,请同时更新DeploymentFilename


 DockerImageArn: <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node:latest DeploymentFilename: Deployment.zip 

就是这样,管道已准备好进行部署。 运行无服务器部署命令,然后等待其配置:


 sls deploy -v 


创建无服务器框架堆栈CloudFormation



由无服务器框架管道CodePipeline创建



由无服务器框架项目CodeBuild项目创建


4.将buildSpec.yml添加到您的应用程序


当CodePipeline在S3中检测到对部署文件的更改时,它告诉CodeBuild启动并尝试构建和部署应用程序。 但是,CodeBuild还必须知道必须执行哪些命令才能构建和部署应用程序,并且buildSpec.yml包含CodeBuild将遵循的指令。


我创建了一个非常简单的“ Hello world”应用程序,其中包括一个示例buildSpec.yml文件,您可以使用该文件: https : //github.com/effectivedigital/serverless-deployment-app
或在现有应用程序中创建buildSpec.yml文件,然后根据以下说明进行填写:


 version: 0.2 phases: pre_build: commands: - chmod a+x * build: commands: - ./build.sh post_build: commands: - sls deploy -v -s $STAGE 

5.管道检查


现在,一切准备就绪,可以首次启动管道。 创建一个名为Deployment.zip的软件包,其中应包括无服务器应用程序的所有文件和buildSpec.yml文件。


片刻之后,CloudTrail应该注册一个PutObject事件并激活CloudWatch事件规则,然后再激活CodePipeline触发器。



部署到S3的Deployment.zip



CodePipeline启动,构建已启动


如果继续进行AWS CodeBuild步骤的细节,我们可以看到构建和部署过程:



CodeBuild将接收来自构建和部署Docker映像的输出



部署成功!


我们的管道部署的新应用程序也出现在CloudFormation中:



您可以测试在我们的简单应用程序中创建的API端点(URL在CodeBuild输出或Gateway API中),并确保该应用程序成功运行:



邮递员调用API


简要结论


CodePipeline允许您创建可伸缩,灵活且廉价的CI / CD管道,它有助于解决与在服务器上创建的传统管道相关的一些问题。
我想走得更远,并在部署后将单元测试添加到组合中,但是该主题值得另写一篇文章,这是将来阅读我们的机会!

Source: https://habr.com/ru/post/zh-CN440756/


All Articles