杨晨 艺康集团数字化部门交付管理工程师
你好,我是杨晨。
或许你早已听说过 DevOps,也知道它是 Development 和 Operations 的结合,中文一般叫做开发运维一体化。到底什么是开发运维一体化?它如何帮助我们解决流程问题?下面我会一一解答,并教你如何实践。
虽然 DevOps中没有提到测试,但“一体化”其实是指开发、测试、运维人员三方的紧密合作和全程参与,这是为了缩短从开发、部署到验证需要的时间,以提高新功能交付的频率。
从新代码的提交到程序的部署,一般会经历编译检查、单元测试、代码扫描、冲突检查(分支合并)、打包和部署几个阶段,其中部署又包括部署到测试环境、集成测试,以及测试结束后部署到生产环境。
那如何缩短这个流程所需要的时间呢?DevOps 给出的建议就是实现自动化。从编译Build、测试Test到冲突检查Merge的自动化流程部分,这被称为持续集成(Continuous Integration, CI),而整个自动化全流程,被称为持续交付(Continuous Delivery, CD)。
为什么自动化能够解决问题?因为它避免了人为的操作失误而带来的返工,也避免了个人的工作负荷成为流程的瓶颈。
对于不同角色来说,自动化还有一些额外好处:
当然新方法的实践不可能只有好处、没有代价,要实现 DevOps 自然需要有人来推动三方的合作,也需要有人来搭建和维护 CI/CD 工具。前者更多是组织和文化问题,后者则要落实到具体工作中,可以由开发和运维共同维护 CI/CD 工具,也可以由专门的 DevOps 工程师来维护。
实现自动化有这么多好处,那么我们该怎样选择DevOps工具呢?
市面上有许多优秀的 DevOps 工具,例如微软的 Azure DevOps 和 Github,开源的 Jenkins 和 GitLab,国内的华为 DevCloud 等等,简单介绍一下:
Github 除了是全球最大的代码托管平台,还提供 Github Actions 用于实现 CI/CD,它的特色在于可以搜索他人分享的 CI/CD 脚本来学习和使用;
而开源工具的好处是搭建自由,免费试用,但需要自备服务器来做部署,并付出相当的人力来进行维护;
华为 DevCloud 在国内的网络环境下访问更加稳定,还内置了代码检查、应用测试等工具,便于靠单一工具实现全流程的管理。
我推荐新人使用 Azure DevOps 作为学习工具,因为它的基本功能全面而且免费,开箱即用,有微软背书的可靠性,最关键的一点是它的文档非常详尽,从原理、使用方法到技巧面面俱到,非常适合新人学习。
这次讲解我们也选用 Azure DevOps 作为演示工具,它的 Pipelines 模块可以用来实现 CI/CD,通过它定义流程的过程被称为搭建流水线(Pipeline)。
接下来我就带你搭建一个简单又完整的CI/CD 流水线,实现自动编译、测试和部署。
在 Pipelines 中可在 Pipelines 页面(同名二级菜单)以 YAML 脚本的方式搭建 CI 流水线,我分解下 YAML 文件的组成。
第一步,要指定 CI 流水线运行的条件,最基本的是代码仓库有代码提交就运行。
# master 分支有代码提交时运行
trigger:
- master
# master 和 Relase1.0 Release... 分支有代码提交时触发
trigger:
branches:
include:
- master
- Release*
我们也可以通过 CRON 表达式配置流水线的定时运行。我们公司多数 CI 流水线配置为代码提交开展自动编译,每晚十点执行代码静态扫描。
# 定时触发,通过 CRON 表达式设置运行时间(UTC 时间)
# always: false 表示 Release... 分支代码有更新才会按时触发 Pipeline
schedules:
- cron: "0 14 * * *"
displayName: build at UTC+8 22:00
branches:
include:
- Release*
always: false
第二步要指定编译环境,例如 iOS 应用需要 MacOS 环境才能完成编译。
# Pipeline 运行环境,最常用的为 windows-latest, ubuntu-latest, macos-latest
pool:
vmImage: 'ubuntu-latest'
可选步骤:设置全局变量,便于对脚本中的一些字段统一管理。
# 全局变量,以该变量为例
variables:
environment: 'Release' # YAML 文件下文通过 $(environment) 引用
第三步,就是在 steps 中写入执行步骤,常用的步骤在 Pipelines 都已经内置为任务(task)了,通过点击即可添加,修改参数即可生效。
如下脚本展示了一个前端工程安装 Node.js、安装项目依赖和编译的过程,流水线运行时会依次执行这些步骤。
steps:
# 安装 NPM 并编译应用
- task: NodeTool@0 # 编译服务器默认已有最新版 Node
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- script: |
npm install
npm run build
displayName: 'npm install and build'
# 发布部署文件(用于部署)
- task: CopyFiles@2
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
contents: '**/dist/**/*'
targetFolder: '$(build.artifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/dist'
ArtifactName: 'Vue-dem
我们可以看到,搭建一个自动编译的流水线是非常容易的,只不过是把我们手动编译的步骤记录在 YAML 文件中。
如果只是在流水线中添加测试任务的话,是非常简单的,你只需要在刚刚的 script 任务中添加运行单元测试的指令,例如npm run test指令。这其中的关键在于,如何方便地看到测试结果和影响编译结果。
.NET 和 Java 等主流框架都有专用的内置任务用于发布测试报告,通用的报告发布任务支持 JUnit、 NUnit、VSTest、 xUnit 和 CTest 的测试结果。但是,这些框架中并没有前端项目可用的单元测试框架,怎么办?
假设选用 Vue 官方支持较好的 Jest 库来编写单元测试,为了让它的测试报告能被发布任务“看懂”,可以在Jest 的配置中指定以 JUnit 格式输出单元测试报告(需要安装 jest-junit 库)。类似的,可以指定代码覆盖率检测以 Cobertura 格式输出。
module.exports = {
reporters: [
"jest-junit"
],
collectCoverage: true,
collectCoverageFrom: [
"**/*.{js,vue}",
"!**/node_modules/**"
],
coverageReporters: [
"cobertura"
]
}
在流水线中修改和添加如下任务,即可发布检测报告并根据测试结果影响编译结果。
# 编译前运行 npm run test:unit
- script: |
npm install
npm run test:unit # 新增
npm run build
displayName: 'npm install and build'
# 添加到编译和运行测试之后
# 发布覆盖率检测报告
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: |
$(System.DefaultWorkingDirectory)/**/*.xml
reportDirectory: '$(System.DefaultWorkingDirectory)/coverage'
failIfCoverageEmpty: false # 找不到覆盖率报告会导致 pipeline 运行失败
# 发布单元测试报告
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: |
$(System.DefaultWorkingDirectory)/junit.xml
mergeTestResults: true
failTaskOnFailedTests: true # 有单元测试未通过会导致 pipeline 运行失
这样,流水线运行后,我们就可以在运行结果页面查看测试结果,点击还可查看报告详情。
到这里,我们已经搭建好了 CI 流水线,只需补上自动部署就能实现 CD。在 Pipelines 中自动部署是在 Releases 页面配置的。
还记得上文脚本中的 PublishBuildArtifacts 任务吗?自动部署中可获取到该任务发布的程序文件,只需添加一个 Deploy Azure App Service 的任务,就能轻松实现将程序发布到 Azure 云的应用服务。
自动部署模板中仅对微软云有较好的支持。对于其他公有云上的资源,可以在新建 Stage 时选择 Empty Job,然后在编辑界面添加 FTP upload 任务,通过 FTP(S) 的方式部署应用文件,例如 Java 项目可以部署 war 包到 TOMCAT 服务器的 webapps 目录下。
以上就是这节课的全部内容了,我们讲解了DevOps的 概念和收益, 以自动化为核心DevOps的是一种方法论,把持续集成CI、持续交付CD贯穿于开发的整个生命周期。作为一个面向开发、测试和运维团队的解决方案,CI/CD流水线主要针对在集成新代码时所引发的问题,具有能提高效率、减少沟通成本和流程瓶颈的优点。
最后我们通过一个 Vue 项目展示了如何搭建一个CI/CD流水线。可以看到,整个搭建流程是比较简单的,但是后续带来的收益却是很显著的,因为开发者只需要提交代码,后面的流程就都自动走完了,能帮助我们节约大量时间。
当然,我的分享也仅作为抛砖引玉。各个 DevOps 工具都有较高的灵活性,可以根据业务需要和应用架构搭建不同的CI/CD流水线。在Azure DevOps的持续交付流水线中,很多环节都可以用更强大的第三方工具替换或补充,实现更强大的功能,而这就需要你多多学习和实践来体会了。
我是杨晨,希望我的分享可以帮助到你,也欢迎你在评论区留下你的思考,和我一起讨论。