持续集成部署(CI/CD)

介绍

持续集成持续部署(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”错误了。

 

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇