基于 Jenkins+K8s 构建 DevOps 自动化运维管理

2023-08-11 16:23:43   LINUX

  k8s jenkins  

基于已有k8s环境安装

角色IP
master192.168.235.190
node1192.168.235.191
node2192.168.235.192


安装NFS服务:

所有主机安装:

yum install nfs-utils -y
systemctl enable nfs --now

master主机创建共享目录:

[root@master ~]# mkdir -pv /data/v1
[root@master ~]# vim /etc/exports
/data/v1 *(rw,no_root_squash)

使配置文件生效:

[root@master ~]# exportfs -arv
exporting *:/data/v1
[root@master ~]# systemctl restart nfs
[root@master ~]# chmod -R 777 /data/v1/

在kubernetes中创建jenkins:

创建命名空间:

[root@master ~]# kubectl create namespace jenkins-k8s

创建pv:

[root@master ~]# mkdir jenkins
[root@master ~]# cd jenkins/
[root@master jenkins]# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
 name: jenkins-k8s-pv
spec:
 capacity:
   storage: 10Gi
 accessModes:
 - ReadWriteMany
 nfs:
   server: 192.168.78.143
   path: /data/v1

[root@master jenkins]# kubectl apply -f pv.yaml
persistentvolume/jenkins-k8s-pv created

[root@master jenkins]# kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
jenkins-k8s-pv   10Gi       RWX            Retain           Available                                   5s

创建pvc:

[root@master jenkins]# vim pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
 name: jenkins-k8s-pvc
 namespace: jenkins-k8s
spec:
 resources:
   requests:
     storage: 10Gi
 accessModes:
 - ReadWriteMany

[root@master jenkins]# kubectl apply -f pvc.yaml
persistentvolumeclaim/jenkins-k8s-pvc created

[root@master jenkins]# kubectl get pvc -n jenkins-k8s
NAME              STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
jenkins-k8s-pvc   Bound    jenkins-k8s-pv   10Gi       RWX                           7s

创建一个sa账号:

[root@master jenkins]# kubectl create sa jenkins-k8s-sa -n jenkins-k8s
serviceaccount/jenkins-k8s-sa created

# 把上面的 sa 账号做 rbac 授权
[root@master jenkins]# kubectl create clusterrolebinding jenkins-k8s-sa-cluster -n jenkins-k8s --clusterrole=cluster-admin --serviceaccount=jenkins-k8s:jenkins-k8s-sa




通过 deployment 部署 jenkins:

[root@master jenkins]# vim jenkins-deployment.yaml 
kind: Deployment
apiVersion: apps/v1
metadata:
 name: jenkins
 namespace: jenkins-k8s
spec:
 replicas: 1
 selector:
   matchLabels:
     app: jenkins
 template:
   metadata:
     labels:
       app: jenkins
   spec:
     serviceAccount: jenkins-k8s-sa
     containers:
     - name: jenkins
       image:  jenkins/jenkins:2.328
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 8080
         name: web
         protocol: TCP
       - containerPort: 50000
         name: agent
         protocol: TCP
       resources:
         limits:
           cpu: 2000m
           memory: 2Gi
         requests:
           cpu: 500m
           memory: 512Mi
       livenessProbe:
         httpGet:
           path: /login
           port: 8080
         initialDelaySeconds: 60
         timeoutSeconds: 5
         failureThreshold: 12
       readinessProbe:
         httpGet:
           path: /login
           port: 8080
         initialDelaySeconds: 60
         timeoutSeconds: 5
         failureThreshold: 12
       volumeMounts:
       - name: jenkins-volume
         subPath: jenkins-home
         mountPath: /var/jenkins_home
     volumes:
     - name: jenkins-volume
       persistentVolumeClaim:
         claimName: jenkins-k8s-pvc

[root@master jenkins]# kubectl apply -f jenkins-deployment.yaml

[root@master jenkins]# kubectl get pods -n jenkins-k8s -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
jenkins-9db894c8c-j9tr7   1/1     Running   0          2m14s   10.244.169.129   k8s-node2   <none>           <none>


把 jenkins 前端加上 service 提供外部网络访问:

[root@master jenkins]# vim jenkins-service.yaml 
apiVersion: v1
kind: Service
metadata:
 name: jenkins-service
 namespace: jenkins-k8s
 labels:
   app: jenkins
spec:
 selector:
   app: jenkins
 type: NodePort
 ports:
 - name: web
   port: 8080
   targetPort: web
   nodePort: 30002
 - name: agent
   port: 50000
   targetPort: agent

[root@master jenkins]# kubectl apply -f jenkins-service.yaml
service/jenkins-service created

[root@master jenkins]# kubectl get svc -n jenkins-k8s
NAME              TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                          AGE
jenkins-service   NodePort   10.99.229.21   <none>        8080:30002/TCP,50000:30527/TCP   7s


把 jenkins 前端加上 service 提供外部网络访问:

[root@master jenkins]# vim jenkins-service.yaml 
apiVersion: v1
kind: Service
metadata:
 name: jenkins-service
 namespace: jenkins-k8s
 labels:
   app: jenkins
spec:
 selector:
   app: jenkins
 type: NodePort
 ports:
 - name: web
   port: 8080
   targetPort: web
   nodePort: 30002
 - name: agent
   port: 50000
   targetPort: agent

[root@master jenkins]# kubectl apply -f jenkins-service.yaml
service/jenkins-service created

[root@master jenkins]# kubectl get svc -n jenkins-k8s
NAME              TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                          AGE
jenkins-service   NodePort   10.99.229.21   <none>        8080:30002/TCP,50000:30527/TCP   7s

#通过上面可以看到 service 的 8080 端口在物理机映射的端口是 30002


配置jenkins:

在浏览器访问 jenkins 的 web 界面:http://192.168.78.143:30002:

5f35caa5b4df48b6879c067513e32ec0.png


1.2.1 获取管理员密码


在 nfs 服务端,也就是我们的 master1 节点获取密码:

[root@master jenkins]# cat /data/v1/jenkins-home/secrets/initialAdminPassword 
081e9ebd3c7243819817c0f6a1adb5d8


把上面获取到的密码拷贝到上面管理员密码下的方框里:网址:yii666.co图片.png
m图片.png


图片.png



点击继续出现如下界面:

图片.png




安装插件:

选择“安装推荐的插件”:

图片.png




插件安装好之后显示如下:

图片.png



创建第一个管理员用户:

图片.png


文章来源地址:https://www.yii666.com/blog/399196.html

用户名和密码都设置成 admin,线上环境需要设置成复杂的密码。修改好之后点击保存并完成,出现如下界面:
图片.png



不用修改,点击保存并完成,出现如下界面:

图片.png


点击开始使用 Jenkins,至此 Jenkins 配置完成!:

图片.png


测试 jenkins 的 CI/CD:

在 Jenkins 中安装 kubernetes 插件
在 jenkins中安装 k8s 插件网址:
点击左边列表中的 Manage Jnekins ------> 插件管理 ------> 可选插件 ------> 搜索 kubernetes ------>出现如下:

图片.png



安装 blueocean 插件

 选中 kubernetes 之后 ------> 点击下面的“Download now and install after restart”(下载待重启后安装)------> 勾选“安装之后选择重新启动 jenkins” ---> 重启之后登陆 jenkins,插件即可生效
安装 blueocean 插件:

图片.png






配置 jenkins 连接到我们存在的 k8s 集群:

点击“系统管理” -> 系统配置 -> 页面拉到最下 -> 点击“a separate configuration page”:

图片.png


新增一个云,在下拉菜单中选择 kubernets:

图片.png


填写云 kubernetes 配置内容:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


https://192.168.78.143:6443:


【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


测试 jenkins 和 k8s 是否可以通信
Kubernetes 命名空间:jenkins-k8s
Jenkins 地址:http://jenkins-service.jenkins-k8s.svc.cluster.local:8080:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

Connected to Kubernetes v1.23.1 说明测试成功,Jenkins 可以和 k8s 进行通信!


配置 pod-template:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


添加一个模板:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)



【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


添加容器:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

Docker 镜像:使用 jenkins-jnlp.tar.gz 解压出来的镜像 xianchao/jenkins-jnlp:v1,把这个镜像压缩包上传到 k8s 的各工作节点并手动解压::

# 解压出来的镜像是 xianchao/jenkins-jnlp:v1
[root@node1 ~]# docker load -i jenkins-jnlp.tar.gz
[root@node2 ~]# docker load -i jenkins-jnlp.tar.gz

在每一个 pod template 右下脚都有一个高级,点击高级:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

       

往下拉,在 Service Account 处输入 jenkins-k8s-sa,这个 sa 就是我们最开始安装 jenkins 时创建的 sa:【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


添加两个卷
添加卷 ------> 选择 Host Path Volume :

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


/var/run/docker.sock
/var/run/docker.sock
/root/.kube
/home/jenkins/.kube

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)





上面配置好之后,点击 Apply(应用) ------> Save(保存) :

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)



添加 Docker Hub 凭据:

注意:如果没有 Docker Hub 账号则需要先去注册 Docker
        首页 ------> 系统管理 Manage Credentials(管理凭据)------> 点击 Stores scoped to Jenkins下的第一行 jenkins 后面的全局,显示如下:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


点击添加凭据(也可以添加阿里云私有镜像仓库账户),出现如下:【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)



测试通过 Jenkins 部署应用发布到 k8s 开发环境、测试环境、生产环境 :

开发提交代码到代码仓库 gitlab -> jenkins 检测到代码更新 -> 调用 k8s api 在 k8s 中创建jenkins slave pod:
        Jenkins slave pod 拉取代码 -> 通过 maven 把拉取的代码进行构建成 war 包或者 jar 包 ---> 上传代码到 Sonarqube 进行静态代码扫描 --> 基于 war 包构建 docker image --> 把镜像上传到阿里云(或者 harbor)镜像仓库 --> 基于镜像部署应用到开发环境 --> 部署应用到测试环境 ---> 部署应用到生产环境。

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


创建名称空间:

[root@master ~]# kubectl create ns devlopment
[root@master ~]# kubectl create ns production
[root@master ~]# kubectl create ns qatest

在 jenkins 创建任务
回到首页,开始创建一个新任务:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


输入一个任务名称:jenkins-variable-test-deploy -> 选择流水线 -> 确定:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

在 Pipeline script 处输入如下内容:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


node('test') {                // 基于前面创建的 pod 模板创建 jenkins slave pod
   stage('Clone') {
       echo "1.Clone Stage"    // 第一步克隆代码
       git url: "https://github.com/loveyou2333/jenkins-sample.git"    // 自己的项目地址
       script {
           build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
       }                    // 检测代码是否有更新,如有则生成随机数字
   }
   stage('Test') {
     echo "2.Test Stage"            // 第二步测试

   }
   stage('Build') {            // 第三步构建镜像
       echo "3.Build Docker Image Stage"
       sh "docker build -t fuhxxx/jenkins-demo:${build_tag} ."    // Docker Hub 账户地址
   }
   stage('Push') {            // 第四步推送镜像到仓库
       echo "4.Push Docker Image Stage"
       withCredentials([usernamePassword(credentialsId: 'DockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
           sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"        // 自动获取 docker hub 的用户和密码;'DockerHub' 为前面创建的凭据 id
           sh "docker push fuhxxx/jenkins-demo:${build_tag}"            // 修改为自己的账户
       }
   }
   stage('Deploy to dev') {    // 部署应用到开发环境
       echo "5. Deploy DEV"
       sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev.yaml"
       sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev.yaml"
//        sh "bash running-devlopment.sh"
       sh "kubectl apply -f k8s-dev.yaml  --validate=false"
   }    
   stage('Promote to qa') {        // 部署项目到测试环境
       def userInput = input(
           id: 'userInput',

           message: 'Promote to qa?',
           parameters: [
               [
                   $class: 'ChoiceParameterDefinition',
                   choices: "YES\nNO",    // 手动判断是否部署
                   name: 'Env'
               ]
           ]
       )
       echo "This is a deploy step to ${userInput}"
       if (userInput == "YES") {
           sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-qa.yaml"
           sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-qa.yaml"
//            sh "bash running-qa.sh"
           sh "kubectl apply -f k8s-qa.yaml --validate=false"
           sh "sleep

把 GitHub - luckylucky421/jenkins-sample 项目 fork 到自己的 GitHub 上,并修改 k8s-dev.yaml、k8s-qa.yaml、k8s-prod.yaml 三个文件里的镜像名称:

       

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)



构建任务  点击应用 ------> 保存 ------> 立即构建 -> 在 #1 的 Console Output 可看到构建过程::

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

在 Console Output 如果看到如下,点击 Input requested:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

点击继续

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中) 从上面可以看到已经把应用部署到 dev 环境了,点击 Input requested

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)通过上面可

以看到把应用部署到了 pro 环境了,验证是否在 devlopment 和 production 名称空间下有应用:

[root@master ~]# kubectl get pods -n devlopment 
NAME                            READY   STATUS    RESTARTS   AGE
jenkins-demo-5f6c587df5-jlxhz   1/1     Running   0          12m

[root@master ~]# kubectl get pods -n qatest
NAME                            READY   STATUS    RESTARTS   AGE
jenkins-demo-5f6c587df5-9wnph   1/1     Running   0          3m10s

[root@master ~]# kubectl get pods -n production
NAME                            READY   STATUS    RESTARTS   AGE
jenkins-demo-5f6c587df5-rhcn6   1/1     Running   0          2m25s

通过上面可以看到 jenkins 对接 k8s,可以把应用发布到 k8s 集群的开发、测试、生产环境了。
打开 blue ocean 会看到如下流程,你也可以尝试重新运行构建,手动点击确认部署流程:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

Jenkins 实现 k8s 应用按照指定版本回滚:

Jenkins 实现 k8s 应用按照指定版本回滚
        回到首页 -> 新建一个任务 ------> 输入一个任务名称:jenkins-variable-test-deploy-rollout ------> 流水线 ------> 确定 ------> 在 Pipeline script 处输入如下内容:

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)




node('test') {                // 基于前面创建的 pod 模板创建 jenkins slave pod
   stage('Clone') {
       echo "1.Clone Stage"    // 第一步克隆代码
       git url: "https://github.com/loveyou2333/jenkins-sample.git"    // 自己的项目地址
       script {
           build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
       }                    // 检测代码是否有更新,如有则生成随机数字
   }
   stage('Test') {
     echo "2.Test Stage"            // 第二步测试

   }
   stage('Build') {            // 第三步构建镜像
       echo "3.Build Docker Image Stage"
       sh "docker build -t fuhxxx/jenkins-demo:${build_tag} ."    // Docker Hub 账户地址
   }
   stage('Push') {            // 第四步推送镜像到仓库
       echo "4.Push Docker Image Stage"
       withCredentials([usernamePassword(credentialsId: 'DockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
           sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"        // 自动获取 docker hub 的用户和密码;'DockerHub' 为前面创建的凭据 id
           sh "docker push fuhxxx/jenkins-demo:${build_tag}"            // 修改为自己的账户
       }
   }
   stage('Deploy to dev') {    // 部署应用到开发环境
       echo "5. Deploy DEV"
       sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev.yaml"
       sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev.yaml"
//        sh "bash running-devlopment.sh"
       sh "kubectl apply -f k8s-dev.yaml  --validate=false"
   }    
   stage('Promote to qa') {        // 部署项目到测试环境
       def userInput = input(
           id: 'userInput',

           message: 'Promote to qa?',
           parameters: [
               [
                   $class: 'ChoiceParameterDefinition',
                   choices: "YES\nNO",    // 手动判断是否部署
                   name: 'Env'
               ]
           ]
       )
       echo "This is a deploy step to ${userInput}"
       if (userInput == "YES") {
           sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-qa.yaml"
           sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-qa.yaml"
//            sh "bash running-qa.sh"
           sh "kubectl apply -f k8s-qa.yaml --validate=false"
           sh "sleep


点击应用 -> 保存 -> 立即构建(三角符):

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)


在构建过程中即可选择需要回滚的环境和指定的版本!