从零开始带你实现一套自己的CI/CD(五)Jenkins+K8s

一、简介

从零开始带你实现一套自己的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 [email protected] ls命令,不需要输入密码执行了命令则说明配置成功。

在这里插入图片描述

2.6 k8s部署yaml资源文件

然后生成Jenkins流水线语法
ssh [email protected] kubectl apply -f /usr/local/k8s/pipeline.yaml shell命令转换为流水线语法

在这里插入图片描述

sh 'ssh [email protected] 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 [email protected] kubectl apply -f /usr/local/k8s/pipeline.yaml
 ssh [email protected] 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 [email protected] kubectl apply -f /usr/local/k8s/pipeline.yaml
            ssh [email protected] kubectl rollout restart Deployment pipeline -n test'''
            }
        }
    }
    post {
    
    
      always {
    
    
        emailext body: '${FILE,path="email.html"}', subject: '【构建通知】:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', to: '[email protected]'
      }
    }
}

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

猜你喜欢

转载自blog.csdn.net/DreamsArchitects/article/details/128673950