从零构建云原生CI/CD流水线:Docker+K8S+Jenkins实战指南
大家好,我是专注于分享云原生与 DevOps 实战经验的技术博主。在团队协作开发中,你是否遇到过这样的困境:代码合并冲突频发、测试环境部署耗时费力、生产发布如履薄冰?这些问题背后,往往是缺乏一套自动化、标准化的软件交付流程。本文将为你带来一套从零到一的完整解决方案,通过整合 Docker、Kubernetes (K8S)、Jenkins 等核心工具,构建一个现代化的 CI/CD 流水线。无论你是刚接触容器化的新手,还是希望将现有项目进行云原生改造的开发者,都能从这篇实战指南中找到清晰的路径。我们将从最基础的 Docker 安装讲起,逐步深入到 Jenkins 流水线编排和 K8S 集群部署,最终实现代码提交到应用上线的全流程自动化。
1. 背景与核心概念:为什么需要 CI/CD 与容器化?
在深入动手之前,我们有必要理解这套技术栈要解决的根本问题,以及每个组件扮演的角色。这能帮助你在后续配置时,不仅知道“怎么做”,更明白“为什么这么做”。
1.1 传统软件交付的痛点与 DevOps 的兴起
在传统的软件开发模式中,开发、测试、运维团队往往各自为政。开发人员完成代码后,将程序打包成一个压缩包,附上一份可能已经过时的部署文档,扔给运维团队。运维人员则在生产服务器上手动安装依赖、配置环境、部署应用。这个过程充满了不确定性:开发环境能跑,测试环境可能就报错;测试环境通过了,生产环境又因为系统库版本不同而崩溃。这种“它在我机器上是好的”问题,严重拖慢了软件交付的速度和质量。
DevOps 文化正是为了打破这种壁垒而生,它强调开发(Dev)和运维(Ops)的紧密协作与自动化。而 CI/CD 是实现 DevOps 理念的关键技术实践。
1.2 CI/CD、Docker 与 Kubernetes 的核心价值
持续集成 (Continuous Integration, CI) :指开发人员频繁地(例如每天多次)将代码集成到共享主干。每次集成都通过自动化的构建和测试来验证,从而尽早发现集成错误。它的核心价值在于快速反馈,避免分支长期偏离主干导致的大量合并冲突。
持续交付/持续部署 (Continuous Delivery/Deployment, CD) :持续交付指在持续集成的基础上,将集成后的代码自动部署到更贴近真实环境的“类生产环境”。持续部署则更进一步,在通过所有测试后,自动将应用发布到生产环境。CD 的目标是让软件发布成为一个可预测、低风险、频繁进行的常规活动。
Docker :是实现环境一致性的基石。它将应用及其所有依赖(库、环境变量、配置文件)打包成一个标准化的单元——容器镜像。这个镜像可以在任何安装了 Docker 的机器上以完全相同的方式运行,彻底解决了“环境差异”问题。你可以把它理解为一个轻量级的、便携的软件集装箱。
Kubernetes (K8S) :当你的应用从单个容器扩展到成百上千个容器时,如何管理它们的生命周期、网络、存储和伸缩?Kubernetes 就是这个容器编排领域的王者。它负责容器的调度、部署、扩缩容、负载均衡和自愈,让你能像管理单个应用一样管理庞大的分布式系统。
Jenkins :是 CI/CD 流程的“大脑”和“指挥中心”。它是一个开源的自动化服务器,通过插件体系可以连接 Git、Maven、Docker、K8S 等几乎所有工具。我们通过编写 Jenkins Pipeline(流水线脚本),定义从代码拉取、编译、测试、构建镜像到部署的完整工作流。
简单来说,这套组合拳的工作流是:开发者提交代码到 Git -> Jenkins 被触发 -> 拉取代码、编译、运行测试 -> 通过后,使用 Docker 构建镜像 -> 将镜像推送到仓库 -> 最后通过 Kubernetes 将新版本应用滚动更新到集群中。整个过程无需人工干预,高效且可靠。
2. 环境准备与版本说明
工欲善其事,必先利其器。为了完成本次实战,你需要准备以下环境。我将以一台 Ubuntu 22.04 LTS 的云服务器或虚拟机作为演示环境,这也是目前最主流和稳定的选择之一。
核心环境清单:
- 操作系统 :Ubuntu 22.04 LTS (x86_64)
- 容器运行时 :Docker Engine 24.0+
- 容器编排 :Kubernetes (使用 Minikube 搭建单节点集群,用于学习和测试)
- CI/CD 服务器 :Jenkins 2.4xx (LTS 版本)
- 构建工具 :OpenJDK 17, Maven 3.8+
- 代码质量 :SonarQube (可选,用于静态代码分析)
- 版本控制 :Git
重要说明 :本文提供的安装命令和配置在 Ubuntu 22.04 上测试通过。如果你使用 CentOS、Rocky Linux 或其他发行版,部分包管理命令(如 apt 需改为 yum 或 dnf )和细节可能略有不同,请参考对应官方文档进行调整。所有涉及版本号的地方,请以安装时官方仓库提供的最新稳定版为准。
3. 基础环境搭建:从 Linux 到 Docker
我们的旅程从最基础的 Linux 操作和 Docker 安装开始。即使你是零基础,跟着步骤也能顺利完成。
3.1 Linux 基础与准备工作
首先,通过 SSH 连接到你的 Ubuntu 服务器。确保系统包列表是最新的。
# 更新软件包索引
sudo apt update
# 升级所有已安装的软件包(可选,但推荐)
sudo apt upgrade -y
# 安装一些常用的工具,如 Vim、curl、wget、net-tools
sudo apt install -y vim curl wget net-tools
接下来,我们需要安装 Java,因为 Jenkins 是基于 Java 开发的。
# 安装 OpenJDK 17 (Jenkins 推荐版本)
sudo apt install -y openjdk-17-jdk
# 验证安装
java -version
# 预期输出应包含 “openjdk version “17.0.x”
3.2 Docker 安装与配置
Docker 的安装非常 straightforward。我们将使用 Docker 官方提供的便捷脚本进行安装,这也是官方推荐的方式。
# 1. 卸载旧版本 Docker(如果存在)
sudo apt remove -y docker docker-engine docker.io containerd runc
# 2. 安装依赖包,允许 apt 通过 HTTPS 使用仓库
sudo apt install -y ca-certificates curl gnupg lsb-release
# 3. 添加 Docker 的官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 4. 设置 Docker 稳定版仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 5. 更新 apt 包索引并安装 Docker Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 6. 验证 Docker 安装是否成功
sudo docker run hello-world
如果看到 “Hello from Docker!” 的消息,说明 Docker 已经安装并运行成功。
配置 Docker 用户组(非常重要) :默认情况下,运行 Docker 命令需要 sudo 权限。为了方便,我们将当前用户加入 docker 用户组,这样以后就可以直接使用 docker 命令了。
# 将当前用户加入 docker 组
sudo usermod -aG docker $USER
# 重新登录或使用以下命令使组更改生效
newgrp docker
# 再次验证,此时应无需 sudo
docker run hello-world
配置 Docker 镜像加速器(国内用户必做) :从 Docker Hub 拉取镜像速度可能较慢,我们可以配置国内镜像加速器。
# 创建或修改 Docker 守护进程配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
“registry-mirrors”: [“https://docker.mirrors.ustc.edu.cn”, “https://hub-mirror.c.163.com”],
“exec-opts”: [“native.cgroupdriver=systemd”],
“log-driver”: “json-file”,
“log-opts”: {
“max-size”: “100m”
},
“storage-driver”: “overlay2”
}
EOF
# 重新加载配置并重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
# 检查加速器是否生效
docker info | grep -A 1 ‘Registry Mirrors’
3.3 Docker 核心概念与常用命令速查
安装完成后,我们快速过一下 Docker 最核心的概念和命令,为后续使用打下基础。
- 镜像 (Image) :一个只读的模板,用于创建容器。例如
ubuntu:22.04,nginx:alpine。 - 容器 (Container) :镜像的运行实例。你可以创建、启动、停止、删除容器。
- 仓库 (Registry) :存放镜像的地方,如 Docker Hub。
常用命令:
# 镜像相关
docker pull nginx:alpine # 拉取镜像
docker images # 列出本地镜像
docker rmi <image_id> # 删除镜像
# 容器相关
docker run -d -p 80:80 --name my-nginx nginx:alpine # 运行容器 (-d 后台, -p 端口映射)
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器(包括已停止的)
docker stop <container_id> # 停止容器
docker start <container_id> # 启动已停止的容器
docker rm <container_id> # 删除容器
docker logs <container_id> # 查看容器日志
docker exec -it <container_id> /bin/bash # 进入容器内部
# 构建镜像 (需要 Dockerfile)
docker build -t my-app:1.0 .
4. Jenkins 安装与基础配置
Jenkins 将作为我们自动化流水线的中枢。我们将把它安装在同一台服务器上。
4.1 安装 Jenkins
Jenkins 提供了稳定的 Debian/Ubuntu 仓库,安装非常方便。
# 1. 添加 Jenkins 仓库的密钥
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
/usr/share/keyrings/jenkins-keyring.asc > /dev/null
# 2. 添加 Jenkins 仓库
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
# 3. 更新并安装 Jenkins
sudo apt update
sudo apt install -y jenkins
# 4. 启动 Jenkins 并设置开机自启
sudo systemctl start jenkins
sudo systemctl enable jenkins
# 5. 检查 Jenkins 状态
sudo systemctl status jenkins
如果状态显示为 active (running) ,说明 Jenkins 服务已成功启动。
4.2 初始化 Jenkins
Jenkins 默认运行在 8080 端口。我们需要配置服务器的安全组或防火墙,允许访问该端口。
# 如果使用 UFW 防火墙(Ubuntu 默认)
sudo ufw allow 8080
sudo ufw status verbose
在浏览器中访问: http://<你的服务器IP地址>:8080 。 你会看到 “Unlock Jenkins” 页面,需要输入初始管理员密码。这个密码在服务器的日志文件中。
# 获取初始管理员密码
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
将输出的密码粘贴到浏览器中,点击“继续”。
接下来,选择“安装推荐的插件”。Jenkins 会自动安装一套最常用的插件,包括 Git、Pipeline 等,这个过程可能需要几分钟。
插件安装完成后,会提示你创建第一个管理员用户。 强烈建议创建一个新用户 ,而不是继续使用初始的 admin 账户。填写用户名、密码、全名和邮箱后,点击“保存并完成”。
最后,配置 Jenkins URL,一般保持默认的 http://<你的IP>:8080 即可,点击“保存并完成”。至此,Jenkins 安装初始化完毕。
4.3 安装必备插件并配置工具
进入 Jenkins 主面板后,我们需要安装一些本次实战必需的插件。
- 点击左侧菜单 “Manage Jenkins” -> “Plugins” -> “Available plugins”。
- 在搜索框中搜索并勾选以下插件:
- Docker Pipeline :用于在 Pipeline 中与 Docker 交互。
- Kubernetes :用于连接 K8S 集群(如果使用 Jenkins Agent 在 K8S 中运行)。
- GitHub Integration 或 Git :用于从 Git 仓库拉取代码。
- Pipeline: GitHub Groovy Libraries :增强 Pipeline 功能。
- SonarQube Scanner (可选):用于集成 SonarQube 代码分析。
- 点击“Install without restart”,等待安装完成。
接下来,配置全局工具。点击 “Manage Jenkins” -> “Tools”。
- JDK :添加一个 JDK 安装,命名为 “openjdk-17”,JAVA_HOME 路径通常为
/usr/lib/jvm/java-17-openjdk-amd64。 - Maven :添加一个 Maven 安装,命名为 “maven-3.8”,可以勾选“自动安装”。
- Git :确保 Git 可执行文件路径正确,通常是
/usr/bin/git。
保存配置。
5. Kubernetes (Minikube) 单机集群搭建
在生产环境中,Kubernetes 集群通常由多台机器组成。为了学习和测试,我们使用 Minikube 在单机上快速搭建一个功能完整的 K8S 集群。
5.1 安装 kubectl 和 Minikube
kubectl 是操作 Kubernetes 集群的命令行工具。
# 安装 kubectl
curl -LO “https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl”
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client --output=yaml
接下来安装 Minikube。Minikube 需要虚拟机驱动,我们使用 Docker 作为驱动,这也是最轻便的方式。
# 安装 Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 启动 Minikube 集群,使用 Docker 驱动
minikube start --driver=docker
# 检查集群状态
minikube status
如果输出显示 host , kubelet , apiserver 都是 Running 状态,说明集群启动成功。
5.2 验证 K8S 集群并部署示例应用
让我们验证一下集群,并部署一个简单的 Nginx 应用。
# 查看集群节点(应该只有一个 minikube 节点)
kubectl get nodes
# 查看所有命名空间下的 Pod
kubectl get pods -A
# 部署一个 Nginx Deployment
kubectl create deployment nginx-demo --image=nginx:alpine
# 将 Deployment 暴露为 NodePort 类型的 Service
kubectl expose deployment nginx-demo --type=NodePort --port=80
# 查看 Service,获取访问端口
kubectl get svc nginx-demo
# 输出中会有一个端口,例如 80:3xxxx/TCP,后面的 3xxxx 就是 NodePort
# 使用 minikube 生成访问 URL
minikube service nginx-demo --url
复制最后命令输出的 URL 到浏览器,你应该能看到 Nginx 的欢迎页面。这证明你的 K8S 集群工作正常。
6. 实战:构建完整的 CI/CD 流水线
现在,所有基础设施都已就位。我们将创建一个简单的 Spring Boot 应用,并为其打造一个完整的 CI/CD 流水线。流程如下:代码推送至 Git -> Jenkins 自动构建 -> 运行单元测试 -> 静态代码检查(SonarQube)-> 构建 Docker 镜像 -> 推送至镜像仓库 -> 更新 K8S 部署。
6.1 准备示例项目与 Git 仓库
首先,在本地或服务器上创建一个简单的 Spring Boot 项目。这里我们使用 Spring Initializr 快速生成。
# 使用 curl 从 start.spring.io 生成项目
curl https://start.spring.io/starter.zip -o demo-app.zip \
-d type=maven-project \
-d language=java \
-d bootVersion=3.1.5 \
-d baseDir=cicd-demo \
-d groupId=com.example \
-d artifactId=cicd-demo \
-d name=cicd-demo \
-d description=Demo+project+for+CI/CD \
-d packageName=com.example.cicd \
-d packaging=jar \
-d javaVersion=17 \
-d dependencies=web
unzip demo-app.zip -d .
cd cicd-demo
项目结构大致如下:
cicd-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/com/example/cicd/
│ │ │ └── CicdDemoApplication.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
│ └── java/com/example/cicd/
│ └── CicdDemoApplicationTests.java
我们添加一个简单的 REST 接口和对应的测试。
文件: src/main/java/com/example/cicd/HelloController.java
package com.example.cicd;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping(“/hello”)
public String sayHello() {
return “Hello from CI/CD Pipeline!”;
}
}
文件: src/test/java/com/example/cicd/HelloControllerTest.java
package com.example.cicd;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HelloController.class)
public class HelloControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHelloEndpoint() throws Exception {
mockMvc.perform(get(“/hello”))
.andExpect(status().isOk())
.andExpect(content().string(“Hello from CI/CD Pipeline!”));
}
}
接下来,在项目根目录创建两个关键文件: Dockerfile 和 Jenkinsfile 。
文件: Dockerfile
# 使用 OpenJDK 17 作为基础镜像
FROM openjdk:17-jdk-slim AS builder
# 设置工作目录
WORKDIR /app
# 将 Maven 包装器和 pom.xml 复制到镜像中
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
# 下载项目依赖(利用 Docker 缓存层,如果 pom.xml 未改变,则跳过)
RUN ./mvnw dependency:go-offline -B
# 复制源代码并打包
COPY src src
RUN ./mvnw clean package -DskipTests
# 第二阶段:运行阶段
FROM openjdk:17-jdk-slim
WORKDIR /app
# 从构建阶段复制打好的 jar 包
COPY --from=builder /app/target/*.jar app.jar
# 暴露端口
EXPOSE 8080
# 启动应用
ENTRYPOINT [“java”, “-jar”, “/app/app.jar”]
文件: Jenkinsfile (声明式流水线)
pipeline {
agent any // 使用任何可用的 Jenkins Agent
tools {
maven ‘maven-3.8’ // 使用在 Jenkins 全局工具中配置的 Maven
jdk ‘openjdk-17’ // 使用在 Jenkins 全局工具中配置的 JDK
}
environment {
// 定义环境变量,请根据实际情况修改
DOCKER_REGISTRY = ‘your-dockerhub-username’ // 或私有仓库地址
DOCKER_IMAGE_NAME = “cicd-demo”
KUBE_CONFIG = credentials(‘k8s-config’) // 在 Jenkins 中配置的 K8S kubeconfig 凭据 ID
}
stages {
stage(‘Checkout’) {
steps {
// 从 Git 仓库拉取代码
git branch: ‘main’, url: ‘https://github.com/your-username/your-repo.git’
}
}
stage(‘Build & Unit Test’) {
steps {
// 清理、编译并运行单元测试
sh ‘mvn clean compile’
sh ‘mvn test’
}
post {
always {
// 无论成功失败,都归档测试报告(可选)
junit ‘target/surefire-reports/*.xml’
}
}
}
stage(‘SonarQube Analysis’) {
steps {
// 使用 SonarQube Scanner 进行代码质量分析
withSonarQubeEnv(‘sonarqube-server’) { // ‘sonarqube-server’ 是在 Jenkins 系统配置中定义的 SonarQube 服务器名称
sh ‘mvn sonar:sonar’
}
}
}
stage(‘Build Docker Image’) {
steps {
script {
// 构建 Docker 镜像,标签使用构建编号
dockerImage = docker.build(“${DOCKER_REGISTRY}/${DOCKER_IMAGE_NAME}:${BUILD_NUMBER}”)
}
}
}
stage(‘Push Docker Image’) {
steps {
script {
// 登录 Docker 仓库(需先在 Jenkins 中添加 Docker Hub 用户名密码凭据,ID 为 ‘dockerhub-cred’)
docker.withRegistry(‘https://index.docker.io/v1/’, ‘dockerhub-cred’) {
dockerImage.push()
// 同时打上 latest 标签
dockerImage.push(‘latest’)
}
}
}
}
stage(‘Deploy to K8S’) {
steps {
script {
// 使用 kubectl 配置更新 K8S 部署
// 假设我们有一个 deployment.yaml 文件在仓库中
sh “““
# 设置 kubectl 配置(从凭据中读取)
echo “\$KUBE_CONFIG” > /tmp/kubeconfig.yaml
export KUBECONFIG=/tmp/kubeconfig.yaml
# 使用 sed 替换 deployment.yaml 中的镜像标签
sed -i ‘s|IMAGE_PLACEHOLDER|${DOCKER_REGISTRY}/${DOCKER_IMAGE_NAME}:${BUILD_NUMBER}|g’ k8s/deployment.yaml
# 应用部署
kubectl apply -f k8s/deployment.yaml
# 检查部署状态
kubectl rollout status deployment/cicd-demo -n default
“““
}
}
}
}
post {
success {
echo ‘Pipeline succeeded! The new version is now deployed.’
// 可以在这里添加通知,如发送邮件、Slack 消息等
}
failure {
echo ‘Pipeline failed! Check the logs for details.’
}
}
}
文件: k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cicd-demo
namespace: default
labels:
app: cicd-demo
spec:
replicas: 2
selector:
matchLabels:
app: cicd-demo
template:
metadata:
labels:
app: cicd-demo
spec:
containers:
- name: cicd-demo
image: IMAGE_PLACEHOLDER # Jenkinsfile 中的 sed 命令会替换这里
ports:
- containerPort: 8080
resources:
requests:
memory: “256Mi”
cpu: “250m”
limits:
memory: “512Mi”
cpu: “500m”
---
apiVersion: v1
kind: Service
metadata:
name: cicd-demo-service
spec:
selector:
app: cicd-demo
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: NodePort
将以上所有文件提交到你的 Git 仓库(如 GitHub、GitLab 或 Gitee)。
6.2 在 Jenkins 中配置流水线任务
- 创建 Pipeline 任务 :在 Jenkins 首页点击“新建任务”,输入任务名称(如
cicd-demo-pipeline),选择“流水线”,点击“确定”。 - 配置流水线 :在任务配置页面,滚动到“流水线”部分。
- 定义 :选择“Pipeline script from SCM”。这告诉 Jenkins 从源代码仓库中读取
Jenkinsfile。 - SCM :选择 “Git”。
- Repository URL :填写你的 Git 仓库地址。
- Credentials :如果你的仓库是私有的,需要添加一个“用户名与密码”类型的凭据,包含你的 Git 账号信息。
- 分支 :
*/main。 - 脚本路径 :保持默认的
Jenkinsfile。
- 定义 :选择“Pipeline script from SCM”。这告诉 Jenkins 从源代码仓库中读取
- 添加必要的凭据 :
- Docker Hub 凭据 :进入 “Manage Jenkins” -> “Credentials” -> “System” -> “Global credentials” -> “Add Credentials”。选择“Username with password”,输入你的 Docker Hub 用户名和密码,ID 设为
dockerhub-cred。 - Kubeconfig 凭据 :同样位置,添加一个“Secret file”类型的凭据,上传你的
~/.kube/config文件(从 Minikube 环境复制),ID 设为k8s-config。 - SonarQube Token (如果使用):添加一个“Secret text”类型的凭据,填入从 SonarQube 获取的 Token,ID 设为
sonarqube-token。并在 “Manage Jenkins” -> “Configure System” 中添加 SonarQube 服务器配置。
- Docker Hub 凭据 :进入 “Manage Jenkins” -> “Credentials” -> “System” -> “Global credentials” -> “Add Credentials”。选择“Username with password”,输入你的 Docker Hub 用户名和密码,ID 设为
- 保存并运行 :点击“保存”,回到任务页面,点击“立即构建”。Jenkins 会开始执行流水线,你可以在“阶段视图”中实时看到每个阶段的执行状态和日志。
6.3 验证部署结果
流水线执行成功后,我们可以验证应用是否已部署到 K8S 集群。
# 查看 Deployment 状态
kubectl get deployment cicd-demo
# 查看 Pod 状态
kubectl get pods -l app=cicd-demo
# 查看 Service 并获取访问端口
kubectl get svc cicd-demo-service
# 使用 minikube 访问服务
minikube service cicd-demo-service --url
访问输出的 URL,并在后面加上 /hello 路径,你应该能看到 “Hello from CI/CD Pipeline!” 的响应。
7. 常见问题与排查思路
在搭建和运行过程中,你可能会遇到一些问题。这里列出一些常见问题及其解决方法。
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
| Docker 命令需要 sudo | 当前用户未加入 docker 用户组。 |
执行 sudo usermod -aG docker $USER 后 重新登录 或执行 newgrp docker 。 |
| Jenkins 无法启动或 8080 端口无法访问 | 1. Jenkins 服务未启动。 2. 防火墙/安全组未开放 8080 端口。 3. 端口被占用。 |
1. sudo systemctl status jenkins 检查状态。 2. 检查 sudo ufw status 或云服务器安全组规则。 3. `sudo netstat -tlnp |
| Pipeline 拉取 Git 代码失败 | 1. 仓库地址错误。 2. 凭据无效或权限不足。 3. 网络问题。 |
1. 检查仓库 URL。 2. 在 Jenkins 凭据页面重新配置 Git 凭据。 3. 在 Jenkins 服务器上手动执行 git clone 测试连通性。 |
| Maven 构建失败 | 1. pom.xml 依赖错误。 2. 网络问题无法下载依赖。 3. JDK 版本不匹配。 |
1. 检查 Jenkins 控制台输出,看具体错误信息。 2. 配置 Maven 镜像仓库 ( settings.xml )。 3. 确认 Jenkins 全局工具中配置的 JDK 版本与项目要求一致。 |
| Docker 构建镜像失败 | 1. Dockerfile 语法错误。 2. 基础镜像拉取失败。 3. 构建上下文路径不对。 |
1. 在本地使用 docker build -t test . 测试 Dockerfile 。 2. 检查网络或配置 Docker 镜像加速器。 3. 确保 docker build 命令在正确的目录下执行。 |
| 推送镜像到仓库失败 | 1. 未登录 Docker 仓库。 2. 凭据错误。 3. 镜像标签命名不符合仓库规则。 |
1. 确认 Jenkins 中配置了正确的 Docker 仓库凭据。 2. 在服务器上手动 docker login 测试。 3. 镜像名通常为 username/repository:tag 。 |
| kubectl 部署失败 | 1. kubeconfig 文件错误或过期。 2. 没有对应命名空间的权限。 3. deployment.yaml 文件语法错误。 |
1. 检查 Jenkins 中上传的 kubeconfig 文件内容是否正确(可用 kubectl get nodes 测试)。 2. 检查 RBAC 权限。 3. 使用 kubectl apply --dry-run=client -f deployment.yaml 验证 YAML 语法。 |
Pod 一直处于 Pending 或 CrashLoopBackOff 状态 |
1. 集群资源不足。 2. 镜像拉取失败。 3. 应用启动失败(如端口冲突、配置错误)。 |
1. kubectl describe pod <pod-name> 查看详细事件。 2. kubectl logs <pod-name> 查看容器日志。 3. minikube ssh 进入节点,用 docker ps 和 docker logs 进一步排查。 |
| SonarQube 扫描失败 | 1. SonarQube 服务器未启动或无法访问。 2. Token 无效。 3. 项目配置(如 sonar-project.properties )缺失。 |
1. 确认 SonarQube 服务 ( http://<ip>:9000 ) 可访问。 2. 检查 Jenkins 中配置的 SonarQube Token 凭据。 3. 在项目根目录添加正确的 sonar-project.properties 文件。 |
8. 最佳实践与工程建议
掌握了基础流程后,以下建议能帮助你将这套流水线应用到更严肃的生产环境中。
- 使用 Jenkins Shared Library :当你有多个项目使用相似的流水线时,将公共逻辑(如构建、推送镜像、部署)抽取到 Shared Library 中,可以极大减少
Jenkinsfile的重复和维护成本。 - Pipeline 代码化与版本控制 :始终将
Jenkinsfile放在项目根目录,并随代码一起进行版本控制。这是“Pipeline as Code”的核心,保证了流水线定义的可追溯性和可重复性。 - 细粒度的权限与凭据管理 :不要在
Jenkinsfile中硬编码密码或密钥。始终使用 Jenkins 的凭据管理功能,并通过credentials()方法在流水线中引用。为不同项目或团队配置不同的 Jenkins 角色和权限。 - 构建高效的 Docker 镜像 :
- 使用多阶段构建 :如示例所示,可以显著减小最终镜像体积。
- 合理利用缓存 :将不经常变动的层(如依赖安装)放在
Dockerfile前面。 - 使用非 root 用户运行容器 :在
Dockerfile中创建专用用户,增强安全性。 - 选择合适的基础镜像 :优先选择官方、轻量级(如
-slim,-alpine)的镜像。
- Kubernetes 部署策略 :
- 使用
Deployment而非直接创建Pod:Deployment提供了声明式更新、回滚和副本管理。 - 配置资源请求和限制 :为每个容器设置
requests和limits,避免资源竞争,帮助调度器做出最佳决策。 - 使用
ConfigMap和Secret管理配置 :将应用配置与镜像分离,提高灵活性。 - 实现健康检查 :配置
livenessProbe和readinessProbe,让 K8S 能感知应用状态,实现自愈。
- 使用
- 流水线稳定性与监控 :
- 添加超时和重试机制 :在 Pipeline 的
options块中设置timeout,对可能失败的步骤(如网络请求)添加重试逻辑。 - 实施人工审批门禁 :在部署到生产环境前,通过
input步骤加入人工确认环节。 - 集成通知机制 :在流水线的
post阶段,根据成功或失败状态,集成邮件、Slack、钉钉等通知。 - 监控流水线性能 :关注构建时长,优化慢步骤。定期清理旧的构建记录和 Docker 镜像,释放磁盘空间。
- 添加超时和重试机制 :在 Pipeline 的
- 安全考虑 :
- 定期更新基础镜像和依赖 :扫描镜像中的漏洞,使用
docker scan或集成 Trivy、Clair 等工具到流水线中。 - 最小权限原则 :为 Jenkins Agent、Docker Daemon、K8S ServiceAccount 分配完成任务所需的最小权限。
- 保护敏感数据 :绝不将密码、密钥等写入日志或代码。使用 K8S
Secret或专业的密钥管理服务。
- 定期更新基础镜像和依赖 :扫描镜像中的漏洞,使用
从 Docker 容器化到 Kubernetes 编排,再到 Jenkins 自动化流水线,我们完成了一个现代云原生应用交付闭环的搭建。这套组合不仅能提升开发效率,更能保障交付质量与稳定性。技术的道路很长,下一步你可以探索 Helm 图表来管理更复杂的 K8S 应用,引入 Argo CD 实现 GitOps,或者搭建高可用的 Jenkins 集群。最重要的是,动手实践,将这套流程应用到你的实际项目中,并根据团队需求不断调整和优化。如果在实践中遇到任何问题,欢迎在评论区交流探讨。
更多推荐



所有评论(0)