DevOps 之 CICD 服务器 Jenkins
1 Jenkins 部署与基本配置
1.2.1 Jenkins 的安装
Jenkins支持多种安装方法 1.包安装 2.JAVA的WAR文件 #要手动配置,不太方便 3.容器运行#系统要求 最低推荐配置:1.256MB可用内存2.1GB可用磁盘空间(作为一个Docker容器运行jenkins的话推荐10GB) 为小团队推荐的硬件配置:1.1GB+可用内存2.50 GB+ 可用磁盘空间 JAVA 软件配置:1.Java 8—无论是Java运行时环境(JRE)还是Java开发工具包(JDK)都可以。2.Jenkins requires Java 11 or 17 since Jenkins 2.357 and LTS 2.361.1.
注意:新版jenkins_2.401.2启动很慢,可能需要20分钟才能启动成功
范例:Ubuntu22.04二进制包安装jenkins
[root@ubuntu2204 ~]#apt update && apt -y install openjdk-11-jdk [root@ubuntu2204 ~]#wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.414.2_all.deb [root@ubuntu2204 ~]#dpkg -i jenkins_2.414.2_all.deb [root@ubuntu2204 ~]#systemctl status jenkins.service#初始化密码 /var/lib/jenkins/secrets/initialAdminPassword #b5e74b98bf2f4a0e9d34b3e7288e43fe#访问 http://10.0.0.152:8080/ #自定义jenkins,什么插件都不装。 #点选择插件安装,再点无,点安装。不要选安装推荐的插件(从国外拉,速度慢)#创建第一个管理员用户界面,点右下角使用admin账户接续,点击保存并完成(密码就是上面的初始化密码) #自己修改密码 admin123
1.3.3 Jenkins 插件管理及安装
中文插件安装
#点击左侧manage jenkins,在System Configuration下点击plugins #搜Localization: Chinese (Simplified),点击Install#插件装在 /var/lib/jenkins/plugins/ #可以把插件目录拷贝给其他不能联网的机器使用 #服务要重启下,插件才能生效 #systemctl restart jenkins.service #也可以通过浏览器输入 http://10.0.0.152:8080/restart 重启
1.3.5.1 SSH 优化
Jenkins 服务器做为一个CICD工具,后续会经常使用 ssh 协议连接远程主机,为方便连接,建议修改自动信 任远程主机,避免首次连接的人为输入yes的确认过程
在 Jenkins 服务器修改 ssh的客户端配置文件
[root@jenkins ~]#vi /etc/ssh/ssh_config # StrictHostKeyChecking ask #修改此行如下面 StrictHostKeyChecking no #修改客户端配置无需重启ssh服务
git优化
#jenkins左侧系统管理下,全局安全配置Git Host Key Verification Configuration #选 No verification 不检验
默认只能并行2个任务,建议根据CPU核心数,将执行者数量修改为CPU的核数(最多不要超过cpu数2倍)
#左侧系统管理下,系统配置下,执行器数量选择 #这里改成4个,同时允许执行4个构建任务
#备份路径查看 #左侧系统管理下,系统配置下,主目录就是要备份的内容(这里是/var/lib/jenkins)#备份(最好计划任务处理) [root@jenkins ~]#tar zcf jenkins-`date +%F`.tar.gz /var/lib/jenkins/#还原(比如插件被删了) #关闭jenkins #把备份文件解压拷贝过去,注意属性,必须是jenkins账号#启动jenkins
#停止服务 systemctl stop jenkins#删除jenkins主目录中config.xml的如下内容(先做备份,以防万一) vim /var/lib/jenkins/config.xml ....... ################################################################################<useSecurity>true</useSecurity> <authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy"> <denyAnonymousReadAccess>true</denyAnonymousReadAccess> </authorizationStrategy> <securityRealm class="hudson.security.HudsonPrivateSecurityRealm"> <disableSignup>true</disableSignup> <enableCaptcha>false</enableCaptcha> </securityRealm> ################################################################################ .......#重动jenkins systemctl start jenkins #此时不需要账号就可以登录jenkins #左侧系统管理下,安全下全局安全配置,安全域改成Jenkins专有用户数据库 #左侧系统管理下,安全下管理用户,打开admin账号设置密码 #此时需要账号登录jenkins
2.1 Jenkins 实现 CICD 说明
2.2 创建 Freestyle 风格的任务 Job
默认只有自由风格,其他需要安装插件
自由风格本质依赖shell脚本
#点击左侧新建任务或者页面当中的create a job #在Build Steps下选择执行shell,输入shell命令,点击保存#默认执行路径 /var/lib/jenkins/workspace/任务名/ #$SHELL为 /bin/bash #实际上用的shell是sh(不一定认识bash命令)不是bash 解决方法: 在shell脚本开头加上 #!/bin/bash 如: #!/bin/bash pwd echo {1..10} ...#注意:如果shell脚本当中命令错误,还会继续执行下去;如果是语法错误,就报错不会往下执行#脚本可以写在linux系统里,jenkins里直接调用,但是要注意jenkins启动是jenkins用户,注意权限 [root@jenkins ~]#mkdir /data/jenkins/scripts/ -p #创建一个目录,专门放jenkins执行脚本 #这里写一个hello.sh [root@jenkins ~]#vim /data/jenkins/scripts/hello.sh #!/bin/bash pwd echo {1..10} [root@jenkins ~]#chmod +x hello.sh#jenkins中shell执行框填入 /data/jenkins/scripts/hello.sh 即可执行 #但是执行结果无法看出是哪个命令执行的,建议使用调试模式 bash -x ,方便排错 [root@jenkins ~]#bash -x /data/jenkins/scripts/hello.sh + pwd /root + echo 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 #jenkins中shell执行框填入 bash -x /data/jenkins/scripts/hello.sh
#把码云的项目导入到自己的gitlab上 #gitlab上在左侧设置通用下配置导入导出设置(没有gitee用Repository by URL) https://gitee.com/lbtooth/wheel_of_fortune.git#gitlab项目下选择导入项目,点仓库(URL) #输入Git仓库URL
#左侧系统管理右侧插件管理下,可用插件,搜gitlab,点击安装(国外下,速度有点慢)#任务编辑里会多出git,Repository URL输入地址 (别忘了做名称解析) #下面Credentials凭据添加连接用户(也可以点jenkins系统管理下的凭据管理) #ID不写会生成随机字符串(不利于调用),建议写下 #注意下分支名称,没问题就点保存#此时构建任务,在 /var/lib/jenkins/workspace/任务名 看到拉取的代码(没有项目名子目录,直接就是里面的内容) 下面是jenkens使用ssh连接gitlab方法 #随便在一台电脑上生成公钥私钥对 ]#ssh-keygen ]#cat /root/.ssh/id_rsa.pub #公钥文件内容 ... #复制公钥文件内容到gitlab用户下的SSH秘钥里,标题起名jenkins-publickey,方便识别 ]#cat /root/.ssh/id_rsa #私钥内容 ... #复制私钥,在jenkins中新建Credentials凭据,任务中调用 #类型选SSH username with private key,private key下key把私钥内容复制进去 #其他随便填(用户名可写gitlab用户xiaoming方便关联,ID可写gitlab-xiaoming-private-key) #passphrase使用私钥时加密,比较麻烦,一般不加
scp免密拷贝到远程机器上
#切到jenkins用户,因为jenkins使用该用户执行命令,要用该用户的秘钥 [root@jenkins ~]#su - jenkins jenkins@jenkins:~$ ssh-keygen #生成公钥私钥对 #把密码发给对方服务器 jenkins@jenkins:~$ ssh-copy-id root@10.0.0.153#编辑shell脚本 [root@jenkins ~]#vim /data/jenkins/scripts/hello.sh #!/bin/bash HOST_LIST=" 10.0.0.153 10.0.0.154" for i in $HOST_LIST;doscp -r * root@$i:/var/www/html/ done#在jenkins任务中shell执行 #!/bin/bash bash -x /data/jenkins/scripts/hello.sh
项目版本回滚可以通过软链接的方式,指向老版本的项目实现回滚
#脚本进行优化 [root@jenkins ~]#vim /data/jenkins/scripts/hello.sh #!/bin/bash HOST_LIST=" 10.0.0.153 10.0.0.154" TIME=`date +%F_%H-%M-%S`for i in $HOST_LIST;dossh root@$i mkdir -p /opt/wheel-$TIME#远程执行scp -r * root@$i:/opt/wheel-$TIME#删除旧的软连接ssh root@$i rm -rf /var/www/htmlssh root@$i ln -s /opt/wheel-$TIME /var/www/html done#下面为测试内容 gitlab提交新代码,然后jenkins构建任务看效果 #gitlab用户配置公钥 [root@gitlab ~]#ssh-keygen -t rsa [root@gitlab ~]#cat /root/.ssh/id_rsa.pub #下载修改代码 [root@gitlab ~]#git clone git@gitlab.wang.org:example1/wheel.git [root@gitlab ~]#cd wheel/ [root@gitlab wheel]#vim index.html #配置用户提交代码 [root@gitlab wheel]#git config --global user.name "ldc" [root@gitlab wheel]#git config --global user.email "123@qq.com" [root@gitlab wheel]#git add . [root@gitlab wheel]#git commit -m "决定是你了" [root@gitlab wheel]#git push -u origin master
#直接读文件对应的软链接 [root@ubuntu ~]#readlink /var/www/html /opt/wheel-2024-11-05_09-18-17#这里因为命名格式相同,所以排序相当于按时间排序,所以前一个文件就是上一个版本 #寻找文件的前一个文件 [root@ubuntu ~]#ls /opt/ |grep -B1 wheel-2024-11-05_09-18-17 wheel-2024-11-05_08-56-17范例: [root@jenkins ~]#vim /data/jenkins/scripts/wheel-html-gitlab-deploy-rollback.sh #!/bin/bash HOST_LIST=" 10.0.0.153 10.0.0.154 " APP=wheel APP_PATH=/var/www/html DATA_PATH=/opt DATE=`date +%F_%H-%M-%S`deploy () {for i in ${HOST_LIST};dossh root@$i "rm -f ${APP_PATH} && mkdir -pv ${DATA_PATH}/${APP}-${DATE}"scp -r * root@$i:${DATA_PATH}/${APP}-${DATE}ssh root@$i "ln -sv ${DATA_PATH}/${APP}-${DATE} ${APP_PATH}"done }rollback() {for i in ${HOST_LIST};doCURRENT_VERISION=$(ssh root@$i "readlink $APP_PATH")#basename取文件前面的路径CURRENT_VERISION=$(basename ${CURRENT_VERISION})echo ${CURRENT_VERISION}PRE_VERSION=$(ssh root@$i "ls -1 ${DATA_PATH} | grep -B1 ${CURRENT_VERISION}|head -n1 ")echo $PRE_VERSIONssh root@$i "rm -f ${APP_PATH}&& ln -sv ${DATA_PATH}/${PRE_VERSION} ${APP_PATH}"done } #输入参数是deploy就部署,rollback就回滚 case $1 in deploy)deploy;; rollback)rollback;; *)exit;; esac[root@jenkins ~]#chmod +x /data/jenkins/scripts/wheel-html-gitlab-deploy-rollback.sh#jenkins脚本输入如 bash -x /data/jenkins/scripts/wheel-html-gitlab-deploy-rollback.sh rollback
对一个任务根据参数不同进行构建
#在任务下点击配置,点击右侧参数化构建过程,选择类型,输入变量名称 #下面执行脚本可以通过 $变量名称 进行调用#例 把上面的部署回滚做成一个任务 #创建任务,引用上面的任务,选择参数化构建,选项参数 #名称为ACTION #选项为(脚本里支持的参数) deploy rollback #写入描述#执行脚本命令改为参数应用 #!/bin/bash bash -x /data/jenkins/scripts/wheel-html-gitlab-deploy-rollback.sh $ACTION#点击任务部署
把分支作为参数选择
#选择参数化构建,选项参数 #名称为BRANCH #选项为 master dev #写入描述#在指定分支栏改为参数(指定哪个分支,就克隆哪个分支) $BRANCH
把tag作为参数选择
#选择参数化构建,字符参数 #名称为TAG #默认值 v1.0 #写入描述#在指定分支栏改为参数 (写是分支,实际是允许写tag的) $TAG #但是这里得手动输入,不能主动去获取gitlab列表,下面有插件可以实现该功能
#配置任务,选择参数化构建,Git参数,名称写TAG #参数类型可以选 分支或标签 都支持 (修订类型 commit提交id) #默认值必选,这里写 origin/master #指定分支写 $TAG 进行调用#点构建,会TAG栏会自动出现所有标签,分支
#项目链接 https://gitee.com/lbtooth/spring-boot-helloworld.git #把gitee项目导入gitlab仓库#jenkins机器上安装mvn环境(jenkins需要java环境,之前已经装过了) [root@jenkins ~]#apt update && apt -y install maven #mvn镜像加速 [root@jenkins ~]#vim /etc/maven/settings.xml .....<mirror><id>nexus-aliyun</id><mirrorOf>*</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url></mirror> </mirrors> ......#jenkins上创建任务,自由风格 #源码管理添加仓库路径,选择凭据(之前添加过) #指定分支改为 */main 分支 #Build Steps选执行shell #!/bin/bash bash -x /data/jenkins/scripts/spring-boot-helloworld.sh#jenkins上编辑执行脚本 [root@jenkins scripts]#vim /data/jenkins/scripts/spring-boot-helloworld.sh #!/bin/bash mvn clean package -Dmaven.test.skip=true#点击构建任务测试,查看编译后文件 [root@jenkins scripts]#ls /var/lib/jenkins/workspace/freestyle-spring-boot-helloworld/target/#客户端安装jdk [root@ubuntu ~]#apt install -y openjdk-11-jdk
2.7.1.4 准备相关脚本
[root@jenkins ~]#vim /data/jenkins/scripts/spring-boot-helloworld.sh #!/bin/bash #提前在目标服务器上手动创建下面目录 APP_PATH=/data/spring-boot-helloworldHOST_LIST=" 10.0.0.153 10.0.0.154 " mvn clean package -Dmaven.test.skip=truefor host in $HOST_LIST;dossh root@$host killall -9 java &> /dev/nullscp target/spring-boot-helloworld-*-SNAPSHOT.jar root@$host:${APP_PATH}/spring-boot-helloworld.jar#ssh root@$host "java -jar ${APP_PATH}/spring-boot-helloworld.jar --server.port=8888 &"ssh root@$host "nohup java -jar ${APP_PATH}/spring-boot-helloworld.jar --server.port=8888 &>/dev/null & "& done#点击构建任务测试 #可以通过Git Parameter插件选择tag进行升级回滚
jenkins全局环境变量自定义
#左侧系统管理下,系统配置下,全局属性,点环境变量进行定义 #jenkins执行shell或内部调用shell脚本时都可以调用该变量
spring-boot已经继承tomcat, 只有老的java项目是war包, 需要tomcat
#目标服务器先装好tomcat [root@ubuntu ~]#apt install tomcat9#项目路径,导入gitlab库中 https://gitee.com/lbtooth/hello-world-war.git#目标机器编辑tomcat服务,增加域名 [root@ubuntu ~]#vim /etc/tomcat9/server.xml ... <Host name="tomcat.wang.org" appBase="/data/webapps"unpackWARs="true" autoDeploy="true"> </Host> ... [root@ubuntu ~]#systemctl restart tomcat9 [root@ubuntu ~]#mkdir -p /data/webapps [root@ubuntu ~]#chown tomcat.tomcat /data/webapps#jenkins服务器把java项目编译发送到目标机器/data/webapps 即可 #在jenkins编写脚本 [root@jenkins ~]#vim /data/jenkins/scripts/hello-world-war.sh #!/bin/bash #APP_PATH=/var/lib/tomcat9/webapps #系统默认位置,这里修改了 APP_PATH=/data/webapps HOST_LIST=" 10.0.0.153 10.0.0.154 " mvn clean package -Dmaven.test.skip=truefor host in $HOST_LIST;dossh root@$host systemctl stop tomcat9scp target/hello-world-war-*.war root@$host:${APP_PATH}/hello.warssh root@$host systemctl start tomcat9 done#创建任务构建, */main分支,执行shell: (这tomcat不知道为什么不解压war包,但可以访问) #!/bin/bash bash -x /data/jenkins/scripts/hello-world-war.sh#访问 http://tomcat.wang.org:8080/hello/ [root@gitlab ~]#curl -H"host: tomcat.wang.org:8080" http://10.0.0.154:8080/hello/