阶段三:Kubernetes基于Jenkins+Gitlab实现CICD

Kubernetes 集群部署CICD流程图

image

安装gitlab(已经安装好了不用再部署)

[root@master01 ops]# kubectl create ns ops
[root@master01 ops]# mkdir ops && cd ops

注意事项:

YAML 保存位置: ~/k8s-manifests/ops/gitlab.yaml

先在 Kubernetes 管理节点执行:

mkdir -p ~/k8s-manifests/ops
cd ~/k8s-manifests/ops
vi gitlab.yaml

把下方 YAML 全部复制进去;红色字段按当前环境修改;按 Esc 后输入 :wq 保存退出。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: gitlab
  namespace: ops
spec:
  serviceName: "gitlab-svc" 
  selector:
    matchLabels:
      app: gitlab
  template:
    metadata:
      labels:
        app: gitlab
    spec:
      containers:
      - name: gitlab-ce
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/gitlab/gitlab-ce:15.4.6-ce.0
        env:
        - name: TZ                        #设置时区
          value: Asia/Shanghai
        - name: GITLAB_ROOT_PASSWORD      #设置GitLab的root密码
          value: "gitlab123"
        - name: GITLAB_OMNIBUS_CONFIG     #需要修改gitlab.rb文件中的配置可以在这里配置,每个配置一行,需要定义GitLab的URL,关闭无用组件
          value: |                        #"|"表示以下内容是一个多行字符串
            external_url "http://gitlab.lanqicheng.top"
            gitlab_rails['time_zone'] = 'Asia/Shanghai'
            node_exporter['enable'] = false
            redis_exporter['enable'] = false
            postgres_exporter['enable'] = false
            gitlab_exporter['enable'] = false
            grafana['enable'] = false
            grafana['reporting_enabled'] = false
            prometheus['enable'] = false
            prometheus['monitor_kubernetes'] = false
            alertmanager['enable'] = false
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        volumeMounts:
        - name: data
          mountPath: /etc/gitlab
          subPath: config
        - name: data
          mountPath: /var/opt/gitlab
          subPath: data
        - name: data
          mountPath: /var/log/gitlab
          subPath: logs

  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "csi-rbd-sc"
      resources:
        requests:
          storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
  name: gitlab-svc
  namespace: ops
spec:
  clusterIP: None
  selector:
    app: gitlab
  ports:
  - name: http
    port: 80
    targetPort: 80
  - name: https
    port: 443
    targetPort: 443
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gitlab-ingress
  namespace: ops
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "512m"
spec:
  ingressClassName: "nginx"
  rules:
  - host: "gitlab.lanqicheng.top"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: gitlab-svc
            port:
              name: http

[root@master01 ops]# kubectl apply -f gitlab-statefulset.yaml
#安装过程很漫长,需要耐心等等

配置详解:

需要改的项为什么改
namespace: ops与实际命名空间一致;使用默认命名空间时可不写。
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/gitlab/gitlab-ce:15.4.6-ce.0替换为实际可拉取的镜像地址和版本。
accessModes: ["ReadWriteOnce"]按存储类型与读写需求确认。
storageClassName: csi-rbd-sc替换为集群中存在的 StorageClass。
storage: 5Gi按数据量调整容量。
port: 80对外暴露的 Service 端口;调用方按此端口访问。

注意事项:

Jenkins 概述

Jenkins 是一个开源的自动化平台工具,主要用于 持续交付(CI)和持续部署(CD)

它可以帮开发团队在 代码提交后,自动完成:

安装jenkins

kubectl create ns ops
mkdir /data/ops && cd /data/ops

可复制 YAML:

YAML 保存位置: ~/k8s-manifests/ops/jenkins-rbac.yaml

先在 Kubernetes 管理节点执行:

mkdir -p ~/k8s-manifests/ops
cd ~/k8s-manifests/ops
vi jenkins-rbac.yaml

把下方 YAML 全部复制进去;红色字段按当前环境修改;按 Esc 后输入 :wq 保存退出。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: ops
---
# clusterRole
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments", "ingresses"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
  - apiGroups: [""]
    resources: ["pods/log", "events"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
---
# clusterrolebinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins
  namespace: ops
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: ops

配置详解:

需要改的项为什么改
namespace: ops与实际命名空间一致;使用默认命名空间时可不写。

注意事项:

YAML 保存位置: ~/k8s-manifests/ops/jenkins.yaml

先在 Kubernetes 管理节点执行:

mkdir -p ~/k8s-manifests/ops
cd ~/k8s-manifests/ops
vi jenkins.yaml

把下方 YAML 全部复制进去;红色字段按当前环境修改;按 Esc 后输入 :wq 保存退出。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: jenkins
  namespace: ops
spec:
  serviceName: "jenkins-svc"
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      serviceAccount: jenkins
      containers:
      - name: jenkins
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jenkins/jenkins:lts-jdk21   #这个版本是2.492.2
        securityContext:      #初始容器安全上下文,用来控制容器的权限
          privileged: true    #privileged属性设置为true时,容器将被授予主机操作系统的完全权限,包括对底层硬件和内核的访问
          runAsUser: 0        #容器启动以UID为0的用户运行
        ports:
        - name: http
          containerPort: 8080
        - name: agent                   #jenkins slave访问jenkins master端口 
          containerPort: 50000   
        env:
        - name: JAVA_OPTS               #设置Jenkins程序时区
          value: -Duser.timezone=Asia/Shanghai
        - name: TZ
          value: "Asia/Shanghai"        #设置Jenkins镜像时区
        readinessProbe:                 #就绪探针
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60       #首次探测时间
          timeoutSeconds: 5             #超时时间
        volumeMounts:
        - name: data
          mountPath: /var/jenkins_home  # Jenkins的家目录
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "nfs-storage"
      resources:
        requests:
          storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins-svc
  namespace: ops
spec:
  clusterIP: None
  selector:
    app: jenkins
  ports:
    - name: http
      port: 8080
      targetPort: 8080
    - name: agent    #jenkins slave访问jenkins master端口 
      port: 50000
      targetPort: 50000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins-ingress
  namespace: ops
spec:
  ingressClassName: "nginx"
  rules:
  - host: "jenkins.lanqicheng.top"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: jenkins-svc 
            port:
              name: http

  [root@master01 ops]# kubectl apply -f jenkins-statefulset.yaml

配置详解:

需要改的项为什么改
namespace: ops与实际命名空间一致;使用默认命名空间时可不写。
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jenkins/jenkins:lts-jdk21替换为实际可拉取的镜像地址和版本。
port: 8080对外暴露的 Service 端口;调用方按此端口访问。
accessModes: ["ReadWriteOnce"]按存储类型与读写需求确认。
storageClassName: nfs-storage替换为集群中存在的 StorageClass。
storage: 5Gi按数据量调整容量。

注意事项:

[root@master01 ops]# kubectl logs  jenkins-0 -n ops
*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

bcf879b5d5b448e1979ee0fc9a53b127   #第一次登录密钥

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

2025-09-15 09:19:02.376+0000 [id=33]    INFO    jenkins.InitReactorRunner$1#onAttained: Completed initialization
2025-09-15 09:19:02.474+0000 [id=24]    INFO    hudson.lifecycle.Lifecycle#onReady: Jenkins is fully up and running
2025-09-15 09:19:06.211+0000 [id=51]    INFO    h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
2025-09-15 09:19:06.213+0000 [id=51]    INFO    hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1

注意事项:

Jenkins Slave环境准备

所谓 Jenkins Master/Slave 架构,在Master上进行任务分配。然后由Slave来完成

image

系统管理--->cloud--->New cloud

image
image
image
image
image
image

Pipeline流水线

pipeline {
    //指定任务在哪个节点上执行(any表示任意节点)
    agent any
    //用于声明全局环境变量,后面可调用
    environment {
        key='value'
    }

    //stages表示一个流水线任务的集合,所有任务的步骤都要定义在stages中
    stages {
        //一个stage就是一个阶段
        stage('拉取代码') {
            //在steps中定义执行的命令
            steps {
                echo 'SUCCESS'
            }
        }
        stage('构建项目') {
            steps {
                echo 'SUCCESS'
            }
        }
        stage('制作镜像') {
            steps {
                echo 'SUCCESS'
            }
        }
        stage('推送镜像到仓库') {
            steps {
                echo 'SUCCESS'
            }
        }
        stage('部署') {
            steps {
                echo 'SUCCESS'
            }
        }
    }
}

命令作用:

执行结果:

关键参数:

注意事项:

containerd拉取镜像代理设置 [Service] Environment="HTTP_PROXY=http://192.168.110.188:7897" Environment="HTTPS_PROXY=http://192.168.110.188:7897" Environment="NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12,.cluster.local,harbor.lanqicheng.top"


**注意事项:**

        }
    }
        //会显示Pod的名称
            }
        }
        //由于Pod执行完任务就销毁,所以等待一段时间验证Pod是否成功运行
            steps{
            }
        }
    }
}
image
image
image
image

**注意事项:**



metadata:
spec:
  accessModes:
  resources:
    requests:

注意事项:

镜像构建 #定义基础镜像 #安装nodejs和npm


**注意事项:**


#构建镜像
#推送镜像

注意事项:

[kubernetes-tencent] baseurl=https://mirrors.cloud.tencent.com/kubernetes_new/core:/stable:/v1.30/rpm/ enabled=1 gpgcheck=0

[kubernetes-aliyun] baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=0 repo_gpgcheck=0

#拷贝集群的配置文件 #定义镜像

#构建镜像

#推送镜像


**注意事项:**

spec: containers: env: volumeMounts: env: env: env: volumes: persistentVolumeClaim: """ } } } } } } } } } } } } } } } }


**注意事项:**




**代码提交(Commit/Push)**


**持续集成(CI)**




**持续交付(CD)**


**持续部署(CD)**




![](/assets/feishu-images/766d5f675705e066f3be3604.png)

![](/assets/feishu-images/d08d482377a2adc753277747.png)

![](/assets/feishu-images/4fb5a891ebb4d50b3740fce1.png)

![](/assets/feishu-images/edc71637c16415c4a29f1f61.png)


修改仓库上传大小(代码仓库没有部署在K8s,这一步忽略)

---

metadata: spec: rules: http: paths: backend: service: port:


**注意事项:**


#设置Git用户及邮箱

#初始化本地仓库并上传项目代码

#添加当前目录文件到本地仓库


#添加远程仓库地址

#推送本地仓库代码到远程仓库

注意事项:

image
image
image
image
image
image
image
image
image

metadata: spec: accessModes: resources: requests:


**注意事项:**

spec: containers: env: volumeMounts: env: env: volumes: persistentVolumeClaim: """ } } } } } } }


**注意事项:**

spec: containers: env: volumeMounts: env: env: volumes: persistentVolumeClaim: """ } } } } } } } } } }


**注意事项:**


注意事项:

[Unit]

[Socket]

[Install]


**注意事项:**

[Unit]
Description=buildkitd
Documentation=https://github.com/moby/buildkit  
Requires=buildkit.socket  
After=buildkit.socket  

[Service]

[Install]
WantedBy=multi-user.target  

注意事项:


**注意事项:**

spec: containers: env: volumeMounts: env: env: volumes: persistentVolumeClaim: hostPath: hostPath: """ } } } } } } } } script{ //env是Groovy中的一个内置对象,用于操作环境变量 } } } } } }


**注意事项:**



                }
            }
        }

注意事项:

image
image
image
image
image

填入Jenkins集群内部服务地址http://jenkins-svc:8080/project/pipeline-zzyl/和c1a4fe022c07b264b61416c4cdaed15b

image
image
image
image
image
image

} } } } } }


**注意事项:**

spec: containers: env: volumeMounts: env: env: volumes: persistentVolumeClaim: hostPath: hostPath: """ } } } } } } } } script{ //env是Groovy中的一个内置对象,用于操作环境变量 } } } } } } } } } } } } } } } }


**注意事项:**



本文由飞书云文档同步生成。涉及命令、SQL、配置示例时,请以飞书源文档和实际环境执行结果为准。