Kubernetes 资源生产实践
前 18 章解决了"会不会用",本章解决"用得好不好"。生产环境的清单要可审阅、可验证、可回滚,应用要高可用、能优雅停机、零宕机更新。本章把散落各章的实践要点收敛为一份可执行的清单。
本篇目标:掌握生产级 YAML 规范与 kube-linter 静态扫描,理解副本数/反亲和/PDB 的高可用组合,掌握优雅停机与零宕机更新,并避开最常见的生产坑。
1. 生产环境 YAML 规范与静态扫描工具
1.1 生产级 YAML 基线
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
labels:
app.kubernetes.io/name: api
spec:
replicas: 3
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: api
template:
metadata:
labels:
app.kubernetes.io/name: api
spec:
containers:
- name: api
image: registry.example.com/api:1.5.2
ports:
- containerPort: 8080
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 256Mi }
readinessProbe:
httpGet: { path: /ready, port: 8080 }
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 30
failureThreshold: 5
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
1.2 静态扫描工具:kube-linter
kube-linter 用内置规则扫描清单中的常见问题(如缺探针、特权容器、latest 标签):
# 安装(macOS)
brew install kube-linter
# 扫描目录或单个文件
kube-linter lint deployment.yaml
kube-linter lint ./manifests/ -v
# 只跑指定规则
kube-linter lint deployment.yaml --include="no-readiness-probe,latest-tag"
常用检查项:latest-tag(禁止 latest)、no-readiness-probe、privileged-container、run-as-non-root、no-requests-limit。
1.3 清单应进 Git
- 生产清单通过 Git 管理,由 CI 或 GitOps 工具(Argo CD/Flux)交付;
- 发布前跑
kubectl diff -f <manifest>确认实际变更范围; kubectl edit只适合测试或紧急止血,不应成为长期配置来源。
2. 高可用应用部署架构
2.1 副本数:至少两个
单副本意味着单点:节点故障、滚动更新期间都会造成服务不可用。关键服务至少 2 副本,核心服务建议 3+ 并跨可用区。
2.2 Pod 反亲和:分散副本
spec:
template:
spec:
affinity:
podAntiAffinity:
# 硬约束:同一 hostname 上不能有两个 api Pod
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: api
topologyKey: kubernetes.io/hostname
requiredDuringScheduling 是硬约束,副本数超过可用节点数时多余的 Pod 会 Pending;改为 preferredDuringScheduling 则是软偏好。
2.3 Topology Spread Constraints:跨可用区均匀分布
spec:
template:
spec:
topologySpreadConstraints:
- labelSelector:
matchLabels:
app.kubernetes.io/name: api
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway # 做不到也不阻塞
比 anti-affinity 更精确——它保证的是"均匀分布",而不是简单的"不在一起"。推荐同时使用 podAntiAffinity(节点级)和 topologySpreadConstraints(可用区级)。
2.4 PDB:节点维护时保留最小可用副本
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app.kubernetes.io/name: api
PDB 约束的是 drain、集群升级等自愿中断,不能阻止节点宕机、OOM 或应用自身崩溃。
3. 应用优雅停机与零宕机更新
3.1 优雅停机组合
零宕机更新需要三层配合,缺一不可:
1. readiness 探针:新 Pod 未就绪不进 Service,旧 Pod 摘除后不再接新请求
2. preStop 钩子:给"流量摘除 + 应用收尾"争取时间
3. 应用处理 SIGTERM:停止接收新请求 → 处理完现有请求 → 关闭连接 → 退出
spec:
terminationGracePeriodSeconds: 60 # 总优雅退出时限
containers:
- name: api
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
readinessProbe:
httpGet: { path: /ready, port: 8080 }
3.2 发布策略组合选择
| 发布方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
Recreate | 新旧版本不能共存(数据库迁移) | 简单,绝不并存 | 发布期间完全不可用 |
RollingUpdate(默认) | 绝大多数无状态服务 | 逐步替换、可用性有保障 | 只能控制副本数比例,无法精确控制流量比例 |
| 金丝雀(pause/resume) | 先小范围验证再放量 | 无需额外组件,随时暂停回滚 | 控制的是 Pod 数量,不是真实流量百分比 |
| 蓝绿(双 Service 切换) | 切换时间敏感、要求瞬时完成 | 新旧彻底隔离,回滚只切流量 | 双倍资源长期运行两套环境 |
需要精确灰度(按权重/Header 切流、指标自动放量)时,引入 Argo Rollouts 或 Ingress 金丝雀注解(第 10 章)。
3.3 零宕机发布检查
# 发布前确认 PDB 不会阻塞、副本充足
kubectl get poddisruptionbudget -A
kubectl rollout status deployment/api -n production --timeout=5m
kubectl get endpointslice -n production -l kubernetes.io/service-name=api
4. 生产级别 K8s 资源清单避坑指南
| 坑 | 后果 | 避免 |
|---|---|---|
用 latest 镜像 | 无法回滚、无法追溯 | 用固定 tag 或 digest |
| 不配 readiness | 流量打到坏 Pod | 所有接流量服务必配 |
| liveness 误杀 | 重启风暴 | 加大 failureThreshold,只探"卡死"信号 |
| 资源值拍脑袋 | 调度失衡、节流、OOM | 用压测数据(第 14 章) |
| 单副本无 PDB | drain 阻塞、节点故障即宕机 | 至少 2 副本 + PDB |
| 副本挤同一节点/AZ | 一次故障全挂 | anti-affinity + topology spread |
| Secret 明文进 Git | 凭据泄漏 | External Secrets / Vault(第 11 章) |
| HPA 与手工 scale 混用 | 副本数互相覆盖 | 由 HPA 接管后发布工具忽略 replicas |
| 忽略 finalizer | Namespace/PVC 删除卡死 | 排查外部依赖后再强删 |
| 跳过 kubectl diff | 发布范围超出预期 | 发布前 diff 并评审 |
5. 上线前检查清单
- 清单来自 Git,镜像版本可追踪,变更有 PR 和至少一人评审
- resources 来自压测,QoS 至少 Burstable
- readiness / startup / liveness 配置合理(liveness 确认需要才加)
- 至少 2 副本 + PDB,副本分散到不同节点/可用区
- 优雅停机三层(readiness + preStop + SIGTERM 处理)就位
- 数据库迁移已评审,确认向前/向后兼容
- 配置变更评估是否需要滚动重启
- 在测试环境跑过
kubectl diff,确认实际变更范围 - kube-linter 扫描通过
- 明确发布责任人、观察窗口(> 15 分钟)和失败回滚步骤
- 发布后同时验证资源状态与业务指标(Pod Running 不是成功,业务正常才是)
6. 练习
练习 A
- 写一个 Deployment,运行
kube-linter lint扫描,修复所有告警(latest tag、缺探针等) - 给 Deployment 添加
podAntiAffinity(hostname 级),用kubectl get pods -o wide确认副本分散 - 创建 PDB
minAvailable: 2,用kubectl drain <node> --dry-run=client观察驱逐提示
练习 B
- 模拟一次零宕机发布:给应用配 readiness + preStop,修改镜像 tag 后
rollout status,在另一个终端kubectl get pods -w观察"旧 Pod 摘流量 → 新 Pod 接流量"的顺序 - 故意单副本 + PDB
minAvailable: 1,执行 drain 观察阻塞,再扩容到 2 副本验证恢复 - 按第 4 节避坑表检查自己的练习清单,找出至少 3 个需要改进的点
本系列到此结束。至此你已覆盖:资源模型与集群安装、Namespace、Pod 与各工作负载、Service/Ingress、配置密钥、存储、资源与探针、HPA、RBAC、调度、排障、集群升级与生产实践——从搭建到运维的完整链路。