介绍
持续集成持续部署(CI/CD)在日常开发过程中还是生产坏境部署中都会用到的工具,通常这类工具一般都会帮我们解决一些繁琐且容易出错的事务上,并且提高效率,节约成本。
这时软件的自动化能力以及可配置的能力尤为重要,首先软件得稳定,其次适用性得符合大部分人的需求,再来就是需要易操作、易理解、易记忆等等。
接下来将介绍一款自动化集成部署的软件:Jenkins。
Jenkins是一款由Java编写的开源的持续集成工具,它支持软件配置,插件管理,定时备份,Shell脚本等功能。
环境准备
系统:Centos7 64位
内核版本:5.0以上
内存大小:2G以上
初始化
系统初始化指令
# 关闭防火墙 systemctl stop firewalld systemctl disable firewalld # 关闭selinux # 永久关闭selinux(重启后生效) sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config # 临时关闭selinux(不需要重启,立即生效) setenforce 0 # 关闭swap # 永久关闭swap(重启后生效) sed -ri 's/.*swap.*/#&/' /etc/fstab # 临时关闭swap(不需要重启,立即生效) swapoff -a # 将桥接的IPv4流量传递到iptables的链 cat > /etc/sysctl.d/kubernetes.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF # 立即生效 sysctl --system # 时间同步 yum install ntpdate -y ntpdate -u pool.ntp.org # 添加定时 crontab -l */20 * * * * /sbin/ntpdate -u pool.ntp.org > /dev/null 2>&1
升级系统内核
首先,查看系统内核版本
输入下面指令会出现如下列表
awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg #或者 rpm -qa kernel
0 : CentOS Linux (3.10.0-1160.53.1.el7.x86_64) 7 (Core)
1 : CentOS Linux (3.10.0-1160.11.1.el7.x86_64) 7 (Core)
2 : CentOS Linux (3.10.0-1062.el7.x86_64) 7 (Core)
3 : CentOS Linux (0-rescue-ccae925869aa43f9b2868f73a0a778e7) 7 (Core)会看到系统内核版本才3.10
所系这时候需要升级内核
导入内核源
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org # 导入elrepo的签名 rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-5.el7.elrepo.noarch.rpm # 升级elrepo源
导入软件yum源
这里使用的阿里巴巴的软件源
当然你也可以使用其他软件源,比如清华,163等
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo --no-check-certificate yum makecache
查看系统可用版本
会看到两个大版本
kernel-lt 基于长期支持分支
kernel-ml 基于主线稳定分支
yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
这里使用ml主线稳定分支版本即可
执行安装指令
yum --enablerepo=elrepo-kernel install kernel-ml kernel-ml-devel -y
安装内核会等待几分钟
这里需要耐心等待
安装完成后
会看到5.19内核已经安装成功
再次查看内核
awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
设置启动项
这里需要设置最新内核为第一启动项
grub2-set-default 0
重启系统
reboot
查看新内核
uname -a
安装Docker
执行安装docker指令
#安装wget yum install wget -y #下载docker-ce源 wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo #查看可以安装的docker版本 yum list docker-ce --showduplicates | sort -r #安装docker yum install -y docker-ce-20.10.10 docker-ce-cli-20.10.10 containerd.io-1.4.12 #查看docker版本 docker -v #创建docker配置目录 mkdir /etc/docker #配置docker源 cat > /etc/docker/daemon.json << EOF { "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"] } EOF #重载 systemctl daemon-reload #设置开机启动 systemctl enable docker #启动docker服务 systemctl start docker #旧版docker迁移 grep -rl 'docker-runc' /var/lib/docker/containers/ | xargs sed -i 's/docker-runc/runc/g' systemctl stop docker systemctl start docker #查看docker docker -v
查看docker
docker -v
出现版本号说明安装成功
至此系统环境准备完成
安装Jenkins
文档:https://hub.docker.com/_/jenkins
编写Dockerfile
首先,编写一个Jenkins的Dockerfile文件
cat > Dockerfile << EOF FROM jenkins/jenkins:lts USER root #指定容器的源 RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list RUN sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list RUN apt clean #安装集成部署需要用到软件 RUN apt-get update RUN apt-get install -y wget RUN apt-get install -y iputils-ping #RUN apt-get install -y libltdl7 RUN apt-get install -y apt-transport-https #RUN apt-get install -y npm ENTRYPOINT ["/sbin/tini","--","/usr/local/bin/jenkins.sh"] EOF
编写执行脚本
创建一个执行脚本文件Jenkins.sh 来创建Jenkins
此方法可方便后期维护,修改,重启等操作
cat > Jenkins.sh << EOF echo 创建Jenkins数据目录 mkdir jenkins_home echo 停止容器中... docker stop jenkinsserver echo 删除容器中... docker rm jenkinsserver echo 删除镜像中... docker rmi myjenkins echo 构建镜像中... docker build -t myjenkins . echo 创建容器中... docker run --restart=always --name jenkinsserver \ --env JAVA_OPTS="-server -Xms1024m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m" \ -e TZ=Asia/Shanghai \ -p 8888:8080 -p 50000:50000 \ -u 0 \ -v /var/myworkhome/jenkins/home:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker \ -d myjenkins EOF
执行安装
bash Jenkins.sh
当执行后等待几分钟
当看到一串字母就说明成功了
查看Jenkins状态
docker ps
访问Jenkins服务
这时候可以通过对应端口访问Jenkins服务
等待Jenkins初始化完成就可以进行登录
获取初始密码
初始化完成会出现获取初始化密码的界面
获取初始化登录密码
获取后输入到文本框然后继续
docker exec -u 0 jenkinsserver /bin/sh -c "cat /var/jenkins_home/secrets/initialAdminPassword"
等待初始化
接着让你选择默认设置还是自定义设置
这里就选择默认设置即可
接着就会出现安装界面
等待安装完成即可
登录系统
接着设置账号密码
配置访问的url,默认即可
登录成功
测试集成部署
环境和软件都搭建好后就可以开始做集成部署任务
这里使用.NET Core代码进行部署测试
创建任务
点击创建任务
输入一个任务名称
然后选择构建一个自由风格的软件项目
填写代码仓库地址
填写仓库地址
这里先用我自己gitlab做演示
当然你也可以用svn的地址或者github
编写部署脚本
编写构建脚本
echo 构建app中... docker build -t myapp . echo 创建容器中... docker run --restart=always --name myapp \ -e TZ=Asia/Shanghai \ -p 8080:80 \ -d myapp echo 构建并部署完成
执行构建任务
保存任务后手动执行CI/CD任务
此时打开任务控制台查看日志
可以看到任务是先拉取仓库代码
然后执行Docker构建任务
查看部署结果
可以看到Success的标志
说明构建部署任务已经完成
访问部署服务
此时尝试访问构建成功的一个web服务
上面用到是8080端口
可以看到访问web服务的一个接口成功返回了数据
至此CI/CD的基础搞清楚了
后续
后续操作
开发人员提交代码,系统触发CI/CD任务
构建失败,给与响应,如果钉钉,微信公众号提醒等
Q&A
上面提到的是一个基础构建任务,
下面的操作将会总结归纳日常的解决方案
1.流水线测试
声明式和脚本式流水线都是 DSL 语言,用来描述软件交付流水线的一部分。 脚本式流水线是用一种限制形式的 Groovy 语法编写的。
文档:https://www.jenkins.io/zh/doc/book/pipeline/getting-started/
多种方式
官方提供的流水线可以通过以下任一方式来创建
1.通过 Blue Ocean - 在 Blue Ocean 中设置一个流水线项目后,Blue Ocean UI 会帮你编写流水线的 Jenkinsfile 文件并提交到源代码管理系统。
2.通过经典 UI - 你可以通过经典 UI 在 Jenkins 中直接输入基本的流水线。
3.在源码管理系统中定义 - 你可以手动编写一个 Jenkinsfile 文件,然后提交到项目的源代码管理仓库中。
开始构建
这里就用Jenkins里面自带的(经典 UI )流水线管理来做演示
首先,创建项目选择流水线
编写流水线构建脚本
在流水线填写如下代码
pipeline { agent any stages { stage('构建') { steps { echo "拉取代码" sh ''' git clone https://gitlab.aiwanyun.cn/root/test.git cd test docker build -t myapp . ''' } } stage('测试') { steps { echo "这里可以执行执行集成测试" } } stage('发布') { steps { sh ''' docker run --restart=always --name myapp -e TZ=Asia/Shanghai -p 8080:80 -d myapp ''' } } } }
开始构建
这里演示手动触发构建
点击立即构建即可
查看流水线日志
上面是可视化查看流水线构建的进度图
还可以通过控制台查看详细日志
成功判断
往下拉可以看到日志提示失败
原来是刚才的容器已经启动
镜像构成后我需要停止原来的已经启动的容器服务
这时修改一下流水线脚本先停止原来的服务再重新启动
pipeline { agent any stages { stage('测试') { steps { echo "这里可以执行执行集成测试" npm run test } } stage('构建') { steps { echo "拉取代码" sh ''' rm -rf test git clone https://gitlab.aiwanyun.cn/root/test.git cd test docker build -t myapp . ''' } } stage('测试') { steps { echo "这里可以执行执行集成测试" npm run test } } stage('发布') { steps { sh ''' docker stop myapp docker rm myapp docker run --restart=always --name myapp -e TZ=Asia/Shanghai -p 8080:80 -d myapp ''' } } } }
可以看到修改了流水线脚本后
最后的集成构建成功发布
访问服务
此时再去访问web服务
访问一下swagger接口文档
可以看到部署成功
再回来看流水线视图
可以看到最后一次都是绿色说明每个阶段的任务都没有出错,代表集成部署任务成功。
在每个阶段可以对任务的耗时进行,方便排查以及优化等
2.jenkins拉取svn老本本代码(tls1.0 tls1.1)
由于某种情况下我们需要去拉取老版本的svn代码库,jenkins在拉取代码时会报错: Unable to access the repository
解决办法也很简单,java配置中默认禁用了tls1.0 tls1.1的访问,我们打开即可,下面是具体操作方法。
找到java.security文件
java环境中的应用的java.security文件是默认禁用了tls1.0 tls1.1的访问请求,这里我以jenkins java 11的容器环境为例子:
进入容器
docker exec -it mf-jenkinsserver bash find / -name java.security
可以看到我们已经找到java.security文件了
修改java.security文件
修改前内容
#jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ # DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ # include jdk.disabled.namedCurves
修改后内容
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ include jdk.disabled.namedCurves
然后保存即可,退出容器
映射文件
由于在容器环境中修改未映射的文件在重新创建容器后数据会丢失,所以此时我们需要拷贝内容出来放到一个可持久化的地方即可
docker run --restart=always --name mf-jenkinsserver \
-e TZ=Asia/Shanghai \
--storage-opt size=100G
-p 8888:8080 -p 50000:50000 \
-u 0 \
-v /var/myworkhome/jenkins/home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/myworkhome/jenkins/dockerScript/java.security:/opt/java/openjdk/conf/security/java.security \
-v /var/myworkhome/jenkins/war/jenkins.war:/usr/share/jenkins/jenkins.war \
-d mf-jenkinsserver
把从 容器拷贝出来的java.security文件用docker映射进去,下次构建容器时出现丢失数据的问题
至此获取svn老版本的配置完成,我们可以再次尝试拉取代码就不会报“ Unable to access the repository”错误了。