脚本宝典收集整理的这篇文章主要介绍了容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
暑期实习期间,所在的技术中台—效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化、标准化; 实习期间对
DevOps
的理解一直懵懵懂懂,最近观看了阿里专家带你玩转容器云原生DevOps 公开课开始系统的学习DevOps
,所以根据学习视频整理出以下学习笔记希望分享给更多对此感兴趣的同学~ 课程大纲如下图所示,会陆续进行更新:
本节课程会教大家从零搭建一个 CI/CD 系统,并通过一个最佳实践的演示来学习如何使用 CI/CD 系统。
首先我们先了解一下 CICD 的概念:
持续集成称为CI
、持续交付和持续部署可以统称为 CD
。
持续集成 其实是一种软件项目管理的方法,依据资产库(比如说源码或者类库等)的变更,能够的自动的去完成代码的编译、测试部署以及其中的一些问题的反馈。通俗来讲就是程序员在向版本库中提交代码以后,持续集成服务器能够自动的发现或者是定时发现这个变更,然后依据这些源码的变更对代码重新进行构建、测试、部署这整个过程。
持续集成的思想是要求我们能够做到以下几点:一是说自动构建无需人员参与,这个能节省大量人力成本;二是说能够自动检测源码版本库的变更,这个可以通过轮询、定时策略、使用触发器或者是程序员自己使用命令来触发构建等等方式来实现;三就是说反馈机制,构建是不同的步骤的,其中每个步骤出现了问题以后都应该能自动的快速的反馈给正确的人,这个正确的人就是说代码的提交者或者是这个产品的测试人员或者是审查人员等等。现在就是说在每一次构建的时候,都应该把之前的环境清理干净,保证本次构建是一个纯净的构建环境。避免脏数据对这个构建或者测试产生影响。
持续交付 是说能够自动化的、频繁的将软件的新版本能够交付给质量团队测试团队或者是用户,目的就是在保证在上生产环境之前可以尽早的发现存在的问题。
持续部署 是在持续交付的下一步进行,指的是代码通过评审以后能够自动化的部署到生产环境当中
这三个概念里边其实都有一个持续这个词,意思就是说我们从代码提交到部署到生产环境,其中的每一个环节出现问题的时候都能够快速的把问题反馈给相关人员进行修复,避免了最后到生产环境以后,你才能发现这个问题,然后回头再去解决这个问题的代价是非常大的。这个就是CICD的核心思想。
程序员必读:七款出色的GitHub功能集成工具 - 51CTO.COM
目前在市场上有多款可用于搭建 CI/CD 系统的工具,其中 Jenkins 是非常流行的一款开源的持续集成、持续交付的平台。它拥有丰富的插件文档以及良好的社区。在国内大多数公司的话,在私有的持续集成持续交付方案的话,都会选择它来做服务器。开发者可以用它快速的搭建符合自己业务场景的流水线流程,结合大量的开源插件,您可以轻松的满足不同语言、不同平台、包括不同框架的持续基层场景。无论是现在使用越来越多的 GitLab CI 或者是在开源领域广受好评的 Travis CI 的话都是无法替代 Jenkins 在持续集成领域的地位的。
我们选择使用 Jenkins ,还有以下几个理由:第一是说 Jenkins 是在所有的3A产品中安装和配置上最简单的;第二是它是基于web访问,用户的界面是非常友好、直观和灵活的,在很多种情况下的话,他还提供了 Ajax 的及时反馈。第三它是基于 Java 开发的,但是它的构建的话是不限于这个 Java 应用;第四是它拥有大量的插件,极大的扩展了Jenkins 功能,这些插件都是开源的,而且可以直接通过 web 界面来进行安装和管理。在搭建 Jenkins CI/CD系统之前,我们有必要先了解一下 Jenkins 的系统架构:
Jenkins 系统架构它是一个master
、slave
的系统架构。我们说的 Jenkins master 就是 Jenkins 服务器,Jenkins slave 的话其实就是我们说的构建节点,两者相当于是 server 和 agent 的一个概念。
master 它主要是用来提供 web 接口,让用户来管理 job 和 slave。 job 就是我们说的构建的项目,它是可以运行在 master 本机上,或者是被分配到这个 slave 节点上进行运行的。一个 master 节点通常可以关联多个 slave 用来做为不同的 job 或者是相同的 job 的不同配置来服务的。虽然 master 也能用来做构建,但是我们在最佳实践中不建议这么做,我们应该把不同语言类型的应用的构建分类,根据类别的不同运行在对应的 slave 构建环境下边,这样便于管理且能避免不必要的错误的产生。
当 job 被分配到slave 上进行运行的时候,此时 master 和 slave 其实是建立的一个双向字节流的链接,其中 master 与 slave 节点之间的连接方式主要有两种:
接下来我们会使用 Jenkins 搭建 CI/CD系统,首先我们来看看我们要实践的一个构建流程:
上图其实就是一个应用从源码提交到部署到生产环境中所需要运行的一些步骤:首先开发者需要推送代码到源码仓库。这个源码仓库可以是 GitHub、Git Bucket、GitLab 等源码仓库,这些都是通过不同的插件来安装来集成到 Jenkins 系统中进行支持的,一般我们会在源码仓库端配置一个 webhook,源码仓库监听到这个推送的动作以后意味着应用的代码有更新,就需要重新构建编译和部署验证。这个 webhook 就是用来通知 Jenkins server 自动触发构建作业的。Jenkins server 也就是 CI server 在接收到通知以后就要运行构建项目。它在运行构建项目之前会先从我们全局配置的一个 k8s 集群中动态的分配一个构建节点,所有的项目构建都会运行在这个构建节点上面。比如说 maven 打包命令、测试命令等等的。然后在本节的课程当中构建物,也就是说应用的 jar/war 包会被打包进 Docker 容器镜像里边,并推送到的镜像仓库。我们这边使用的是阿里云镜像仓库,然后部署应用的时候,再从镜像仓库中拉取对应的 image,最终把应用部署到 k8s 集群当中。构建过程当中有任何失败了的步骤的话,都应该及时的通知到相关的人员,使用邮件或者是使用钉钉通知的话都可以。然后整个构建完成了以后,我们从 k8s 是集群当中分配出来的构建节点是可以释放掉的,这样就是一方面是说我们每次构建的时候都是一个新的构建环境。另一方面就是说可以这样动态分配动态销毁来构建资源的话,可以节省很多的计算资源。
环境准备:CentOS7 腾讯云服务器、阿里云容器服务、阿里云容器镜像服务、Gitee
[root@zsr02 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
搭建 Jenkins 系统,就是要先安装一个 Jenkins 的 master,我们这边选择容器化搭建 Jenkins 系统的方式。首先我们会在一个 CentOS7.4 的机器上去安装 Docker 服务,然后使用 Docker 去启动 Jenkins master,master 启动起来以后我们就可以登录到他的 web 界面上边去,从界面上去给他安装插件,然后配置构建节点,并且运行第一个构建项目
# 1.移除以前docker相关包
sudo yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
# 2. 配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager
--add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 3. 安装docker
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 4. 启动docker
systemctl enable docker --now
# 5. 配置阿里云加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
以上操作完成后,我们可以使用 systemctl status docker
来查看 Docker 服务是否启动
我们通过 docker run 运行一个容器,-u root
表示以 root 身份来启动这个容器,-itd
表示以交互模式后台运行这个容器,-p
8080:8080 表示把容器内部的8080端口(Jenkins master会占用该端口)映射到这个主机上的8080端口,50000端口的话也是如此,是用于JNLP连接的。然后我们用的这个 Jenkins 的镜像的话,其 Jenkins master 相关的一些配置都会放到 var/jenkins_home
目录下边,我们把它映射到宿主机上面。另外我们在 Jenkins 上面可能会用到 docker 的命令,所以我们把宿主机上的 docker.sock 挂载到容器里;然后我们可以给这个容器加个名字 jenkins-master,最后一行是 jenkinssci/blueocean,这个是是 Jenkins master 镜像的 blueocean 的版本,我们会从 DockerHub 的公共镜像仓库里面去拉取这个镜像,然后把它启动成一个服务。
docker run -u root -itd -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock --name jenkins-master jenkinsci/blueocean
下载启动之后,我们可以用以下命令查看已经启动的容器,也可以查看8080是否已经被宿主机坚监听:
[root@zsr02 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34326090ece5 jenkinsci/blueocean "/sbin/tini -- /usr/…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp jenkins-master
[root@zsr02 ~]# netstat -anp|grep 8080
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 2692/docker-proxy
tcp6 0 0 :::8080 :::* LISTEN 2696/docker-proxy
然后我们可以通过浏览器进行访问,通过宿主机公网ip:8080进行访问,如下图所示则代表成功~
Jenkins 第一次安装的时候会给你初始化一个密码,然后我们根据提示查看密码复制即可登陆[root@zsr02 ~]# cat /var/jenkins_home/secrets/initialAdminPassword
b83af83a04c64ad696c4e8f681286a93
到此 Jenkins Master 容器安装完成,接下来我们进行插件的啊装
登陆成功后,可以看到 Jenkins 给我们提供了两个选项:一个就是安装推荐的插件,一个是选择插件的安装。我们新手刚搭建起来的话,可以直接点击安装推荐的插件。后续的话,我们可以在 Jenkins 的插件管理界面上边自定义的添加自己想要的插件。
此时报错了,安装过程中出现一个错误: No such plugin: cloudbees-folder
这是因为缺少cloudbees-folder
插件,我们下载即可:cloudbees-folder下载地址 下载后得到 cloudbees-folder.hpi
文件,接下来我们只需将它拷贝到 Jenkins 的插件目录中即可,插件目录的位置在我们启动 Jenkins 容器时所挂载的宿主机目录/war/WEB-INF/detached-plugins中: 这里为:/var/jenkins_home/war/WEB-INF/detached-plugins
我们可以使用 scp
命令进行拷贝,注意这里的用户名、ip地址、拷贝路径要换成自己服务器的相应信息!
scp cloudbees-folder.hpi root@152.136.245.137:/var/jenkins_home/war/WEB-INF/detached-plugins
然后可以在 Jenkins 插件目录中看到 cloudbees-folder.hpi
然后我们重启容器
[root@zsr02 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34326090ece5 jenkinsci/blueocean "/sbin/tini -- /usr/…" About an hour ago Up 5 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp jenkins-master
[root@zsr02 ~]# docker restart 34326090ece5
34326090ece5
然后再次访问 公网ip:8080 ,此时可能会出现如下界面,我们稍等一下就好,它会自动刷新
然后再次会进入到登陆界面,我们按照上述输入密码再次登陆选择安装推荐的插件即可成功推荐插件安装完成之后,会进入到如下图所示界面,我们来创建一个管理员用户
接下来的url设置我们采用默认的到此安装完成
然后进入到后台管理界面
在 Jenkins 的主页面上面,我们可以看到左边有新建任务、用户列表、构建历史、系统管理等等一些串单。我们可以先点击新建任务,这边需要输入一个任务的名称,这个任务的话就是我们刚刚所通常说的项目或者是作业。下边可以选择自由风格软件项目流水线等等,我们这边是先配置一个最简单的自由风格的软件项目 点击确定可以进入到作业的配置页面。我们可以看到它是分六个部分的:General、源码管理、构建触发器、构建、构建环境、构建后操作。我们可以以 master 作为构建节点来运行一个最简单的任务,比如这里打印一行字符串 保存以后,点击立即构建,然后可以看到构建历史这边会出现一个完成了的构建号。 我们点进去该构建号,然后在控制台输出面板可以看到我们刚刚执行的命令信息:它是由哪个用户运行的,以及他的工作空间,以及他最终的完成的状态。 我们刚刚其实讲到就是说在 Jenkins CI 这个系统里不希望 master 作为构建节点,所以我们需要在系统设置里边关于系统的主目录以及执行者数量作出修改,原先是2,我们把它设置成零进行保存。 这样设置的话,Jenkins master 就不允许作业运行在它上边,我们需要另外给它配置 slave 节点去执行相应的 job。我们也是以容器的方式来启动构建节点,首先拉取镜像并启动容器
# 拉取镜像
docker pull registry.cn-beijing.aliyuncs.com/codepipeline/jenkins-slave-java:latest
# 启动镜像(将容器里的22端口,也就是SSH的端口映射到宿主机的30001上)
docker run -itd -p 30001:22 -v /var/run/docker.sock:/var/run/docker.sock registry.cn-beijing.aliyuncs.com/codepipeline/jenkins-slave-java:latest
为了接下来的ssh远程连接到该容器,我们首先要进入该容器设置一些用户名和密码,默认的登陆用户名是root,我们进入到容器中设置登陆密码,记住该密码
[root@zsr02 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5e280aa72ea7 registry.cn-beijing.aliyuncs.com/codepipeline/jenkins-slave-java:latest "/usr/sbin/sshd -D" 2 seconds ago Up 2 seconds 0.0.0.0:30001->22/tcp, :::30001->22/tcp gracious_keller
34326090ece5 jenkinsci/blueocean "/sbin/tini -- /usr/…" 4 days ago Up 4 days 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp jenkins-master
[root@zsr02 ~]# docker exec -it 5e280aa72ea7 /bin/bash
root@5e280aa72ea7:/# sudo passwd root
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
然后我们依次点击 Manage-Jenkins --> Manage Nodes and Clouds,这里我们可以看到只有 master 这一个节点,由于刚才它已经被我们设置了可执行数量为0,因此它现在是没法去构建 job。
因此我们需要新建一个节点,起名字叫做slave-java
,勾选固定节点,然后点击ok
然后进入到详细设置页面,首先来设置并发构建数,我们可以改成5;然后设置 Job 在该构建节点上的工作空间,这里为 /home/jenkins;然后设置标签,标签用于在 Job 的配置中选择,可以映射到具体的构建节点,用法一般选择只允许运行绑定到这台机器上的 Job;
启动方式的话,我们可以选择 SSH 远程连接方式,其中的主机就是宿主机的公网ip地址,登陆凭证的话我们需要创建一个 SSH 登陆的用户名和密码,也就是我们前面设置的容器用户名密码,用户名为root,密码为你自己前面设置的然后这里的 Credentials 选择以上创建的凭证;host key 选择不采用验证策略
然后我们点开这里的高级,修改端口号设置为30001
,因为我们容器启动的时候将容器内的22映射到了宿主机的30001 以上设置都设置完成后,点击保存即可看到新创建的节点 此时该节点显示❌,代表与 Jekins master 连接是有问题的,这里是因为它在初始化,我们等待一会即可看到 slave-java 节点已经正常的连接,而且它是有五个 executor 的执行者,也就是说有五个 job 可以在这个节点上面并行构建。 现在我们就可以回到刚才我们的新建的任务里边修改它的配置,让其来在我们刚刚创建的 slave-java 节点上进行运行。 在 General 区域的我们可以限制项目的运行节点,这里要填一个标签,就是前面我们配置 slave-java 节点设置的标签。 设置完保存,然后点击立即构建,可以看到构建成功 然后我们查看其控制台输出,可以看到它成功运行在 slave-java 机器上
在对 Jenkins 系统的使用有了一个基本的了解以后,我们就可以配置一个更复杂的作业,来自动化一个应用从源代码的提交到整个应用部署这一整个过程,正如我们下图中所示的一样,我们需要配置去拉取源码,对源码进行构建。构建出来的 war 包打包成 docker 镜像,并推送到镜像仓库,最终把这个应用镜像部署到容器集群的这样一个过程。
我们回到 Jenkins 的主页面,现在新建一个任务,名字叫做 java-demo 构建,选择一个自由风格的软件项目。
首先我们需要配置这个 job 可以运行在 slave-java 构建节点上面。 然后我们需要配置一个源码管理。这里有一个我自己的项目代码,地址为:https://gitee.com/zhong_siru/staff-manage-system.git,它是一个公共仓库,可以直接克隆下来,而不需要配置用户名密码。如果是私有仓库的话,这边需要添加一个包含用户名和密码的证书。然后源码的分支的话,这里是main。 再往下在构建这部分的话,我们添加一个执行 shell,将 maven 打包命令写进去。mvn package -B -DskipTests
上述操作设置完成后,保存任务,然后点击立即构建。我们来看控制台输出,首先是 admin 用户,然后运行在 slave-java 节点上边进行源码的拉取源码构建,
然后根据构建命令进行构建。在构建过程中,会先拉取一些依赖的 jar 包,然后执行打包命令,可以看到在 target 目录下生成了 spring-04-system-0.0.1-SNAPSHOT.jar 包,构建成功。
以上我们成功运行构建了一个项目,在该任务配置里边的话,我们在 slave-java 节点上将源码的拉取下来进行构建,构建产物也就是这个 jar 包其实是放置在该构建节点上面的,我们应该要将它打包成一个docker 镜像,然后推送到镜像仓库。
这样我们需要使用到一个插件,这个插件目前是没有安装的,我们需要在 Manage Jenkins 中的 Manage Plugins 中的可选插件中搜索CloudBees Docker Build and Publish
这个插件点击 Download now and install after restar,也就是下载然后重启安装,因为所有插件的安装都得在 Jenkins master 重启后才生效。
前面安装完插件以后,这边就会出现一个docker build and publish 的插件,这个插件就是能帮助我们打包 docker 镜像并且进行推送。接下来我们就是需要填入这个插件所需要的各个参数项。它每个参数项的后边都会有一个问号,就是一些帮助的文档,如果我们有什么不明白的,可以点开这个问号来看一下有哪些信息我们可以参考。
首先就是这个 Repository Name 的话,格式为name space/仓库名称
。仓库的名称的话,我们可以起个名字,比如说 java -demo。Tag 的话就是说这个镜像它的标签我们可以给出 v1。Docker host URI 以及 server credentials 我们可以不用管。
然后我们需要写这个 Docker registered URL,对于阿里云的容器镜像服务来说的话,我们查询一下他的公网地址,复制一下,加上 v2 代表这个API 的版本为2。
然后我们需要添加一个镜像仓库的用户名密码作为证书,账号是阿里云账号,密码就是前面设置的 Registry 的密码 然后保存立即构建,之前我们可以看一下这个控制台的输出,可以发现出错了 命令提示 /home/jenkins/workspace/java-demo/Dockerfile 下没有该文件,意思就是我们缺少一个 Dockerfile,由于该任务是运行在 slave-java 构建节点上的,也就是一个容器,因此我们可以进入该容器中,在指定位置添加一个 DockerfileDockerfile文件内容如下:
FROM java:8
MAINTAINER zsr
ADD target/springboot-04-system-0.0.1-SNAPSHOT.jar /staff-manage-system.jar
CMD ["--server.port=8081"]
EXPOSE 8081
ENTRYPOINT ["java","-jar","/staff-manage-system.jar"]
添加之后,我们在 Jenkins 页面上重新执行 java-demo任务,观察控制台变化,等待一会,就可以看到已经 success,镜像已经推送到我们的阿里云镜像仓库
我们回到阿里云镜像仓库界面,可以看到 java-demo 的镜像推送上来 再看一下它的镜像版本的话,也是 v1 跟 latest 两个版本,因为该插件默认会把 latest 标签也推送上来。这个就完成了docker 镜像的构建和推送这个步骤。接下来我们要做的事情,就是把这个打好的 docker 镜像部署到容器集群里边,这里就部署到 k8s 集群中,我们首先需要安装一个插件
然后在 Jenkins 这端我们要去给 java-demo 这个任务新增一个构建步骤,选则 Deploy to Kubenetes首先需要配置一个证书,选择这个 Kubenetes configuration 这个类型,id 设置为k8s,这边的话我已经提前准备好一个 kubenetes 集群,
然后我们现在先复制一下他的 KubeConfig 的信息添加到 Content 区域,然后点击保存。 这里选择我们刚刚创建的证书,然后 configure files 的话是我们要部署的样本文件,这里为 deployment.yaml,该文件是放在这个gitee源码文件里边的。 deployment.yaml 内容如下:apiVersion: v1
kind: Deployment
metadata:
name: java-demo-001
spec:
replicas: 2
selector:
matchLabels:
app: java-demo-001
template:
metadata:
labels:
app:java-demo-001
spec:
containers;
- name: java-demo-001
image: registry.cn-hangzhou.aliyuncs.com/bareth/java-demo:v1
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: java-demo-001
spec:
ports:
- port:80
targetPort:8080
name: java-demo-001
selector:
app: java-demo-001
type: LoadBalancer
上述配置添加完成以后,我们保存,然后进行构建,可以看一下这个控制台的输出:
可以看到首先是打包镜像,然后是镜像的推送,最后是部署我们刚刚指定的deployment,执行结果为 success。
此时项目镜像已经成功推送到 k8s 的集群中,然后我们在阿里云容器集群里的控制台界面就可以看到推送上来的 java-demo-001 服务以及它的外部访问信息,这样我们通过该外部端点就可以直接访问该项目啦!
到目前为止,我们就已经完成了一个项目从源码的拉取、编译构建、打包成docker镜像、推送镜像到影响仓库、部署到k8s容器集群这一系列流程的自动化,最终实现我们可以从浏览器上边访问到这个服务。
以上只是我们为了讲解搭建的一个最简单CICD系统,对于真正在生产中使用CICD系统远不止如此,还需要很多其他的工作,如下所示:
阿里云公共云服务 CodePipeline 是基于 Jenkins 做的二次开发的 CICD系统,相比 Jenkins 有很多优点:
第一就是它是一个 SaaS 化的持续交付引擎,也就是只要阿里云用户登录上来就能使用的一个免费服务。
第三是它与阿里云产品生态无缝集成。比如说OSS、容器服务、容器的镜像仓库服务等等,此外还支持多种的部署环境,比如说可以部署到ECS,或者部署到我们刚刚演示的容器集群中。
第四是它具有多维度安全策略保障。首先构建节点是用完即焚的,每个人都是一个独立的构建环境,不会跟其他用户混在一起,避免脏数据的污染;然后构建物的上传可以上传到用户自己的私有的OSS仓库,或者是用户私有的容器镜像仓库。最后就是说其提供的专用插件是经过安全加固的。 最后就是它支持多种方式部署,如下图所示:以上是脚本宝典为你收集整理的容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程全部内容,希望文章能够帮你解决容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。