K8S 的项目发布方式
大约 11 分钟约 3262 字
K8S 的项目发布方式
简介
在 Kubernetes 中,应用的更新和发布是运维工作的核心环节。Kubernetes 提供了多种发布策略,包括滚动更新(Rolling Update)、重建(Recreate)、蓝绿发布(Blue/Green)、金丝雀发布(Canary)等。不同的发布策略适用于不同的场景,选择合适的策略可以在保证服务可用性的同时,安全地完成应用版本迭代。
特点
发布策略概览
| 发布策略 | 停机时间 | 资源消耗 | 回滚难度 | 风险控制 | 适用场景 |
|---|---|---|---|---|---|
| 滚动更新 | 无 | 低 | 中等 | 中等 | 日常版本更新 |
| 重建更新 | 有 | 低 | 简单 | 低 | 开发/测试环境 |
| 蓝绿发布 | 无 | 高(双倍) | 简单 | 低 | 需要快速切换的场景 |
| 金丝雀发布 | 无 | 中等 | 简单 | 高 | 生产环境谨慎发布 |
滚动更新(Rolling Update)
简介
滚动更新是 Kubernetes Deployment 的默认更新策略。它通过逐步替换旧版本的 Pod 来完成更新,在更新过程中始终保持一定数量的可用 Pod,实现零停机部署。
工作原理
配置示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: rolling-deployment
labels:
app: rolling-demo
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新时最多多创建 1 个 Pod(可以是百分比如 25%)
maxUnavailable: 0 # 更新时最多允许 0 个 Pod 不可用
selector:
matchLabels:
app: rolling-pod
template:
metadata:
labels:
app: rolling-pod
spec:
containers:
- name: app-container
image: registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v1:v1
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthCheck
port: 80
initialDelaySeconds: 5
periodSeconds: 5操作命令
# 创建 Deployment
kubectl apply -f rolling-deployment.yaml
# 查看部署状态
kubectl get deployment rolling-deployment -w
# 更新镜像版本(触发滚动更新)
kubectl set image deployment/rolling-deployment \
app-container=registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v2:v2 \
--record
# 查看滚动更新状态
kubectl rollout status deployment/rolling-deployment
# 持续访问测试
while sleep 0.2; do curl -s http://10.110.155.221 | grep "Deploy Version"; echo ""; done
# 查看 Deployment 配置
kubectl describe deployment rolling-deployment滚动更新参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
| maxSurge | 更新过程中超出期望副本数的最大 Pod 数量 | 1 或 25% |
| maxUnavailable | 更新过程中允许不可用的最大 Pod 数量 | 0 或 25% |
重建更新(Recreate)
简介
Recreate 策略先终止所有旧版本 Pod,然后创建新版本 Pod。在更新过程中会有短暂的停机时间。
配置示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: recreate-deployment
spec:
replicas: 3
strategy:
type: Recreate # 重建更新策略
selector:
matchLabels:
app: recreate-pod
template:
metadata:
labels:
app: recreate-pod
spec:
containers:
- name: app-container
image: registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v1:v1
ports:
- containerPort: 80关键知识点
- 部署类主题的核心不是“装成功”,而是“稳定运行、可排障、可回滚”。
- 同一个服务通常至少要关注版本、目录、端口、权限、数据、日志和备份。
- Linux 问题经常跨越系统层、网络层、服务层和应用层。
- Kubernetes 主题必须同时看资源对象、调度行为、网络暴露和配置分发。
项目落地视角
- 把安装步骤补成可重复执行的清单,必要时写成脚本或配置文件。
- 把配置目录、数据目录、日志目录和挂载点明确拆开。
- 上线前检查防火墙、SELinux、时区、磁盘、系统服务和健康检查。
- 上线前检查镜像、命名空间、探针、资源限制、Service/Ingress 和配置来源。
常见误区
- 使用 latest 或未固定版本,导致环境不可复现。
- 只验证启动成功,不验证持久化、开机自启和故障恢复。
- 遇到问题先改配置而不是先看日志和依赖链路。
- 只会 apply YAML,不理解对象之间的依赖关系。
进阶路线
- 继续补齐 systemd、性能监控、安全加固和备份恢复。
- 把单机操作升级成 Docker、Kubernetes 或 IaC 方案。
- 建立标准化运维手册,包括巡检、扩容、回滚和灾备演练。
- 继续补齐调度、网络策略、存储、GitOps 和平台工程能力。
适用场景
蓝绿发布(Blue/Green)
简介
蓝绿部署同时运行两个版本的应用(蓝色和绿色),通过切换 Service 的标签选择器来实现版本切换。测试验证通过后将流量全部切换到新版本,同时保留旧版本以便快速回滚。
优点
缺点
蓝色版本(v1)配置
# bluegreen-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: blue
spec:
replicas: 4
selector:
matchLabels:
app: bluegreen
template:
metadata:
labels:
app: bluegreen
version: v1.0
spec:
containers:
- name: bluegreen
image: registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v1:v1
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: bluegreen
spec:
type: ClusterIP
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: bluegreen
version: v1.0 # 当前流量指向 v1.0绿色版本(v2)配置
# bluegreen-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: green
spec:
replicas: 4
selector:
matchLabels:
app: bluegreen
template:
metadata:
labels:
app: bluegreen
version: v2.0
spec:
containers:
- name: bluegreen
image: registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v2:v2
ports:
- containerPort: 80切换流量
# 1. 部署蓝色版本(v1)
kubectl apply -f bluegreen-v1.yaml
# 2. 部署绿色版本(v2)
kubectl apply -f bluegreen-v2.yaml
# 3. 此时两个版本共存,但流量全部指向 v1
# 4. 测试 v2 版本无误后,切换 Service 到 v2
kubectl patch svc bluegreen -p '{"spec":{"selector":{"version":"v2.0"}}}'
# 5. 验证流量已切换到 v2
while sleep 0.2; do curl -s http://<ClusterIP> | grep "Deploy Version"; echo ""; done
# 6. 确认稳定后删除旧版本
kubectl delete deployment blue金丝雀发布(Canary / 灰度发布)
简介
金丝雀发布(又称灰度发布)是一种渐进式发布策略,先将新版本部署到少量实例上,让部分用户流量到达新版本,观察无问题后再逐步扩大范围,最终完成全量发布。
优点
实现方式
方式一:通过 Pod 副本数控制流量比例
# canary-v1.yaml(80% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v1
spec:
replicas: 4
selector:
matchLabels:
app: canary-app
template:
metadata:
labels:
app: canary-app
version: v1.0
spec:
containers:
- name: app
image: registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v1:v1
ports:
- containerPort: 80
---
# canary-v2.yaml(20% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v2
spec:
replicas: 1
selector:
matchLabels:
app: canary-app
template:
metadata:
labels:
app: canary-app
version: v2.0
spec:
containers:
- name: app
image: registry.cn-hangzhou.aliyuncs.com/gerry-docker/k8s-deploy-v2:v2
ports:
- containerPort: 80
---
# Service 不指定 version 标签,匹配所有版本
apiVersion: v1
kind: Service
metadata:
name: canary-service
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: canary-app # 注意:不包含 version 标签# 部署 v1 版本(4 个副本)
kubectl apply -f canary-v1.yaml
# 部署 v2 版本(1 个副本 = 20% 流量)
kubectl apply -f canary-v2.yaml
# 持续访问,观察流量分布
while sleep 0.2; do curl -s http://10.104.89.32 | grep "Deploy Version"; echo ""; done
# 如果 v2 正常,逐步扩大 v2 副本数
kubectl scale deployment app-v2 --replicas=2
# 最终完全切换到 v2
kubectl scale deployment app-v2 --replicas=5
kubectl scale deployment app-v1 --replicas=0方式二:使用 Nginx Ingress 进行精准流量控制
# 通过 Ingress 注解实现金丝雀发布(需要 Nginx Ingress Controller)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress-v2
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20" # 20% 流量到 v2
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2-service
port:
number: 80版本回滚
查看修订历史
# 查看 Deployment 修订历史
kubectl rollout history deployment rolling-deployment
# 查看特定版本的详细信息
kubectl rollout history deployment rolling-deployment --revision=2回滚操作
# 回滚到上一个版本
kubectl rollout undo deployment rolling-deployment
# 回滚到指定版本
kubectl rollout undo deployment rolling-deployment --to-revision=1
# 查看回滚状态
kubectl rollout status deployment rolling-deployment暂停和恢复更新
# 暂停滚动更新(用于金丝雀发布场景)
kubectl rollout pause deployment rolling-deployment
# 恢复滚动更新
kubectl rollout resume deployment rolling-deployment发布流程最佳实践
CI/CD 集成发布流程
# 完整的 CI/CD 发布流程示例
# 阶段 1:构建与推送镜像
docker build -t registry.example.com/myapp:v1.2.3 .
docker push registry.example.com/myapp:v1.2.3
# 阶段 2:更新 Deployment 镜像
kubectl set image deployment/myapp \
myapp=registry.example.com/myapp:v1.2.3 \
--namespace=production \
--record
# 阶段 3:等待滚动更新完成
kubectl rollout status deployment/myapp --namespace=production --timeout=300s
# 阶段 4:健康检查验证
kubectl get pods -n=production -l app=myapp
# 确认所有 Pod 都是 Running 且 Ready
# 阶段 5:冒烟测试
curl -s http://myapp.production.svc/api/health | jq .
# 阶段 6:(可选)如果失败则回滚
# kubectl rollout undo deployment/myapp --namespace=production发布前检查清单
#!/bin/bash
# pre-release-check.sh — 发布前检查脚本
echo "========== 发布前检查 =========="
# 1. 检查当前部署状态
echo "--- 当前部署状态 ---"
kubectl get deployments -n production
# 2. 检查 Pod 健康状态
echo "--- Pod 健康状态 ---"
kubectl get pods -n production -o wide
# 3. 检查资源使用率
echo "--- 资源使用率 ---"
kubectl top pods -n production
kubectl top nodes
# 4. 检查最近的事件
echo "--- 最近事件 ---"
kubectl get events -n production --sort-by='.lastTimestamp' | tail -10
# 5. 检查镜像版本
echo "--- 当前镜像版本 ---"
kubectl get deployments -n production -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.containers[0].image}{"\n"}{end}'
# 6. 检查副本数和可用副本
echo "--- 副本状态 ---"
kubectl get deployments -n production -o wide
# 7. 检查 PVC 状态
echo "--- 持久化存储 ---"
kubectl get pvc -n production
# 8. 检查 ConfigMap 和 Secret 是否存在
echo "--- 配置资源 ---"
kubectl get configmaps,secrets -n production
echo "========== 检查完毕 =========="排查发布问题
# Pod 一直处于 ImagePullBackOff
kubectl describe pod <pod-name> -n production | grep -A 5 "Events"
# 常见原因:镜像不存在、仓库认证失败、网络不通
# Pod 一直处于 CrashLoopBackOff
kubectl logs <pod-name> -n production --previous
# 常见原因:应用启动失败、配置错误、端口冲突
# Pod 一直处于 Pending
kubectl describe pod <pod-name> -n production | grep -A 10 "Events"
# 常见原因:资源不足、PVC 无法挂载、节点选择器不匹配
# 滚动更新卡住
kubectl rollout status deployment/myapp --namespace=production
# 常见原因:
# 1. readinessProbe 未通过 — 新 Pod 不被标记为 Ready
# 2. maxUnavailable=0 且新 Pod 启动失败
# 3. 镜像拉取超时
# 检查 RollingUpdate 进度
kubectl get rs -n production # 查看 ReplicaSet 状态
# DESIRED CURRENT READY 对比判断更新进度探针配置对发布的影响
# 正确配置探针对零停机发布至关重要
spec:
containers:
- name: app
image: myapp:v2
# 存活探针 — 检测应用是否存活
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30 # 启动后等待 30 秒再检测
periodSeconds: 10
failureThreshold: 3 # 连续失败 3 次后重启容器
# 就绪探针 — 决定 Pod 是否接收流量(影响滚动更新)
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5 # 可以比 liveness 更早开始检测
periodSeconds: 5
failureThreshold: 3
# 只有 readinessProbe 通过的 Pod 才会被 Service 转发流量
# 启动探针 — 给应用足够的启动时间(K8S 1.18+)
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 30 # 最多允许 30 次失败
periodSeconds: 2 # 每 2 秒检测一次
# 等效于给应用 60 秒启动时间
# startupProbe 通过前不会执行 liveness 和 readiness常用 kubectl 发布命令汇总
# 应用配置
kubectl apply -f deployment.yaml --record
# 更新镜像
kubectl set image deployment/[name] [container]=[image]:[tag] --record
# 查看部署状态
kubectl rollout status deployment/[name]
# 查看修订历史
kubectl rollout history deployment/[name]
# 回滚到上一版本
kubectl rollout undo deployment/[name]
# 回滚到指定版本
kubectl rollout undo deployment/[name] --to-revision=[n]
# 暂停更新
kubectl rollout pause deployment/[name]
# 恢复更新
kubectl rollout resume deployment/[name]
# 查看部署详情
kubectl describe deployment [name]
# 查看 Pod 状态
kubectl get pods -l app=[label] -w
# 扩缩容
kubectl scale deployment/[name] --replicas=[n]优点
缺点
总结
K8S 原生支持滚动更新,通过 maxSurge 和 maxUnavailable 控制更新节奏。出问题用 kubectl rollout undo 快速回滚。配合 Readiness Probe 实现零停机发布。
