开源软件打造企业级 DevOps 工作流(三):持续集成(企业级开源项目)

网友投稿 990 2022-05-30

前言

本文为《用开源软件打造企业级 DevOps 工作流》系列的第三篇文章。接着上一篇版本控制系统篇,本篇文章主要讲介绍 DevOps 工作流中另一个核心模块 持续集成(CI),这可以说是 DevOps 中的重中之重,因为这涉及到自动化管理项目的部署过程。有了持续集成,我们就可以从手动部署中解脱出来,把时间用在更重要的事情上,例如代码重构、回归测试、架构设计等等。

在本篇文章中,我们将介绍持续集成的基本概念,为什么用持续集成,以及如何利用开源软件 Jenkins 来实现持续集成。

持续集成简介

本系列文章的第一篇概述中我们提到,持续集成可以类比于工厂中的流水线操作。例如生产一辆汽车,一切从裸车架开始,车架用吊钩送上传送带,经过装配、打磨、测试等一系列复杂而紧凑的统一化流程,最终产出一辆功能齐全、质量卓越的完整汽车。

持续集成类似软件开发中的流水线,只是持续集成中的流水线通常来说是自动化的,也就是说不需要任何人为干预,一个软件程序就可以从源码开始,经过一系列的构建步骤,最终形成成熟的产品。什么时候启动这个流水线呢?一般来说,是代码变更的时候。其实,这里所说的流水线还包括了部署的过程,一般说持续集成通常会提到 持续部署(CD)。严格意义上来说这是两个概念:持续集成(CI)是指不断将代码不断同步到主干,持续部署是指代码经过评审后自动部署到生产环境。为了方便起见,我们将这两个概念合二为一,统称为 CI/CD 。

例如上图这个持续集成流水线,当持续集成工具检测到源代码有变更的时候,会启动这个流水线:

首先获取源代码;

并行构建前后端应用;

构建 Docker 镜像;

单元测试;

完成部署。

经历了这几个步骤之后,一次集成过程就算完成了。整个流程不需要人为干预,唯一需要开发者做的,就是提交一次代码更新代码仓库,持续集成工具会自动将后面的事情(包括部署)一步步帮你做完,全程自动化。

为什么用 CI/CD

其实我们可以不用 CI/CD 来完成从编码到部署的过程。那么,为什么我们要用 CI/CD 呢?首先我们看看下面一个流程图。

这是一个从码代码到最终部署交付的流程例子:我们花数小时码代码(Coding),不到 1 分钟提交代码(Commit),然后构建(Build)这个应用花 1 分钟到 1 小时(根据应用复杂程度),接着花数分钟部署(Deploy)这个应用,最后测试(Test)。除开代码和提交的时间,后面的构建+部署时间最少也得花几分钟,而测试可能会花更久。

我们要知道的是,构建和部署一般来说是重复性的工作,例如运行一次 npm run build:prod 打包前端代码,或者将打包好后的前端静态文件拷贝到目标地址。如果是人来操作这些流程,非常浪费时间和精力。虽然构建部署一次可能花不了多少时间,但考虑到企业中通常是多人协同工作,每个人都会提交代码,而且很可能是多次提交,这样需要执行的次数就是远不止一次或几次了。你简单做一做乘法,就知道会有多少人工时间成本会花费在上面,而人工成本目前来说是越来越贵的。因此,使用持续集成将降低时间成本(Time Expense)。

上面这个流程图中红色部分(编码和提交)是无法自动化的,需要人工操作;而绿色部分(构建和部署)是可以自动化的,也是需要尽可能全部自动化的;黄色部分(测试)是半人工半自动化的,因为我们可以通过 单元测试(Unit Test) 来自动化很多测试工作,但一些复杂的测试用例(例如页面的排版是否符合设计预期)则需要人工来完成,因此测试部分是半自动化的。这里多提一下单元测试,固然单元测试是非常有助于提升代码的工程质量,但是编写单元测试却相当耗费时间,差不多跟写功能的时间差不多,因此会将整个项目时间加倍,所以需要在时间与质量之间权衡是否需要采用单元测试。

开源工具 Jenkins

要实现 CI/CD,我们需要一些工具。我们推荐的工具是 Jenkins,这也是企业环境中用的比较多的持续集成开源软件。下面我们将详细介绍一下 Jenkins,包括基本介绍、安装、基本使用以及如何实践应用到 DevOps 工作流中。

可能你对 Jenkins 本身并不陌生,这是因为 Jenkins 从 2011 年开始就已经存在,是最早的也是最常用的选择。它出自 Sun 公司的一个工程师的业余项目,不断改进优化后逐渐壮大成为最热门的持续集成工具(听起来是不是跟 JavaScript 的经历差不多?)。

关于 Jenkins 的介绍,我们主要引用其官网上的描述。以下是官方的关于 Jenkins 的一句话描述:

Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。

其中,CI 指代持续集成,CD 指代持续交付。

以下是其主要特点:

持续集成和持续交付: 作为一个可扩展的自动化服务器,Jenkins 可以用作简单的 CI 服务器,或者变成任何项目的持续交付中心;

简易安装: Jenkins 是一个基于 Java 的独立程序,可以立即运行,包含 Windows、Mac OS X 和其他类 Unix 操作系统;

配置简单: Jenkins 可以通过其网页界面轻松设置和配置,其中包括即时错误检查和内置帮助;

插件: 通过更新中心中的 1000 多个插件,Jenkins 集成了持续集成和持续交付工具链中几乎所有的工具;

扩展: Jenkins 可以通过其插件架构进行扩展,从而为 Jenkins 可以做的事提供几乎无限的可能性;

分布式: Jenkins 可以轻松地在多台机器上分配工作,帮助更快速地跨多个平台推动构建、测试和部署。

从介绍总结来看,Jenkins 的核心功能是持续集成和持续交付,另外还有便捷性(安装简单)和扩展性(插件、分布式)。

跟之前的文章里安装 GitLab 一样,我们同样是用 Docker 来安装 Jenkins。在确保您已安装 Docker 、并且能顺利运行 docker ps 的前提下,执行以下命令。

docker run

-u root \  # 以root用户运行

--restart always \  # 永远设置为重启状态,开机时也会启动

-d \  # daemon方式后台运行

-p 8080:8080 -p 50000:50000 \  # 将web端口映射出来,8080为web界面端口

--name jenkins \  # 容器名称

-v jenkins-data:/var/jenkins_home \  # 持久化数据

-v /var/run/docker.sock:/var/run/docker.sock \  # Docker守护进程默认监听的Unix域套接字

-e JAVA_OPTS=-Duser.timezone=Asia/Shanghai \  # 调整时区为中国时区

jenkinsci/blueocean  # Jenkins镜像

以上命令已经有注释了,读者可以根据需要更改其中的一些配置,例如映射端口,8080 可以是 9090、80 等等。执行上述命令后,Jenkins 需要一定初始化时间,等待片刻后在浏览器中输入 http://<宿主机ip>:8080,就可以看到 Jenkins 的初始界面(如下图),这是 Jenkins 在加载必要数据和第三方库,大概需要几分钟。

初始化完毕后,浏览器会重新加载,我们会看到如下配置界面。

这个是告知您,需要输入初始密码,而这个密码在 Jenkins 容器里的 /var/jenkins_home/secrets/initialAdminPassword 文件里。输入以下命令来查看初始密码。

docker exec -it jenkins bash  # 进入容器命令行

cat /var/jenkins_home/secrets/initialAdminPassword  # 查看初始密码

将查看到的初始密码输入到上述界面中,点击 Continue 进入下一步。加载片刻后,您将看到如下选择界面。

选择默认的 Install suggested plugins 安装建议的插件。然后 Jenkins 会安装一些常用的插件,例如连接 Git 的 Git plugin 、邮件插件、管道插件等等。安装进度如下图。请耐心等待,这个过程可能花很长的时间!

安装完毕后,输入第一个管理员账户,点击 Save and Continue 进入到下一步,然后点击 Save and Finish,最后选择 Restart,完成重启。

重启完毕后,您就可以注册登陆了,请选择刚才的管理员账户登陆。

你可能最开始使用 Jenkins 的时候会发现它朴素的用户界面一点也不酷炫,总体显得比较老旧,不像是现代软件的风格,不过我们有 Open Blue Ocean 加强版界面,非常扁平化和现代化,不习惯 Jenkins 默认界面的可以切换过去。下图是进入 Jenkins 的主页界面,可以看到左侧有一些操作选项以及构建队列和执行器状态,右侧是自动化项目的列表。

下图是 Open Blue Ocean 的主页界面,功能上跟默认界面差不多,只是排版和风格有所不同。

其实,界面这些都不是特别重要的问题,很快你会被它朴实但强大的核心功能(持续集成)所折服。在使用这些强大的功能之前,我们需要做一些配置。

这里简单介绍一下 Jenkins 的原理,Jenkins 构建项目是通过 Jenkins Executor 这个 jar 包来实现构建和部署的。Jenkins 服务的本地机器叫做 主机(master) ,如果告诉主机其他机器的 IP 地址和登陆信息,Jenkins 就可以通过 SSH 的方式在该机器上将 Jenkins Executor 拷贝过去并运行,再而与其交互通信,通过 Jenkins Executor 完成远程构建工作。

下面我们介绍如何配置节点。

在主页中点击 Manage Jenkins (确保您有管理员权限),进入管理页面;

然后点击 Manage Nodes ,进入到管理节点页面;

这里您应该能看到 master 节点,这时候你需要添加节点,点击左侧的 New Node;

输入节点名称(Node Name),点击 OK,将看到很多配置信息;

完成配置(配置信息如下图),点击 Save 保存设置。

然后,您应该就可以看到下图节点列表了,左侧 S 列代表的是节点状态(Status),如果节点在线,会显示为计算机的符号,如果离线,则会显示一个计算机加红叉的符号。你可以点击去看它的日志(Log),如果一直连不上,需要查看日志排查错误。

节点配置好了,您就可以在这些节点上运行构建程序了。如果您有多个机器需要部署,只要一次性手动将这些信息注册进 Jenkins,就可以一劳永逸的在各台机器自动化部署应用程序了。是不是很酷?

现在,我们介绍在 Jenkins 中如何创建一个自动化项目。其实过程很简单,只是配置方面稍微复杂一些。

在主页点击 New Item 创建新项目;

输入项目名称,然后选择项目类别,强烈建议选择 Multibranch Pipeline (多分支管道),因为这一个类别是最方便配置和最容易集成之前介绍的 GitLab 版本控制系统的类别,然后点击 OK;

配置各种输入,包括展示名称、项目来源(来自VCS,例如Git/SVN)、构建周期(选择每分钟)等等。

点击 Save 保存项目,就创建好了一个项目。

读者可能会问:等等,构建过程跑哪儿去了?别着急,我们接下来会将如何配置构建过程,也就是用一个配置文件来定义构建过程,而这个配置文件叫 Jenkinsfile。

读者可能会问,Jenkinsfile 是不是与 Dockerfile 有异曲同工之妙?没错!这两种配置文件都属于 Infrastructure as Code(架构即代码) ,仅仅用代码就可以配置出计算机和网络架构,非常易于管理和扩展。下面我们会详细介绍 Jenkinsfile。

Jenkinsfile 是 Jenkins 2 发布的一个实用功能,这个功能让用代码管理构建过程变成可能。它使用 Groovy 语法,很容易配置不同的构建阶段。下面是一个 Jenkinsfile 的例子。

pipeline {

agent {

node {

label 'docker'  // 要执行的节点名称

}

}

stages {

// 配置阶段

stage('Configure') {

steps {

echo 'Configuring'

script {

// 根据 Git 分值名称选择不同的 docker-compose 文件

switch (env.GIT_BRANCH) {

case 'develop':

// 开发分支的 docker-compose 文件

env.DOCKER_COMPOSE_FILENAME = 'docker-compose-dev.yaml'

break

case 'master':

// 主干的 docker-compose 文件

env.DOCKER_COMPOSE_FILENAME = 'docker-compose-prod.yaml'

break

default:

echo "Unknown branch ${env.GIT_BRANCH}"

exit 1

}

}

}

}

// 构建阶段

stage('Build') {

steps {

echo 'Building'

用开源软件打造企业级 DevOps 工作流(三):持续集成(企业级开源项目)

// 用 Docker 不同分支的构建镜像(用 GIT_BRANCH 环境变量区分)

sh """

docker build -t awesome-image:${ENV:GIT_BRANCH} -f Dockerfile-local .

"""

}

}

// 测试阶段

stage('Test') {

steps {

echo 'Testing'

}

}

// 部署阶段

stage('Deploy') {

steps {

// 用 docker-compose 重启镜像服务

sh """

docker-compose -f ${ENV:DOCKER_COMPOSE_FILENAME} down | true

docker-compose -f ${ENV:DOCKER_COMPOSE_FILENAME} up -d

"""

}

}

// 清理阶段

stage ('Clean-up')

{

steps

{

// 清理不用的 Docker 镜像

sh '''

docker rmi $(docker images -f "dangling=true" -q) || true

'''

}

}

}

}

这里,我们用了 Docker 来完成构建工作,Docker Compose 来完成部署工作。后面的文章会详细介绍 Docker 在 DevOps 中的应用。

关于 Jenkinsfile 的内容以及 API 还很多,本文不会全部涵盖。需要的朋友可以参考官方文档 https://jenkins.io/zh/doc/book/pipeline/jenkinsfile/。

配置好了 Jenkinsfile,将它放在 Git 项目根目录下,当每次有代码提交的时候,Jenkins 就会拉最新代码,然后开始构建过程,如下图。

用 Pipeline 构建的好处在于可以直观的看到构建的过程,包括各阶段花了多少时间等信息。下图是某个项目构建过程的概览。可以看到,每一次构建都是由 VCS 代码提交触发的。这样的话,只要我们在某个分支上提交了代码,Jenkins 就可以自动帮我们构建、部署了。如果构建过程中有报错,Jenkins 中会有提示信息。

Jenkins 与其他 CI/CD 工具

Jenkins 是一个强大的工具,不过市面上还有其他很多优秀的 CI/CD 工具。如下图,我们可以看到整个 CI/CD 市场的市场份额。

为什么 Jenkins 这么出名,是因为它是最早的开源 CI/CD 工具,存在市场比较久而已,读者有权利选择任何合适的工具。

下图是各个 CI/CD 工具的市场竞争矩阵图。

总结

本文介绍了持续集成的基本概念,以及使用 CI/CD 的原因,此外还详细介绍了开源 CI/CD 工具 Jenkins,包括 Jenkins 的简单介绍、如何安装、如何配置、创建项目以及如何使用 Jenkinsfile 和查看构建进度。相信仔细阅读了本篇文章的读者,应该会基本了解持续集成的概念和框架,以及在企业中推广使用持续集成的重要性。此外我们还了解了 CI/CD 工具的市场情况,并知道 Jenkins 并不是唯一的选择,市面上还可以选择很多其他优秀的工具,例如后起之秀 Circle CI。我们选合适的 CI/CD 工具是为了满足企业的 DevOps 需求,而不应该局限于工具的名声和自己所掌握的知识,只要做好了前期调研和需求分析,我相信是可以实践好 DevOps 中的持续集成功能的。最后提一点,就是工具并不是全部,如果没有良好定义的流程与技能储备,DevOps 是实践不通的,应用再优秀的 CI/CD 工具也会失去意义。因此,我们需要经常充实自己,加强 DevOps 的知识了解,扩充自己的能力范围,这样才能打造出最佳的 DevOps 工作流。

我们之前介绍了 DevOps 概述、VCS,现在又介绍 CI/CD,接下来我们会讲容器化,会详细介绍 Docker,敬请期待后续文章。

DevOps Jenkins

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:vi常用操作(vi常用操作命令)
下一篇:azkaban零基础学习(azkaban 教程)
相关文章