【实战】持续集成与持续交付

    今天我们讨论CI/CD,即持续集成(Continuous Integration)与持续部署(Continuous Deployment),这对于软件交付工程师或程序员来说非常重要。
首先我们说CI-持续集成,这是为保证不同功能的开发人员所贡献的代码保持同步,简单的说就是通过自动测试、验证与反馈的方式实现程序员间的协同。比如说开发团队将自己的代码库都放在Github上,然后每个开发人员都Fork了一个副本在本地做开发测试,最终我们希望将每个开发人员的代码段集成到主线(Mainline)中,在这之前我们需要创建测试案例保证程序不仅可以单步运行,也可以按照主线的逻辑运行不至于影响其他模块。在持续集成的场景中,开发人员可以不断拉测试案例来验证程序运行正常,与主线兼容良好,不会在发布时有巨大改动。
再说持续部署,他将持续集成所编译的程序部署到环境中,既然是持续部署,就可以是某个特定项目的多个场景,比如说临时环境(Staging Environment)、测试环境(Testing Environment)、验收环境(Acceptance Environment)最后是生产环境(Production Environment)。当然也包括了各个环境中的高可用、负载均衡等场景。
持续集成和持续部署的工具有AWS CodeBuild/CodeDeploy,Atlassian Bamboo和Jenkins。我们拿一个Python Flask web应用来说,首先我们需要做本地测试,包括单元测试,语义测试和功能测试。通过了上述这些测试才能说明本地开发完成。接下来我们需要拉取一些需求,这些需求是要将本地代码段并入总线(Master Branch)前的一组测试案例,包括安装、测试案例执行、语义分析、单元测试和评论(为和项目组其他成员协同开发,必须兼容评论功能)。

【实战】持续集成与持续交付

    并入总线后,我们会继续测试包的安装、构建、创建缺陷、创建版本、推到‘提交’阶段(提交阶段是持续集成和持续部署的分水岭)。进入部署阶段,工具会从‘提交’库中获取安装包,继续在临时环境测试、部署场景验证、负载均衡测试、并发连接测试、应用安装、验证和提交。

【实战】持续集成与持续交付

    在临时环境有测试人员,甚至会有最终用户,完成全部功能点的测试之后会提交进入下一环境,上到临时环境之后,AWS的CodeBuild可以模拟负载均衡环境来验证程序对环境的适应性。

【实战】持续集成与持续交付

    我们的Python Flask web应用程序也非常简单,只是一个调用Rest API的安装程序。

【实战】持续集成与持续交付

    我们在CodeBuild中创建一个项目:

【实战】持续集成与持续交付

    输入项目名称,必要的话,可以添加注释。

【实战】持续集成与持续交付

    接下来我们选择程序源,我们的代码库存放在Github上,用户名是bundyfx下的flaskerino数据库。关于Webhook,在Github的代码库中不需要创建Webhook,通过AWS CodeBuild项目中的复选框会自动关联Github的代码库从而自动创建Webhook。

【实战】持续集成与持续交付

    接下来可以选择运行环境,包括选择CodeBuild的镜像还是自定义Docker镜像、操作系统、编译环境和版本等等。

【实战】持续集成与持续交付

    如果最后选择使用buildspec.yml来作为Build的配置文件,以下是此yml文件的样式:

【实战】持续集成与持续交付

    在这个yml文件中,我们可以看到CodeBuild分为两个阶段(Phase):安装阶段和预构建阶段。在安装阶段,首先执行的是更新pip(对于不熟悉python开发的朋友,这里普及一下,pip 是 Python 包管理工具,该工具提供了对Python 包的查找、下载、安装、卸载的功能);然后是安装根目录下即setup.py中定义的所有安装包,即flask和pylint

【实战】持续集成与持续交付

    预构建阶段执行的两个命令,先是找到所有*.py的文件,然后对其语义进行检查(即pylint,python linting);然后在对此项目做单元测试。之后我们定义了一个artifacts:语句,意为将所有输出文件作为制品打包提交给下一阶段。
制品输出位置只有Amazon S3可选,它相当于一个制品杂货店,CodeBuild可以在这个杂货店里寄存和取出制品部署到各个环境中。

【实战】持续集成与持续交付

    除了上述选项之外,还有些高级选项,包括选择加密S3,制品打包格式、资源耗费(一般情况3GB,2vCPU绰绰有余了),环境变量等等。

【实战】持续集成与持续交付

    和其他的云产品一样,AWS CodeBuild仅根据你的使用时间来收费。创建完CodeBuild的项目之后,由于我们之前勾选了自动关联Github的代码库变化。在Github中我们也就自动创建了关联的Webhook。

【实战】持续集成与持续交付

    在URL的释义中标明了pull_request and push,意为当github的此代码库收到推送更新时,CodeBuild会自动对新版本进行构建(包括我们上面所说到的安装、语义测试和单元测试);当CodeBuild这边的项目执行完某个测试之后,在Github的代码库也会收到一个comments标记测试情况。
AWS的CodeBuild实现了构建和测试代码的自动化,今天我们将介绍CodeDeploy,它和CodeBuild并没有太大关联,两者可以独立运行,但在软件开发过程中,串联使用的效果更佳。
再定义完应用名和部署组名后,进入部署方式的选择,CodeDeploy提供了两种部署方式,分别是就地部署(In-place deployment)和迭代部署(Blue/green deployment)。前者意为直接用最新版本替换当前的运行程序,期间可能有文件夹和目录结构的更新,CodeDeploy会自动将相关前端应用指向新的目录位置;后者更适用于有负载均衡的生产场景,比如当前程序有60个实例运行在负载均衡器下,最新版本同样有这些实例。程序可以在指定时间切换,同时保留之前的版本,以便在新版本运行故障时回切。这里我们从生产出发,选择迭代部署(Blue/Green Deployment)

【实战】持续集成与持续交付

    在环境配置中,建议选择复制自动定标组(Automatically copyAuto Scaling group),意为将现行环境的资源分配情况复制到最新版本中并有自适应功能,以保证迭代后对并发压力的应对能力。

【实战】持续集成与持续交付

    在这个配置的下方我们可以看到当前正在运行的所有实例的ID列表以及当前是否启用了负载均衡,这跟我们之后所要配置的迭代方案有密切关系。

【实战】持续集成与持续交付

    在部署设置中,迭代部署的默认配置是一次仅更新一个实例,且立即切换客户端的访问流量到新实例,对于旧实例在切换一小时后停止运行。

【实战】持续集成与持续交付

    当然我们也可以修改这个默认配置,建议是既然要立即切换客户端访问实例,何不一次性替换掉所有的实例。至于旧实例的保留时间,看内部规定或外部法律,这里不做推荐。

【实战】持续集成与持续交付

    最后输入具有部署权限的账号名称,点击Create Application即可完成预部署。

【实战】持续集成与持续交付

    在我们上期讲CodeBuild的时候谈到了Amazon S3制品库,这里我们也可以根据提示直接将S3中的制品位置输入到脚本中完成部署。

【实战】持续集成与持续交付

    值得一提的是,通过CodeDeploy,不仅可以将程序部署在AWS上,还可以部署在本地环境中。除了CodeBuild和CodeDeploy,AWS还提供了可视化工具CodePipeline以方便建模、自动部署目标软件,更直观地控制软件发布的各个阶段。
理论上说,通过CodePipeline可以将我们之前所创建的Build和Application关联起来。我们先创建一个Pipeline试一下,名字和我们之前创建的build和application一致。

【实战】持续集成与持续交付

    接着我们选择代码库的位置,跟之前一样,我们选择Github上的位置。

【实战】持续集成与持续交付

    在选择Build提供者时,因为我们先前创建了项目,这里选择CodeBuild的提供者以及对应的项目名称即可。

【实战】持续集成与持续交付

    同样,下一步时选择部署对象。由于我们之前的部署提供者是AWS的CodeDeploy,选择这个提供者并选择之前创建的应用名和部署组名。

【实战】持续集成与持续交付

    最后我们给刚创建的AWS Pipeline服务取个名字。

【实战】持续集成与持续交付

    CodePipeline就自动帮我们梳理了整个开发流程,并自动开始运行。

【实战】持续集成与持续交付

    运行到每一步,我们都可以进入看到运行的每个细节,比如Build的运行情况。每一个阶段前的小三角箭头都可以继续下钻查看进一步的运行情况。

【实战】持续集成与持续交付

    再比如CodeDeploy阶段,我们可以中断任意正在运行的阶段;查看每一个高可用下属实例的状态及客户流量信息。

【实战】持续集成与持续交付

    除了按照Code Pipeline的向导部署各个阶段外,我们还可以直接编辑当前的Pipeline,例如删掉某个阶段,或添加某个自定义的新阶段。

【实战】持续集成与持续交付
【实战】持续集成与持续交付

    可添加的阶段包括审批、源码、构建、测试、部署和激活。在测试阶段通过之后,我们可以将代码部署到生产环境了。
首先,在我们之前创建的Code Pipeline中添加一个生产阶段。

【实战】持续集成与持续交付

    在生产阶段的配置中,我们需要将其指向到生产的部署组。

【实战】持续集成与持续交付

    保存之后,Code Pipeline就会自动进入蓝绿部署阶段。

【实战】持续集成与持续交付

    在详情页可以查看当前阶段的部署详细报告。

【实战】持续集成与持续交付

    运行完成后,我们就可以考虑更新当前的版本了,点击Pipeline下方的Release Change更新版本。

【实战】持续集成与持续交付

    系统会提示最近的变更将覆盖原始代码,是否据悉,我们点击发布(Release)。

【实战】持续集成与持续交付

   到此,我们就完成了一个项目的敏捷开发。