Jenkins + Kubernetes CI/CD 实战指南:从零搭建自动化部署流水线

📋 目录

  1. [Jenkins与K8s CI/CD概述](#Jenkins与K8s CI/CD概述)
  2. 环境准备
  3. Jenkins基础配置
  4. K8s部署资源准备
  5. [编写Jenkins Pipeline](#编写Jenkins Pipeline)
  6. 执行部署与验证
  7. 常见问题与优化

🎯 引言

在微服务架构盛行的今天,如何高效地将代码从开发环境部署到生产环境,是每个团队都要面对的挑战。本文将手把手教你搭建一套基于 Jenkins + Kubernetes 的 CI/CD 自动化部署流水线,实现:

代码提交自动触发构建

自动编译、打包、构建Docker镜像

自动推送镜像到容器镜像仓库

自动部署到K8s集群并实现滚动更新

零停机部署,支持快速回滚

本文基于真实项目实践(仓储管理系统:Spring Boot后端 + Vue3前端),所有配置文件和命令均可直接使用。


第一章:Jenkins与K8s CI/CD概述

1.1 什么是CI/CD?

CI(持续集成):开发人员频繁地将代码集成到主干分支,每次集成都通过自动化构建和测试来验证,快速发现错误。

CD(持续交付/部署):在CI的基础上,自动将通过测试的代码部署到测试环境或生产环境。

传统部署 vs CI/CD

对比项 传统部署 CI/CD自动化
部署频率 周/月级别 日/小时级别
人工操作 编译、打包、上传、重启 一键触发,全自动
错误发现 部署后才发现 构建阶段即发现
回滚速度 需要重新打包部署 一键回滚到历史版本
部署风险 高(人为失误) 低(标准化流程)

1.2 Jenkins + K8s架构优势

开发者提交代码
Gitee/GitHub
Jenkins自动触发
Maven/npm编译构建
Docker构建镜像
推送到镜像仓库CCR
kubectl部署到K8s
滚动更新Pod
用户访问新版本

核心优势

  1. Jenkins宿主机部署:直接访问系统工具(Docker、kubectl、Maven),避免Docker-in-Docker复杂配置
  2. K8s原生支持:滚动更新、自动扩缩容、健康检查、服务发现
  3. 镜像版本管理 :每次构建生成唯一标签(如v1.0-23),支持快速回滚
  4. 统一流程:前后端使用相同的Pipeline模板,易于维护

1.3 完整流程预览

后端部署流程(Spring Boot项目):

复制代码
拉取代码 → Maven编译打包 → 构建Docker镜像 → 推送到CCR → kubectl apply部署 → 验证Pod状态

前端部署流程(Vue3项目):

复制代码
拉取代码 → npm install → npm build → 构建Nginx镜像 → 推送到CCR → kubectl apply部署 → 验证访问

1.4 技术栈说明

本文使用的技术栈版本:

组件 版本 说明
Kubernetes v1.28.2 容器编排平台
Jenkins 2.541.1 LTS CI/CD工具
Docker 26.1.3 容器运行时
Maven 3.6.3 Java项目构建工具
Node.js 16.x 前端构建环境
kubectl 1.28.2 K8s命令行工具
镜像仓库 腾讯云CCR 容器镜像存储

第二章:环境准备

2.1 K8s集群要求

最小配置(本文环境):

  • Master节点:2核4G,CentOS Stream 9
  • Worker节点:至少2个,2核8G
  • 网络插件:Calico/Flannel
  • 存储:支持动态PV(可选,用于持久化数据)

验证集群状态

bash 复制代码
# 检查节点状态(所有节点应为Ready)
kubectl get nodes

# 输出示例:
# NAME         STATUS   ROLES           AGE   VERSION
# k8s-master   Ready    control-plane   30d   v1.28.2
# k8s-node1    Ready    <none>          30d   v1.28.2
# k8s-node2    Ready    <none>          30d   v1.28.2

2.2 Jenkins服务器安装(宿主机方案)

为什么选择宿主机而不是Docker容器?

对比项 Docker容器方案 宿主机方案(推荐)
Docker访问 需要Docker-in-Docker 直接使用宿主机Docker
kubectl访问 需要挂载kubeconfig 直接使用系统kubectl
Maven缓存 容器重启丢失 持久化在宿主机
权限管理 复杂(需要映射UID) 简单(jenkins用户直接授权)
性能 多一层容器开销 原生性能

安装步骤(CentOS/RHEL系统):

bash 复制代码
# 1. 添加Jenkins仓库
sudo wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key

# 2. 安装Jenkins(需要Java 17)
sudo yum install fontconfig java-17-openjdk -y
sudo yum install jenkins -y

# 3. 启动Jenkins服务
sudo systemctl enable jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins

# 4. 获取初始管理员密码
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

访问Jenkins

  • 浏览器打开:http://192.168.1.100:8080(替换为你的服务器IP)
  • 输入初始密码,选择"安装推荐的插件"
  • 创建管理员账号

2.3 必要工具安装

在Jenkins服务器上安装以下工具

2.3.1 Docker安装
bash 复制代码
# 安装Docker
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io -y

# 启动Docker
sudo systemctl enable docker
sudo systemctl start docker

# 将jenkins用户加入docker组(重要!)
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins

# 验证
docker --version
# 输出:Docker version 26.1.3, build ...
2.3.2 kubectl安装
bash 复制代码
# 下载kubectl
curl -LO "https://dl.k8s.io/release/v1.28.2/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

# 验证
kubectl version --client
# 输出:Client Version: v1.28.2
2.3.3 Maven安装
bash 复制代码
# 下载Maven
cd /opt
sudo wget https://dlcdn.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
sudo tar -xzf apache-maven-3.6.3-bin.tar.gz
sudo ln -s /opt/apache-maven-3.6.3 /opt/maven

# 配置环境变量
sudo tee /etc/profile.d/maven.sh <<EOF
export MAVEN_HOME=/opt/maven
export PATH=\$MAVEN_HOME/bin:\$PATH
EOF

source /etc/profile.d/maven.sh

# 验证
mvn -version
# 输出:Apache Maven 3.6.3

2.4 网络连通性验证

关键验证点

bash 复制代码
# 1. Jenkins服务器能访问K8s API Server
curl -k https://192.168.1.10:6443
# 应返回:Unauthorized(说明API Server可达)

# 2. Jenkins服务器能访问镜像仓库
ping ccr.ccs.tencentyun.com
# 应返回:正常ping通

# 3. Jenkins服务器能访问Git仓库
ping gitee.com
# 应返回:正常ping通

# 4. K8s集群能拉取镜像(在任意Worker节点测试)
docker pull ccr.ccs.tencentyun.com/your-namespace/test:latest
# 应返回:成功拉取

防火墙配置(如果启用了防火墙):

bash 复制代码
# Jenkins服务器开放8080端口
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# K8s Master节点开放6443端口(API Server)
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --reload

第三章:Jenkins基础配置

3.1 插件安装

登录Jenkins后,进入 系统管理 → 插件管理,安装以下插件:

必装插件清单

插件名称 用途 说明
Git 代码拉取 支持Gitee/GitHub/GitLab
Pipeline 流水线核心 支持Jenkinsfile
Docker Pipeline Docker构建 提供docker.build()等方法
Kubernetes CLI K8s部署 提供kubectl命令支持
Credentials Binding 凭据管理 安全存储密码/Token
Blue Ocean 可视化界面 更友好的Pipeline视图(可选)

安装步骤

复制代码
1. 进入 "系统管理" → "插件管理" → "可选插件"
2. 搜索框输入插件名称(如"Git")
3. 勾选插件,点击"直接安装"
4. 等待安装完成,重启Jenkins

3.2 凭据配置(核心步骤)

进入 系统管理 → 凭据 → 系统 → 全局凭据 → 添加凭据

3.2.1 Git仓库凭据

类型:Username with password

复制代码
ID: gitee-credentials
用户名: your-gitee-username
密码: your-gitee-password(或Personal Access Token)
描述: Gitee代码仓库访问凭据

验证方法

bash 复制代码
# 在Jenkins服务器上测试
git clone https://gitee.com/your-username/your-repo.git
# 应能成功克隆
3.2.2 镜像仓库凭据

类型:Username with password

复制代码
ID: ccr-credentials
用户名: 100012345678(腾讯云账号ID)
密码: your-ccr-token(在腾讯云容器镜像服务获取)
描述: 腾讯云CCR镜像仓库凭据

获取CCR Token

复制代码
1. 登录腾讯云控制台
2. 进入"容器镜像服务" → "访问凭证"
3. 生成长期访问凭证,复制密码

验证方法

bash 复制代码
# 在Jenkins服务器上测试
docker login ccr.ccs.tencentyun.com -u 100012345678 -p your-ccr-token
# 应返回:Login Succeeded
3.2.3 Kubernetes凭据

类型:Secret file

复制代码
ID: k8s-kubeconfig
文件: 上传kubeconfig文件(下一章生成)
描述: K8s集群访问配置

临时验证(使用Master节点的kubeconfig):

bash 复制代码
# 在K8s Master节点上
cat ~/.kube/config

# 复制内容,保存为 kubeconfig-jenkins.yaml
# 上传到Jenkins凭据

3.3 全局工具配置

进入 系统管理 → 全局工具配置

3.3.1 JDK配置
复制代码
名称: JDK17
JAVA_HOME: /usr/lib/jvm/java-17-openjdk
取消勾选"自动安装"

验证路径

bash 复制代码
# 在Jenkins服务器上
echo $JAVA_HOME
ls -l /usr/lib/jvm/java-17-openjdk
3.3.2 Maven配置
复制代码
名称: Maven-3.6.3
MAVEN_HOME: /opt/maven
取消勾选"自动安装"

配置Maven settings.xml(可选,用于配置阿里云镜像加速):

bash 复制代码
sudo vi /opt/maven/conf/settings.xml

# 在<mirrors>标签内添加:
<mirror>
  <id>aliyun</id>
  <mirrorOf>central</mirrorOf>
  <name>Aliyun Maven</name>
  <url>https://maven.aliyun.com/repository/public</url>
</mirror>
3.3.3 Git配置
复制代码
名称: Default
路径: git
勾选"自动安装"(或指定路径 /usr/bin/git)

3.4 权限配置(关键步骤)

3.4.1 Docker权限

确保jenkins用户能执行docker命令:

bash 复制代码
# 在Jenkins服务器上执行
sudo usermod -aG docker jenkins

# 验证(切换到jenkins用户)
sudo su - jenkins -s /bin/bash
docker ps
# 应能正常执行,不报权限错误

# 如果仍报错,重启Jenkins
exit
sudo systemctl restart jenkins
3.4.2 kubectl权限

将kubeconfig文件放到jenkins用户目录:

bash 复制代码
# 在Jenkins服务器上执行
sudo mkdir -p /var/lib/jenkins/.kube
sudo cp /path/to/kubeconfig /var/lib/jenkins/.kube/config
sudo chown -R jenkins:jenkins /var/lib/jenkins/.kube
sudo chmod 600 /var/lib/jenkins/.kube/config

# 验证(切换到jenkins用户)
sudo su - jenkins -s /bin/bash
kubectl get nodes
# 应能正常访问K8s集群

3.5 Jenkins系统架构图

外部服务
Jenkins服务器
拉取代码
推送镜像
部署应用
编译打包
Jenkins Master
Git插件
Docker引擎
kubectl工具
Maven工具
Gitee代码仓库
腾讯云CCR镜像仓库
K8s集群API Server

3.6 配置验证清单

完成上述配置后,逐项验证:

bash 复制代码
# 1. 在Jenkins服务器上,切换到jenkins用户
sudo su - jenkins -s /bin/bash

# 2. 验证Docker权限
docker ps
docker images

# 3. 验证kubectl权限
kubectl get nodes
kubectl get pods -A

# 4. 验证Maven
mvn -version

# 5. 验证Git
git --version

# 6. 验证镜像仓库登录
docker login ccr.ccs.tencentyun.com -u <username> -p <password>

# 7. 退出jenkins用户
exit

所有命令都应正常执行,无权限错误!


第四章:K8s部署资源准备

4.1 创建Namespace和ServiceAccount

在K8s Master节点上执行:

bash 复制代码
# 创建专用命名空间
kubectl create namespace shaohao-prod

# 创建ServiceAccount(供Jenkins使用)
kubectl create serviceaccount jenkins-deployer -n shaohao-prod

# 验证
kubectl get sa -n shaohao-prod
# 应看到 jenkins-deployer

4.2 配置RBAC权限(最小权限原则)

创建权限配置文件:

bash 复制代码
cat > jenkins-rbac.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: jenkins-deployer-role
  namespace: shaohao-prod
rules:
  # 允许管理Deployment
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "create", "update", "patch", "delete"]

  # 允许管理Pod(用于查看状态)
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]

  # 允许管理Service
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list", "create", "update", "patch"]

  # 允许管理Ingress
  - apiGroups: ["networking.k8s.io"]
    resources: ["ingresses"]
    verbs: ["get", "list", "create", "update", "patch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jenkins-deployer-binding
  namespace: shaohao-prod
subjects:
  - kind: ServiceAccount
    name: jenkins-deployer
    namespace: shaohao-prod
roleRef:
  kind: Role
  name: jenkins-deployer-role
  apiGroup: rbac.authorization.k8s.io
EOF

# 应用配置
kubectl apply -f jenkins-rbac.yaml

# 验证
kubectl get role,rolebinding -n shaohao-prod

权限说明

  • ✅ 只授予shaohao-prod命名空间的权限
  • ✅ 只允许管理Deployment、Service、Ingress
  • ✅ 不允许删除Namespace、修改RBAC
  • ✅ 符合最小权限原则

4.3 生成kubeconfig文件

为Jenkins生成专用的kubeconfig文件:

bash 复制代码
# 获取ServiceAccount的Token(K8s 1.24+需要手动创建Secret)
cat > jenkins-sa-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: jenkins-deployer-token
  namespace: shaohao-prod
  annotations:
    kubernetes.io/service-account.name: jenkins-deployer
type: kubernetes.io/service-account-token
EOF

kubectl apply -f jenkins-sa-secret.yaml

# 等待Token生成
sleep 3

# 提取Token和CA证书
TOKEN=$(kubectl get secret jenkins-deployer-token -n shaohao-prod -o jsonpath='{.data.token}' | base64 -d)
CA_CERT=$(kubectl get secret jenkins-deployer-token -n shaohao-prod -o jsonpath='{.data.ca\.crt}')

# 获取API Server地址
API_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')

# 生成kubeconfig文件
cat > kubeconfig-jenkins.yaml <<EOF
apiVersion: v1
kind: Config
clusters:
- name: kubernetes
  cluster:
    certificate-authority-data: ${CA_CERT}
    server: ${API_SERVER}
contexts:
- name: jenkins-deployer@kubernetes
  context:
    cluster: kubernetes
    namespace: shaohao-prod
    user: jenkins-deployer
current-context: jenkins-deployer@kubernetes
users:
- name: jenkins-deployer
  user:
    token: ${TOKEN}
EOF

echo "✅ kubeconfig文件已生成:kubeconfig-jenkins.yaml"

验证kubeconfig

bash 复制代码
# 测试权限
kubectl --kubeconfig=kubeconfig-jenkins.yaml get pods -n shaohao-prod
# 应能正常执行

kubectl --kubeconfig=kubeconfig-jenkins.yaml get nodes
# 应返回:Error(没有权限,符合预期)

上传到Jenkins

复制代码
1. 将 kubeconfig-jenkins.yaml 下载到本地
2. 进入Jenkins "系统管理" → "凭据" → "添加凭据"
3. 类型选择 "Secret file"
4. 上传 kubeconfig-jenkins.yaml
5. ID填写:k8s-kubeconfig

4.4 创建镜像拉取Secret

在K8s集群中配置镜像仓库凭据:

bash 复制代码
# 创建Docker Registry Secret
kubectl create secret docker-registry ccr-secret \
  --docker-server=ccr.ccs.tencentyun.com \
  --docker-username=100012345678 \
  --docker-password=your-ccr-token \
  --namespace=shaohao-prod

# 验证
kubectl get secret ccr-secret -n shaohao-prod

4.5 准备Deployment清单模板

创建后端Deployment模板:

bash 复制代码
cat > backend-deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: shaohao-backend
  namespace: shaohao-prod
  labels:
    app: shaohao-backend
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: shaohao-backend
  template:
    metadata:
      labels:
        app: shaohao-backend
    spec:
      imagePullSecrets:
        - name: ccr-secret
      containers:
      - name: backend
        image: ccr.ccs.tencentyun.com/your-namespace/shaohao-backend:IMAGE_TAG
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: shaohao-backend-svc
  namespace: shaohao-prod
spec:
  selector:
    app: shaohao-backend
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
  type: ClusterIP
EOF

关键配置说明

  • IMAGE_TAG:占位符,Pipeline中会替换为实际版本号
  • RollingUpdate:滚动更新策略,零停机部署
  • imagePullSecrets:使用ccr-secret拉取私有镜像
  • livenessProbe/readinessProbe:健康检查,确保Pod就绪后才接收流量

第五章:编写Jenkins Pipeline

5.1 Pipeline基本结构

Jenkins Pipeline使用Groovy语法,分为以下阶段:
拉取代码
编译构建
构建镜像
推送镜像
部署到K8s
验证部署

Pipeline核心概念

  • agent:指定执行节点(any表示任意节点)
  • environment:定义环境变量
  • stages:包含多个stage
  • stage:单个构建阶段
  • steps:具体执行步骤

5.2 后端Pipeline完整示例

创建 Jenkinsfile-backend

groovy 复制代码
pipeline {
    agent any

    environment {
        // 镜像仓库配置
        REGISTRY = 'ccr.ccs.tencentyun.com'
        NAMESPACE = 'your-namespace'
        IMAGE_NAME = 'shaohao-backend'

        // 版本标签(使用构建号)
        IMAGE_TAG = "v1.0-${BUILD_NUMBER}"

        // K8s配置
        K8S_NAMESPACE = 'shaohao-prod'
        DEPLOYMENT_FILE = 'k8s/backend-deployment.yaml'
    }

    stages {
        stage('拉取代码') {
            steps {
                echo "开始拉取代码..."
                git branch: 'main',
                    credentialsId: 'gitee-credentials',
                    url: 'https://gitee.com/your-username/shaohao-backend.git'
                echo "代码拉取完成"
            }
        }

        stage('Maven编译打包') {
            steps {
                echo "开始Maven编译..."
                sh '''
                    mvn clean package -DskipTests
                    echo "编译完成,JAR包位置:"
                    ls -lh target/*.jar
                '''
            }
        }

        stage('构建Docker镜像') {
            steps {
                echo "开始构建Docker镜像..."
                script {
                    // 使用项目中的Dockerfile
                    docker.build("${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}")
                }
                echo "镜像构建完成:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
            }
        }

        stage('推送镜像到CCR') {
            steps {
                echo "开始推送镜像..."
                script {
                    docker.withRegistry("https://${REGISTRY}", 'ccr-credentials') {
                        docker.image("${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}").push()
                        // 同时打上latest标签
                        docker.image("${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}").push('latest')
                    }
                }
                echo "镜像推送完成"
            }
        }

        stage('部署到K8s') {
            steps {
                echo "开始部署到K8s集群..."
                script {
                    // 使用kubeconfig凭据
                    withKubeConfig([credentialsId: 'k8s-kubeconfig']) {
                        // 替换Deployment中的镜像标签
                        sh """
                            sed -i 's|IMAGE_TAG|${IMAGE_TAG}|g' ${DEPLOYMENT_FILE}
                            kubectl apply -f ${DEPLOYMENT_FILE}
                        """
                    }
                }
                echo "部署命令已执行"
            }
        }

        stage('验证部署状态') {
            steps {
                echo "验证Pod状态..."
                script {
                    withKubeConfig([credentialsId: 'k8s-kubeconfig']) {
                        sh """
                            echo "等待Pod就绪..."
                            kubectl rollout status deployment/shaohao-backend -n ${K8S_NAMESPACE} --timeout=5m

                            echo "当前Pod列表:"
                            kubectl get pods -n ${K8S_NAMESPACE} -l app=shaohao-backend

                            echo "部署历史:"
                            kubectl rollout history deployment/shaohao-backend -n ${K8S_NAMESPACE}
                        """
                    }
                }
                echo "✅ 部署成功!镜像版本:${IMAGE_TAG}"
            }
        }
    }

    post {
        success {
            echo "🎉 Pipeline执行成功!"
            echo "镜像:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
        }
        failure {
            echo "❌ Pipeline执行失败,请检查日志"
        }
        always {
            // 清理本地镜像(可选)
            sh "docker rmi ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} || true"
        }
    }
}

关键代码说明

  1. 环境变量管理

    groovy 复制代码
    IMAGE_TAG = "v1.0-${BUILD_NUMBER}"  // 每次构建生成唯一标签
  2. 凭据安全使用

    groovy 复制代码
    git credentialsId: 'gitee-credentials'  // Git凭据
    docker.withRegistry(..., 'ccr-credentials')  // 镜像仓库凭据
    withKubeConfig([credentialsId: 'k8s-kubeconfig'])  // K8s凭据
  3. 镜像标签替换

    bash 复制代码
    sed -i 's|IMAGE_TAG|${IMAGE_TAG}|g' ${DEPLOYMENT_FILE}
  4. 滚动更新验证

    bash 复制代码
    kubectl rollout status deployment/shaohao-backend --timeout=5m

5.3 前端Pipeline示例(简化版)

前端构建流程类似,主要区别在于使用npm和Nginx:

groovy 复制代码
pipeline {
    agent any

    environment {
        REGISTRY = 'ccr.ccs.tencentyun.com'
        NAMESPACE = 'your-namespace'
        IMAGE_NAME = 'shaohao-frontend'
        IMAGE_TAG = "v1.0-${BUILD_NUMBER}"
        K8S_NAMESPACE = 'shaohao-prod'
    }

    stages {
        stage('拉取代码') {
            steps {
                git branch: 'main',
                    credentialsId: 'gitee-credentials',
                    url: 'https://gitee.com/your-username/shaohao-frontend.git'
            }
        }

        stage('npm构建') {
            steps {
                sh '''
                    npm install --registry=https://registry.npmmirror.com
                    npm run build
                    ls -lh dist/
                '''
            }
        }

        stage('构建Nginx镜像') {
            steps {
                script {
                    // Dockerfile会将dist目录复制到Nginx
                    docker.build("${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}")
                }
            }
        }

        stage('推送并部署') {
            steps {
                script {
                    // 推送镜像
                    docker.withRegistry("https://${REGISTRY}", 'ccr-credentials') {
                        docker.image("${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}").push()
                    }

                    // 部署到K8s
                    withKubeConfig([credentialsId: 'k8s-kubeconfig']) {
                        sh """
                            sed -i 's|IMAGE_TAG|${IMAGE_TAG}|g' k8s/frontend-deployment.yaml
                            kubectl apply -f k8s/frontend-deployment.yaml
                            kubectl rollout status deployment/shaohao-frontend -n ${K8S_NAMESPACE}
                        """
                    }
                }
            }
        }
    }
}

第六章:执行部署与验证

6.1 创建Pipeline任务

  1. 进入Jenkins首页,点击"新建任务"

  2. 输入任务名称shaohao-backend-deploy

  3. 选择类型:Pipeline

  4. 配置Pipeline

    • 定义:Pipeline script from SCM
    • SCM:Git
    • 仓库URL:https://gitee.com/your-username/shaohao-backend.git
    • 凭据:选择gitee-credentials
    • 分支:*/main
    • 脚本路径:Jenkinsfile(或Jenkinsfile-backend
  5. 保存配置

6.2 触发构建

方式一:手动触发

复制代码
1. 进入任务页面
2. 点击"立即构建"
3. 查看构建进度(左侧构建历史)

方式二:Webhook自动触发(可选)

复制代码
1. Jenkins安装"Generic Webhook Trigger"插件
2. 任务配置中启用"Generic Webhook Trigger"
3. 在Gitee仓库设置中添加Webhook:
   URL: http://192.168.1.100:8080/generic-webhook-trigger/invoke
4. 推送代码后自动触发构建

6.3 查看构建日志

点击构建号 → Console Output,关键日志示例:

复制代码
[Pipeline] stage (拉取代码)
Cloning repository https://gitee.com/your-username/shaohao-backend.git
✅ Checkout completed

[Pipeline] stage (Maven编译打包)
[INFO] Building jar: /var/lib/jenkins/workspace/shaohao-backend-deploy/target/shaohao-backend-1.0.jar
✅ BUILD SUCCESS

[Pipeline] stage (构建Docker镜像)
Successfully built 3a2f5c8d9e1b
Successfully tagged ccr.ccs.tencentyun.com/your-namespace/shaohao-backend:v1.0-23

[Pipeline] stage (推送镜像到CCR)
v1.0-23: digest: sha256:abc123... size: 2841
✅ Push complete

[Pipeline] stage (部署到K8s)
deployment.apps/shaohao-backend configured
✅ Deployment updated

[Pipeline] stage (验证部署状态)
Waiting for deployment "shaohao-backend" rollout to finish: 1 old replicas are pending termination...
deployment "shaohao-backend" successfully rolled out
✅ 部署成功!镜像版本:v1.0-23

6.4 验证K8s部署状态

在K8s Master节点执行:

bash 复制代码
# 查看Pod状态
kubectl get pods -n shaohao-prod -l app=shaohao-backend
# 输出示例:
# NAME                               READY   STATUS    RESTARTS   AGE
# shaohao-backend-7d8f9c5b6d-4xk2p   1/1     Running   0          2m
# shaohao-backend-7d8f9c5b6d-9tn5l   1/1     Running   0          2m

# 查看Deployment
kubectl get deployment shaohao-backend -n shaohao-prod
# 输出:READY 2/2

# 查看滚动更新历史
kubectl rollout history deployment/shaohao-backend -n shaohao-prod
# 输出:
# REVISION  CHANGE-CAUSE
# 1         <none>
# 2         <none>

# 查看Pod详细信息
kubectl describe pod <pod-name> -n shaohao-prod
# 检查Events部分,确认镜像拉取成功

6.5 测试应用访问

bash 复制代码
# 方式一:通过Service访问(集群内)
kubectl run test-pod --image=busybox:1.28 --rm -it --restart=Never -- \
  wget -O- http://shaohao-backend-svc.shaohao-prod.svc.cluster.local:8080/actuator/health

# 方式二:通过Ingress访问(外部)
curl http://your-domain.com/api/health

# 方式三:端口转发测试
kubectl port-forward -n shaohao-prod svc/shaohao-backend-svc 8080:8080
curl http://localhost:8080/actuator/health

6.6 滚动更新验证

修改代码后再次构建,观察滚动更新过程:

bash 复制代码
# 实时监控Pod变化
kubectl get pods -n shaohao-prod -l app=shaohao-backend -w

# 输出示例(滚动更新过程):
# shaohao-backend-7d8f9c5b6d-4xk2p   1/1   Running       0     5m
# shaohao-backend-7d8f9c5b6d-9tn5l   1/1   Running       0     5m
# shaohao-backend-8c4a6d7e9f-x3n8m   0/1   Pending       0     0s   ← 新Pod创建
# shaohao-backend-8c4a6d7e9f-x3n8m   0/1   ContainerCreating   0     1s
# shaohao-backend-8c4a6d7e9f-x3n8m   1/1   Running       0     30s  ← 新Pod就绪
# shaohao-backend-7d8f9c5b6d-4xk2p   1/1   Terminating   0     6m   ← 旧Pod终止

零停机验证:在滚动更新期间持续访问服务,应无中断。


第七章:常见问题与优化

7.1 镜像拉取失败

问题 :Pod状态为ImagePullBackOff

排查步骤

bash 复制代码
# 1. 检查Secret是否存在
kubectl get secret ccr-secret -n shaohao-prod

# 2. 验证Secret内容
kubectl get secret ccr-secret -n shaohao-prod -o yaml

# 3. 在Worker节点手动拉取镜像
docker login ccr.ccs.tencentyun.com -u <username> -p <password>
docker pull ccr.ccs.tencentyun.com/your-namespace/shaohao-backend:v1.0-23

# 4. 检查Deployment是否引用了Secret
kubectl get deployment shaohao-backend -n shaohao-prod -o yaml | grep imagePullSecrets

解决方案:重新创建Secret或检查凭据是否过期。

7.2 kubectl权限问题

问题 :Pipeline报错Error from server (Forbidden)

解决方案

bash 复制代码
# 检查ServiceAccount权限
kubectl auth can-i create deployments --as=system:serviceaccount:shaohao-prod:jenkins-deployer -n shaohao-prod

# 如果返回no,重新应用RBAC配置
kubectl apply -f jenkins-rbac.yaml

7.3 构建缓存优化

Maven缓存

groovy 复制代码
// 在Pipeline中配置Maven本地仓库
sh 'mvn clean package -Dmaven.repo.local=/var/lib/jenkins/.m2/repository'

Docker层缓存

dockerfile 复制代码
# Dockerfile优化示例
FROM openjdk:17-slim
WORKDIR /app
# 先复制依赖文件(变化少)
COPY pom.xml .
RUN mvn dependency:go-offline
# 再复制源码(变化多)
COPY src ./src
RUN mvn package

7.4 Webhook自动触发

在Gitee仓库设置中添加Webhook:

复制代码
URL: http://192.168.1.100:8080/generic-webhook-trigger/invoke?token=your-secret-token
触发事件: Push

Jenkins任务配置:

groovy 复制代码
triggers {
    GenericTrigger(
        genericVariables: [
            [key: 'ref', value: '$.ref']
        ],
        causeString: 'Triggered by Gitee Push',
        token: 'your-secret-token',
        regexpFilterText: '$ref',
        regexpFilterExpression: 'refs/heads/main'
    )
}

7.5 多环境部署建议

使用不同的Namespace和配置文件:

groovy 复制代码
environment {
    K8S_NAMESPACE = "${params.ENVIRONMENT == 'prod' ? 'shaohao-prod' : 'shaohao-dev'}"
}

parameters {
    choice(name: 'ENVIRONMENT', choices: ['dev', 'prod'], description: '部署环境')
}

🎯 总结

本文从零开始搭建了一套完整的 Jenkins + Kubernetes CI/CD 自动化部署流水线,实现了:

Jenkins宿主机部署 ,避免Docker-in-Docker复杂配置

K8s RBAC权限管理 ,遵循最小权限原则

Pipeline自动化流程 ,从代码提交到部署上线全自动

滚动更新策略 ,实现零停机部署

镜像版本管理,支持快速回滚

参考资源

相关推荐
未定义.22115 小时前
第2篇:请求实战!覆盖GET/POST/请求头/参数全场景
java·python·http·servlet·自动化·jenkins
A-刘晨阳20 小时前
K8S 之 DaemonSet
运维·云原生·容器·kubernetes·daemonset
切糕师学AI1 天前
Kubernetes 中的 Volume(存储卷)
云原生·容器·kubernetes
ghostwritten1 天前
worker01 NotReady 排查与修复步骤
云原生·kubernetes
zmjjdank1ng2 天前
创建 NodePort 类型的 Service
运维·kubernetes
努力搬砖的咸鱼2 天前
Kubernetes Service :ClusterIP、NodePort、LoadBalancer
微服务·云原生·容器·架构·kubernetes
lGSrsEpqUxi2 天前
基于K-L级数展开法与FLAC3D的岩土体参数随机场模拟
jenkins
文静小土豆2 天前
K8s Gateway API 全面指南:从入门到实践
kubernetes·gateway
only_Klein2 天前
Ansible自动化部署Kubernetes
kubernetes·自动化·ansible
还是转转2 天前
像 K8S 一样部署 EC2:Launch Template + Auto Scaling 实践
云原生·容器·kubernetes