目录
- 一、简介
- 二、Jenkins + K8s
- 2.1 Jenkins配置k8s-master服务器信息
- 2.2 配置镜像仓库信息
- 2.3 编写k8s yaml文件
- 2.4 将yaml文件推送到k8s
- 2.5 配置免密钥登录
- 2.6 k8s部署yaml资源文件
- 2.7 重新部署yaml资源文件
- 2.8 构建注意事项
- 2.9 完整Jenkinsfile
- 2.10 构建成功
- 三、Webhook
- 源码
一、简介
从零开始带你实现一套自己的CI/CD(一)Jenkins
从零开始带你实现一套自己的CI/CD(二)Jenkins+Sonar Qube
从零开始带你实现一套自己的CI/CD(三)Jenkins+Harbor
从零开始带你实现一套自己的CI/CD(四)Jenkins Pipeline流水线
上一节我们学习了Jenkins Pipeline风格的方式,Jenkins执行目标服务器编写好的shell脚本进行容器部署。但是也是有缺点的:编写的shell脚本比较复杂,容器不方便管理。这一节我们就学习一下Jenkins结合K8s技术实现项目部署。
k8s官方文档:https://kubernetes.io/zh-cn/docs/home/
Kubernetes 为你提供:
- 服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。- 存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。- 自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。- 自动完成装箱计算
你为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。- 自我修复
Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。- 密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
二、Jenkins + K8s
2.1 Jenkins配置k8s-master服务器信息
进入Jenkins 系统管理 -》 系统配置 -》 Publish over SSH,添加k8s-master节点的服务器信息:
Remote Directory 是Jenkins服务器连接到k8s服务器时的目录,我们填写/usr/local/k8s
,注意需要将该目录创建出来。
勾选Use password authentication, or use a different key,输入服务器密码。
2.2 配置镜像仓库信息
在Jenkins连接到k8s-master服务器后,需要执行k8s命令进行部署,需要从Harbor镜像仓库中拉取我们的镜像,所以需要在docker中配置Harbor的账号密码信息。
注意:k8s集群所有的节点都需要修改这个配置,因为部署的时候不一定是哪一个节点。
vim /etc/docker/daemon.json
#加入harbor镜像仓库的地址,注意Json的格式,不要少了逗号
"insecure-registries": ["http://192.168.153.131:80"]
#重启Docker服务
systemctl restart docker
然后使用docker login命令登录试一下
2.3 编写k8s yaml文件
创建pipeline.yaml
文件:
pipeline.yaml文件创建了一个Deployment、一个Service、一个Ingress
Pod镜像指向Harbor镜像仓库中的镜像。
Service8886端口映射到容器的8080端口。
Ingress host配置 hello.world.com域名转发到创建的Service。
需要修改本地hosts文件,映射hello.world.com域名到k8s集群的任意IP地址。
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: test
name: pipeline
labels:
app: pipeline
spec:
replicas: 2
selector:
matchLabels:
app: pipeline
template:
metadata:
labels:
app: pipeline
spec:
containers:
- name: pipeline
image: 192.168.153.131:80/helloworld/helloworld:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
namespace: test
labels:
app: pipeline
name: pipeline
spec:
selector:
app: pipeline
ports:
- port: 8886
targetPort: 8080
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: test
name: pipeline
spec:
ingressClassName: ingress
rules:
- host: hello.world.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pipeline
port:
number: 8886
2.4 将yaml文件推送到k8s
接下来修改我们的Jenkinsfile的流程
删除之前Publish Over SSH的步骤,不再需要去执行目标服务器中准备好的shell脚本,而是将Git仓库中编写好的pipeline.yaml k8s资源文件推送到k8s-master节点
。然后通过k8s部署pipeline.yaml
资源文件。
Jenkins将pipeline.yaml
文件推送到k8s-master服务器
注意推送的目录就是之前配置的/usr/local/k8s
目录下
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: 'pipeline.yaml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
然后开始构建,如果能够在k8s-master服务器的**/usr/local/k8s**目录看到pipeline.yaml
文件,就表示我们配置的没有问题。
在k8s-master节点进行查看:
2.5 配置免密钥登录
Jenkins配置免密钥登录k8s-master主机
将pipeline.yaml文件推送到k8s-master节点后,是无法直接执行kubectl apply
命令的,因为没有权限。
所以需要配置免秘钥登录。
将Jenkins中公钥信息
复制到k8s-master的~/.ssh/authorized_keysz
中,保证远程连接无密码。
#jenkins
cd ~
ls -a
ssh-keygen -t rsa # 如果没有.ssh文件,用此命令生成
cd .ssh/
cat id_rsa.pub # 查看公钥
#k8s-master
cd ~
mkdir .ssh
cd .ssh/ # 如果没有.ssh文件,直接使用mkdir .ssh 命令创建即可
vi authorized_keys #将公钥直接粘贴保存
将Jenkins服务器的公钥信息粘贴到k8s-master服务器的.ssh/authorized_keys
然后再部署Jenkins的服务器通过ssh root@192.168.153.128 ls
命令,不需要输入密码执行了命令则说明配置成功。
2.6 k8s部署yaml资源文件
然后生成Jenkins流水线语法
将ssh root@192.168.153.128 kubectl apply -f /usr/local/k8s/pipeline.yaml
shell命令转换为流水线语法
sh 'ssh root@192.168.153.128 kubectl apply -f pipeline.yaml'
我们在Jenkinsfile中在添加一个步骤:将pipeline.yaml文件推送到k8s-master节点后,执行kubectl apply
命令进行部署。
2.7 重新部署yaml资源文件
在完成以上步骤后,看似Jenkins和K8s的整合已经完成了,但是这里还有一个问题。
当我们的代码发生了变化,但是pipeline.yaml资源文件没有改变,k8s则不会重新执行部署。
所以我们需要增加一条k8s命令:kubectl rollout restart Deployment pipeline -n test
,就算pipeline.yaml没有发生改变,k8s也会重新部署。
sh '''ssh root@192.168.153.128 kubectl apply -f /usr/local/k8s/pipeline.yaml
ssh root@192.168.153.128 kubectl rollout restart Deployment pipeline -n test'''
2.8 构建注意事项
我们使用了k8s部署,不再需要参数化构建
所以可以把之前需要的参数全部删除了,对应需要修改我们的Jenkinsfile中的tag变量:
在pipeline.yaml中的镜像版本也修改为latest
2.9 完整Jenkinsfile
pipeline {
agent any
environment{
harborHost = '192.168.153.131:80'
harborRepo = 'helloworld'
harborUser = 'admin'
harborPasswd = 'Harbor12345'
}
// 存放所有任务的合集
stages {
stage('Pull Code') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[url: 'https://gitee.com/L1692312138/jenkins-demo.git']]])
}
}
stage('Maven Build') {
steps {
sh '/var/jenkins_home/apache-maven-3.8.6/bin/mvn clean package -DskipTests'
}
}
stage('Push Harbor') {
steps {
sh '''cp ./target/*.jar ./deploy/
cd ./deploy
docker build -t ${JOB_NAME}:latest .'''
sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
docker tag ${JOB_NAME}:latest ${harborHost}/${harborRepo}/${JOB_NAME}:latest
docker push ${harborHost}/${harborRepo}/${JOB_NAME}:latest'''
}
}
stage('Publish Over SSH') {
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: 'pipeline.yaml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('Deployment k8s') {
steps {
sh '''ssh root@192.168.153.128 kubectl apply -f /usr/local/k8s/pipeline.yaml
ssh root@192.168.153.128 kubectl rollout restart Deployment pipeline -n test'''
}
}
}
post {
always {
emailext body: '${FILE,path="email.html"}', subject: '【构建通知】:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', to: 'liush99@foxmail.com'
}
}
}
2.10 构建成功
Deployment
Pod
Service
Ingress
访问服务
三、Webhook
Jenkins下载Gitee插件
如果你使用的不是Gitee,是其他的Github、GitLab、Gogs仓库则自行下载对应的Jenkins插件。
然后进入项目中配置 构建触发器,勾选 Gitee webhook触发构建
点击生成Gitee WebHook密码
在Gitee仓库 管理 --》 WebHooks --》 添加WebHooks
输入回调Jenkins的URL和密码,点击添加
出现了一个错误,Gitee WebHooks的URL需要是公网可以访问的IP,由于博主是搭建的虚拟机,所以这一步就无法实现了。
到此为止,Jenkins 整合 K8s构建项目的方式就完成了!
源码
Gitee:https://gitee.com/L1692312138/jenkins-demo.git
Github:https://github.com/Liu-Shihao/helloworld.git