📋 目录
- [Jenkins与K8s CI/CD概述](#Jenkins与K8s CI/CD概述)
- 环境准备
- Jenkins基础配置
- K8s部署资源准备
- [编写Jenkins Pipeline](#编写Jenkins Pipeline)
- 执行部署与验证
- 常见问题与优化
🎯 引言
在微服务架构盛行的今天,如何高效地将代码从开发环境部署到生产环境,是每个团队都要面对的挑战。本文将手把手教你搭建一套基于 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
用户访问新版本
核心优势:
- Jenkins宿主机部署:直接访问系统工具(Docker、kubectl、Maven),避免Docker-in-Docker复杂配置
- K8s原生支持:滚动更新、自动扩缩容、健康检查、服务发现
- 镜像版本管理 :每次构建生成唯一标签(如
v1.0-23),支持快速回滚 - 统一流程:前后端使用相同的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:包含多个stagestage:单个构建阶段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"
}
}
}
关键代码说明:
-
环境变量管理:
groovyIMAGE_TAG = "v1.0-${BUILD_NUMBER}" // 每次构建生成唯一标签 -
凭据安全使用:
groovygit credentialsId: 'gitee-credentials' // Git凭据 docker.withRegistry(..., 'ccr-credentials') // 镜像仓库凭据 withKubeConfig([credentialsId: 'k8s-kubeconfig']) // K8s凭据 -
镜像标签替换:
bashsed -i 's|IMAGE_TAG|${IMAGE_TAG}|g' ${DEPLOYMENT_FILE} -
滚动更新验证:
bashkubectl 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任务
-
进入Jenkins首页,点击"新建任务"
-
输入任务名称 :
shaohao-backend-deploy -
选择类型:Pipeline
-
配置Pipeline:
- 定义:Pipeline script from SCM
- SCM:Git
- 仓库URL:
https://gitee.com/your-username/shaohao-backend.git - 凭据:选择
gitee-credentials - 分支:
*/main - 脚本路径:
Jenkinsfile(或Jenkinsfile-backend)
-
保存配置
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自动化流程 ,从代码提交到部署上线全自动
✅ 滚动更新策略 ,实现零停机部署
✅ 镜像版本管理,支持快速回滚
参考资源:
- Jenkins官方文档:https://www.jenkins.io/doc/
- Kubernetes官方文档:https://kubernetes.io/docs/
- Docker官方文档:https://docs.docker.com/