标签:DevOps, Docker, Jenkins, Kubernetes, CI/CD
简介:手把手教学如何搭建完整的CI/CD流水线,整合Docker容器化、Jenkins自动化构建、Kubernetes集群部署,实现从代码提交到生产环境的全自动发布流程,提升团队交付效率。
一、引言:为什么需要 DevOps 流水线?
在现代软件开发中,快速迭代、持续交付已成为企业竞争力的核心要素。传统的“瀑布式”开发模式已无法满足敏捷开发的需求,而 DevOps 理念应运而生——通过自动化工具链打通开发(Development)与运维(Operations)之间的壁垒,实现 CI/CD(持续集成 / 持续交付) 的全流程自动化。
本篇文章将带你深入实践一套完整的 Docker + Jenkins + Kubernetes 联合部署流水线,涵盖从代码提交、自动构建、镜像打包、推送至私有仓库,到在 Kubernetes 集群中自动部署上线的全过程。这套方案已被广泛应用于中大型互联网公司的生产环境中,具有高可扩展性、高可靠性与强安全性。
二、技术栈概览与架构设计
2.1 核心组件介绍
| 组件 | 作用 |
|---|---|
| Git | 代码版本管理,作为流水线触发源 |
| Jenkins | CI/CD 引擎,负责任务调度、脚本执行、构建与部署 |
| Docker | 容器化工具,用于打包应用及其依赖 |
| Kubernetes (k8s) | 容器编排平台,实现应用的弹性伸缩、负载均衡与高可用部署 |
| Harbor / Docker Registry | 私有镜像仓库,用于安全存储和分发镜像 |
| kubectl / Helm | Kubernetes 命令行工具与包管理器 |
2.2 架构图(文字描述)
[开发者] → [Git 仓库]
↓
[Jenkins 触发构建]
↓
[Docker 构建镜像]
↓
[推送镜像到 Harbor]
↓
[Helm Chart 打包 & 发布]
↓
[自动部署到 Kubernetes 集群]
↓
[应用运行于生产环境]
✅ 优势:
- 自动化减少人为错误
- 可视化构建日志便于排查问题
- 支持多环境(dev/test/prod)隔离部署
- 支持灰度发布、回滚机制
三、前置准备:环境搭建
3.1 环境要求
| 项目 | 推荐配置 |
|---|---|
| 操作系统 | Ubuntu 20.04 LTS / CentOS 7+ |
| Jenkins | v2.400+(推荐 LTS 版) |
| Docker | v20.10+ |
| Kubernetes | v1.25+(Minikube / K3s / EKS / AKS 等) |
| Git | v2.30+ |
| Harbor | v2.7+(支持 HTTPS 和 RBAC) |
⚠️ 建议使用独立服务器或虚拟机进行部署,避免资源冲突。
3.2 安装 Docker
# Ubuntu/Debian
sudo apt update
sudo apt install -y docker.io
# 启用开机自启
sudo systemctl enable docker
sudo systemctl start docker
# 添加当前用户到 docker 组(避免 sudo)
sudo usermod -aG docker $USER
newgrp docker
3.3 安装 Jenkins
# 安装 Java 11(Jenkins 依赖)
sudo apt install -y openjdk-11-jdk
# 安装 Jenkins
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo gpg --dearmor -o /usr/share/keyrings/jenkins.gpg
echo deb [signed-by=/usr/share/keyrings/jenkins.gpg] https://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list
sudo apt update
sudo apt install -y jenkins
# 启动 Jenkins
sudo systemctl enable jenkins
sudo systemctl start jenkins
📌 默认访问地址:
http://<your-server-ip>:8080
🔐 第一次启动需输入初始密码(位于
/var/lib/jenkins/secrets/initialAdminPassword)
3.4 安装 Kubernetes(以 Minikube 为例)
# 安装 kubectl
curl -LO "https://dl.k8s.io/release/v1.29.0/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# 安装 Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 启动 Minikube
minikube start --driver=docker --cpus=4 --memory=8192MB
验证安装:
kubectl version --short
minikube status
3.5 安装 Harbor(私有镜像仓库)
使用官方 Helm Chart 快速部署:
# 添加 Harbor Helm 仓库
helm repo add harbor https://helm.goharbor.io
helm repo update
# 创建命名空间
kubectl create namespace harbor
# 部署 Harbor
helm install harbor harbor/harbor \
--namespace harbor \
--set hostname=harbor.yourdomain.com \
--set http.port=80 \
--set https.port=443 \
--set expose.type=ingress \
--set expose.ingress.hosts.core=harbor.yourdomain.com \
--set expose.ingress.hosts.notary=notary.harbor.yourdomain.com \
--set externalURL=https://harbor.yourdomain.com \
--set adminPassword='Harbor123!' \
--set persistence.enabled=true \
--set persistence.size=10Gi
📝 替换
yourdomain.com为真实域名或内网 IP 地址,并确保 DNS 可解析。
✅ 访问
https://harbor.yourdomain.com,登录默认账号admin,密码为Harbor123!
四、Jenkins 配置:核心构建引擎
4.1 安装必要插件
登录 Jenkins Web UI 后,进入 Manage Jenkins > Plugins > Available,安装以下插件:
- Git Plugin
- Docker Pipeline Plugin
- Kubernetes Plugin
- Pipeline Plugin
- Credentials Binding Plugin
- Blue Ocean (可选)
4.2 配置全局凭据
4.2.1 添加 Docker Hub 凭据(示例)
进入 Manage Jenkins > Manage Credentials > System > Global credentials (unrestricted)
- Kind:
Username with password - Scope:
Global - Username:
your-dockerhub-username - Password:
your-dockerhub-password - ID:
dockerhub-credentials
💡 建议使用个人访问令牌(PAT)替代明文密码。
4.2.2 添加 Kubernetes API 凭据
若使用 Kubernetes Plugin,需配置 kubeconfig 文件:
# 获取 kubeconfig
kubectl config view --raw > ~/.kube/config
# 将内容复制并粘贴为 Jenkins 凭据
Kind: `File`
ID: `k8s-kubeconfig`
Content: (整个 .kube/config 内容)
4.2.3 添加 Harbor 凭据
同样方式添加 Harbor 登录凭证:
- Username:
admin - Password:
Harbor123! - ID:
harbor-credentials
五、创建 Jenkins Pipeline:完整流水线定义
5.1 示例项目结构
假设你有一个简单的 Node.js 应用:
project-root/
├── src/
│ └── app.js
├── package.json
├── Dockerfile
├── Jenkinsfile
└── charts/
└── myapp/
├── Chart.yaml
├── values.yaml
└── templates/
├── deployment.yaml
└── service.yaml
5.2 编写 Jenkinsfile(声明式流水线)
pipeline {
agent any
environment {
// 设置环境变量
DOCKER_IMAGE_NAME = 'myapp'
DOCKER_TAG = "${env.BUILD_ID}"
HARBOR_REGISTRY = 'harbor.yourdomain.com'
HARBOR_NAMESPACE = 'library'
IMAGE_NAME = "${HARBOR_REGISTRY}/${HARBOR_NAMESPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_TAG}"
// Helm 相关
HELM_CHART_DIR = 'charts/myapp'
RELEASE_NAME = 'myapp-release'
NAMESPACE = 'production'
}
stages {
stage('Checkout') {
steps {
script {
echo 'Cloning repository...'
checkout scm
}
}
}
stage('Build') {
steps {
script {
echo 'Building application...'
sh 'npm install'
sh 'npm run build'
}
}
}
stage('Test') {
steps {
script {
echo 'Running tests...'
sh 'npm test'
}
}
}
stage('Docker Build and Push') {
steps {
script {
echo 'Building Docker image...'
docker.build("${IMAGE_NAME}")
echo 'Pushing image to Harbor...'
docker.withRegistry("https://${HARBOR_REGISTRY}", 'harbor-credentials') {
docker.image("${IMAGE_NAME}").push()
}
}
}
}
stage('Deploy to Kubernetes') {
steps {
script {
echo 'Deploying using Helm...'
sh """
helm upgrade --install ${RELEASE_NAME} ${HELM_CHART_DIR} \\
--namespace ${NAMESPACE} \\
--set image.repository=${IMAGE_NAME} \\
--set image.tag=${DOCKER_TAG} \\
--create-namespace
"""
echo 'Waiting for rollout...'
sh """
kubectl rollout status deployment/${RELEASE_NAME} \\
--namespace ${NAMESPACE} \\
--timeout=600s
"""
}
}
}
}
post {
success {
echo '✅ Deployment succeeded!'
slackSend(channel: '#devops', message: "🎉 Deployment successful: ${IMAGE_NAME}")
}
failure {
echo '❌ Deployment failed!'
slackSend(channel: '#devops', message: "🚨 Deployment failed: ${BUILD_URL}")
}
}
}
📌 说明:
agent any表示可在任意节点执行environment定义全局变量,便于复用docker.withRegistry(...)是 Jenkins Docker Pipeline 插件的关键语法- 使用
helm upgrade --install实现幂等部署post块支持成功/失败通知(如 Slack)
六、Dockerfile 设计最佳实践
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制源码
COPY . .
# 构建前端(如果适用)
RUN npm run build
# 运行时阶段
FROM node:18-alpine AS runner
WORKDIR /app
# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
# 创建非 root 用户
RUN adduser -D -u 1001 appuser
USER appuser
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "dist/index.js"]
✅ 最佳实践:
- 使用多阶段构建(Multi-stage Build),减小镜像体积
- 不要使用
root用户运行服务- 使用
.dockerignore排除不必要的文件(如node_modules,.git)- 明确指定基础镜像版本(避免不稳定的 latest)
七、Helm Chart 高级配置
7.1 Chart.yaml
apiVersion: v2
name: myapp
version: 0.1.0
description: A simple Node.js app deployed via Helm
7.2 values.yaml
# Default values for myapp
replicaCount: 2
image:
repository: harbor.yourdomain.com/library/myapp
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 3000
resources:
limits:
memory: "128Mi"
cpu: "500m"
requests:
memory: "64Mi"
cpu: "250m"
env:
NODE_ENV: production
PORT: "3000"
7.3 deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
envFrom:
- configMapRef:
name: {{ include "myapp.fullname" . }}-configmap
resources:
{{- toYaml .Values.resources | nindent 8 }}
✅ 优势:
- 支持参数化部署(不同环境传入不同 values)
- 可通过
helm template预览生成的 YAML- 支持 Helm Hooks(Pre-install, Post-upgrade 等)
八、高级功能与优化建议
8.1 多环境部署(dev/test/prod)
通过 Helm Values 差异化管理:
# dev/values.yaml
replicaCount: 1
image:
tag: dev-${BUILD_ID}
# prod/values.yaml
replicaCount: 5
image:
tag: stable-${BUILD_ID}
在 Jenkinsfile 中动态切换:
def envConfig = 'dev' // 由参数决定
sh "helm upgrade --install ${RELEASE_NAME} ${HELM_CHART_DIR} --values charts/myapp/${envConfig}/values.yaml ..."
8.2 使用 Parameterized Build(参数化构建)
在 Jenkins 项目中启用参数化构建:
- String Parameter:
ENVIRONMENT(值:dev/test/prod) - Boolean Parameter:
SKIP_TEST(是否跳过测试)
然后在 Jenkinsfile 中使用:
parameters {
string(name: 'ENVIRONMENT', defaultValue: 'dev', description: 'Target environment')
booleanParam(name: 'SKIP_TEST', defaultValue: false, description: 'Skip testing phase')
}
stage('Test') {
when { expression { !params.SKIP_TEST } }
steps {
sh 'npm test'
}
}
8.3 灰度发布与滚动更新策略
修改 Helm Chart 中的 Deployment:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
配合 helm upgrade --wait --timeout=300s 确保平滑升级。
8.4 日志与监控集成
- 在 Jenkins Pipeline 中加入日志收集步骤:
sh 'kubectl logs deployment/myapp-release -n production' - 使用 Prometheus + Grafana 监控 Pod 状态。
- 集成 Loki 用于日志聚合。
8.5 安全加固措施
| 措施 | 说明 |
|---|---|
| 使用非 root 用户运行容器 | 减少权限攻击面 |
| 镜像签名(Cosign) | 保证镜像来源可信 |
| Harbor 仓库权限控制 | 按角色分配读写权限 |
| Jenkins 权限矩阵(RBAC) | 限制用户操作范围 |
| Pipeline 审计日志 | 记录每次构建行为 |
九、常见问题排查与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Jenkins 无法拉取镜像 | Docker 权限不足 | 检查 docker 用户组、重启服务 |
| Harbor 接收镜像失败 | HTTPS 证书问题 | 添加信任证书或禁用验证(仅测试) |
| Helm 部署超时 | Pod 启动慢或网络不通 | 检查 kubectl describe pod |
Jenkins 报错 No such file or directory |
路径错误或权限不足 | 检查工作目录与文件是否存在 |
| 构建失败但日志无明确信息 | 插件版本不兼容 | 升级 Jenkins 及相关插件 |
十、总结:打造可持续演进的 CI/CD 生态
通过本文的完整实践,我们已经构建了一套 基于 Docker + Jenkins + Kubernetes 的现代化 CI/CD 流水线。这套系统具备以下核心能力:
✅ 自动化:从代码提交到部署上线全程无需人工干预
✅ 可重复性:所有流程通过代码定义(Jenkinsfile、Helm Chart)
✅ 可观测性:构建日志、部署状态、监控指标一目了然
✅ 安全性:权限分离、镜像签名、私有仓库保障数据安全
✅ 可扩展性:支持多项目、多环境、多团队协作
🚀 下一步建议:
- 引入 Argo CD 做 GitOps,实现“声明式基础设施即代码”
- 使用 Tekton 替代 Jenkins,获得更现代化的 CI/CD 引擎
- 构建内部 DevOps 平台,提供自助式部署门户
十一、附录:一键脚本示例(初始化环境)
#!/bin/bash
# setup-devops.sh
echo "🚀 Starting DevOps environment setup..."
# 1. 安装 Docker
sudo apt update && sudo apt install -y docker.io
# 2. 安装 Jenkins
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo gpg --dearmor -o /usr/share/keyrings/jenkins.gpg
echo deb [signed-by=/usr/share/keyrings/jenkins.gpg] https://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list
sudo apt update && sudo apt install -y jenkins
# 3. 安装 Minikube & kubectl
curl -LO "https://dl.k8s.io/release/v1.29.0/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 4. 启动服务
sudo systemctl enable docker jenkins
sudo systemctl start docker jenkins
minikube start --driver=docker --cpus=4 --memory=8192MB
echo "✅ Environment ready!"
echo "Access Jenkins at http://localhost:8080"
echo "Run 'minikube dashboard' to view cluster status"
十二、结语
在数字化转型浪潮下,高效的 CI/CD 流水线不仅是技术能力的体现,更是组织敏捷性的基石。掌握 Docker + Jenkins + Kubernetes 的联合部署,意味着你掌握了现代云原生时代的核心生产力工具。
无论你是 DevOps 工程师、研发主管,还是希望提升团队效率的技术负责人,这套实战方案都值得你深入研究与落地实施。
记住:自动化不是终点,而是起点。真正的价值在于通过自动化释放人力,去专注于更高阶的创新与架构设计。
📌 立即行动:将本文中的 Jenkinsfile、Dockerfile、Helm Chart 复制到你的项目中,从今天开始构建属于你的自动化发布流水线!
📢 关注我,获取更多 DevOps 系列实战文章:自动化部署、GitOps、可观测性、混沌工程……

评论 (0)