说明
通过本文章,您可以轻松入门cicd过程。本地测试环境为springboot微服务项目。用户提交代码到gitlab,触发jenkins拉取gitllab上的代码,然后完成编译构建成jar包,同步完成sonarsqube代码质量检测。然后在jenkins内部完成生成镜像,并将镜像推送到harbor仓库中,然后通过K8s完成服务的部署。
依赖环境部署
环境准备
使用环境说明
使用的虚拟机环境centos7.9,使用vmware安装
同步主机时区为亚洲,并同步时间
[root@linux-node ~]# echo "ZONE=Asia/Shanghai" >> /etc/sysconfig/clock
[root@linux-node ~]# rm -f /etc/localtime
#链接到上海时区文件
[root@linux-node ~]# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
关闭防火墙和selinux
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost ~]# setenforce 0
[root@localhost ~]# sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
设置yum源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache
安装docker
创建数据目录将数据持久话到该目录下,以便后期好维护
mkdir -p /data
安装maven
gitlab安装部署
harbor安装部署
jenkins安装部署
sonarqube部署
docker安装sonarsqube
k8s部署
部署过程略
创建java工程并测试将代码上传到gitlab仓库
gitlab上创建项目
创建springboot工程,并将代码提交到hello-test工程下
编写Jenkinsfile的方式
流水线语法
我们在编写jenkins流水线脚本时可以先将框架写好,然后再补齐内容。
pipeline {
//指定任务在哪个集群节点上执行
agent any
//声明环境变量,方便后面使用
environment {
key='value'
}
stages {
stage('拉取git仓库代码') {
steps {
echo '拉取git仓库代码-SUCCESS'
}
}
stage('通过maven构建项目') {
steps {
echo '通过maven构建项目-SUCCESS'
}
}
stage('通过sonarqube做代码质量检测') {
steps {
echo '代码质量检测-SUCCESS'
}
}
stage('通过docker制作自定义镜像') {
steps {
echo 'docker制作自定义镜像-SUCCESS'
}
}
stage('将自定义镜像推送到harbor仓库中') {
steps {
echo '推送到harbor仓库-SUCCESS'
}
}
stage('通过publish over ssh通知目标服务器') {
steps {
echo '通知目标服务器-SUCCESS'
}
}
}
}
生成jenkins 流水线脚本
点击下方的流水线语法
例如:我要从git上下载代码
下面填好之后
点击生成流水线脚本
把生成的脚本粘贴到对应的步骤下
这样就完成了流水线代码的生成。
可以在对应的stage处查看对应步骤的日志。
使用git维护Jenkinsfile文件
在gitlab一个项目中创建Jenkinsfile,可以在一个单独的项目中,也可放到对应项目中
在项目目录下创建Jenkinsfile文件,名称必须是这样的。J为大写的。
将内容放到该文件中
点击commit changes
这样工程根目录下就多了个Jenkinsfile文件,我们就可以在gitlab上去维护该文件了。
jenkins上配置使用gitlab上的Jenkinsfile
构建后发现多了该步骤
jenkins全局配置
管理Jenkins中点击
配置maven
手动配置:
主机上安装maven后将maven的安装目录移动到jenkins数据卷中
重命名文件夹
在页面上配置,MAVEN_HOME要使用容器内部目录,不要使用宿主机目录
配置jdk
页面配置jdk
使用 jenkins流水线完成cicd
新建任务,选择流水线
git下载代码到本地
下面填好之后
点击生成流水线脚本
把生成的脚本粘贴到对应的步骤下
通过maven构建项目
使用sh:shell script步骤
将生成的脚本粘贴到gitlab Jenkinsfile对应的步骤下
通过sonarqube做代码质量检测
通过docker制作自定义镜像
配置使得jenkins内部具有构建镜像能力 docker in docker配置
修改/var/run/docker.sock权限,使其属于root组,并且其他用户有读和写的权限
修改jenkins数据数据卷,jenkins内部要有执行docker命令的能力,需要将下面文件挂载到容器内部。
Jenkins docker-compose.yml文件
version: '3.1'
services:
jenkins:
image: jenkins/jenkins:2.319.1-lts
container_name: jenkins
ports:
- 8090:8080
- 8091:50000
volumes:
- /data/jenkins_home/:/var/jenkins_home/
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
- /etc/docker/daemon.json:/etc/docker/daemon.json
由于之前使用docker run方式启动的jenkins,此时需要删除掉容器,不要删除之前创建的数据卷就可以,然后使用docker-compose方式启动,此时不会删除数据,以后推荐改成docker-compose方式,这样运维人员也知道你的启动时加了哪些参数了,易于维护。
docker stop jenkins
docker rm jenkins
docker-compose up -d
进入到容器内部,测试,发现成功。
生成构建镜像的jenkinsfile内容
将自定义镜像推送到harbor仓库中
使用K8s编排容器完成部署
准备部署的yaml文件
放到项目的根目录下,放到项目的根路径下
apiVersion: apps/v1
kind: Deployment
metadata:
name: pipline-deployment
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
app: pipline-pod
template:
metadata:
labels:
app: pipline-pod
spec:
containers:
- name: pipline
image: 192.168.59.129:8888/hello/pipline-test:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: pipline-service
namespace: dev
spec:
selector:
app: pipline-pod
type: NodePort
ports:
- port: 30002
targetPort: 8080
配置jenkins可以ssh连接到K8s master节点
系统配置里配置K8S主节点
将pipline.yaml文件传送到K8s-master节点上
生成代码放到Jenkinsfile文件中
查看K8s-master节点对应的目录里是否有pipline.yaml文件
在k8s-master节点上执行kubectl apply -f pipline.yaml 命令将服务部署起来
解决jenkins上执行ssh命令时需要输入密码问题
ssh无密码登录设置
docker exec -it jenkins bash
cd ~
mkdir .ssh
$ cd ~/.ssh
ssh-keygen -t rsa -C “email@example.com”
系统提示输入文件保存位置等信息,连续按三次回车即可,生成的SSH key文件的保存路径会在终端中给出:id_rsa id_rsa.pub
cat id_rsa.pub 将内容追加到k8s-master节点/root/.ssh/authorized_keys文件后面
验证
在jenkins容器内部验证,发现不用再输入密码了
配置远程执行命令
gitlab jenkinsfile增加以下步骤
测试验证,注意每次提交需要打tag,不修改pipline文件时并不会重新部署服务。
集成钉钉通知将部署结果发送到钉钉里
安装DingTalk插件
创建钉钉群,获取到webhook
创建过程略
系统配置钉钉
系统管理–系统配置
自动化ci操作
配置提交代码后jenkins自动拉取代码 (webhook配置)
需要安装gitlab插件
勾选下面当代码推送后触发构建
在gitlab上
点击下面的Add webhook后提示
不能填写本地主机的url允许本地地址构建webhook
需要在admin settings network 处勾选
重新添加
会在项目下看到webhook的地址
点击此处测试自动化构建
解决测试webhook返回403问题
解决:
在系统配置里将此处勾选去掉
系统管理 -> 系统设置 -> Enable authentication for ‘/project’ end-point
重新测试会发现jenkins已经开始自动构建了。
ps://img-blog.csdnimg.cn/09cfd85cec5944fb84c039cce83a5314.png)
解决构建过程中提交代码后然后发现没有改动的问题:
解决办法:
需要使用kubectl rollout命令重新滚动一次
kubectl rollout restart deployment pipline-deployment -n dev
修改Jenkinsfile
自动化ci Jenkinsfile文件
pipeline {
//指定任务在哪个集群节点上执行
agent any
//声明环境变量,方便后面使用
environment {
harbor_user='admin'
harbor_password='Harbor12345'
harbor_addr='192.168.59.129:8888'
harbor_repo='hello'
}
stages {
stage('拉取git仓库代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'hello-demo', url: 'http://192.168.59.129:8099/root/hello-demo.git']]])
}
}
stage('通过maven构建项目') {
steps {
sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
}
}
stage('通过sonarqube做代码质量检测') {
steps {
sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target/ -Dsonar.login=23adbf175860533b91bd72d5795ad4f74ab81989'
}
}
stage('通过docker制作自定义镜像') {
steps {
sh '''mv ./target/*.jar ./docker/
docker build -t ${JOB_NAME}:latest ./docker/'''
}
}
stage('将自定义镜像推送到harbor仓库中') {
steps {
sh '''docker login -u ${harbor_user} -p ${harbor_password} ${harbor_addr}
docker tag ${JOB_NAME}:latest ${harbor_addr}/${harbor_repo}/${JOB_NAME}:latest
docker push ${harbor_addr}/${harbor_repo}/${JOB_NAME}:latest'''
}
}
stage('将pipline.yaml传送到K8s-master节点') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'k8s', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'pipline.yaml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('在k8s-master上执行部署命令') {
steps {
sh '''ssh root@192.168.59.128 kubectl apply -f /root/deploy/pipline.yaml
ssh root@192.168.59.128 kubectl rollout restart deployment pipline-deployment -n dev'''
}
}
}
post {
success {
dingtalk(
robot: 'jenkins-dingding',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建: ${JOB_NAME}! \n - 版本:latest \n - 持续时间:${currentBuild.durationString}"]
)
}
failure {
dingtalk(
robot: 'jenkins-dingding',
type: 'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 失败构建: ${JOB_NAME}! \n - 版本:latest \n - 持续时间:${currentBuild.durationString}"]
)
}
}
}