Appearance
Deployment 发布
无状态服务最常见的需求:跑 N 个相同副本,换镜像时逐个替换不中断服务,出问题能快速退回上一版。Deployment 通过 ReplicaSet 管理 Pod 副本来实现这一套。
没有 Deployment 时,要手动创建 ReplicaSet、盯着 Pod 数量、滚动更新时自己写脚本逐批替换。Deployment 把这些自动化了。
Deployment → ReplicaSet → Pod
Deployment 不直接管每个 Pod——它创建 ReplicaSet 作为版本载体。每次更新镜像或模板,Deployment 创建一个新 ReplicaSet,在新 ReplicaSet 里创建 Pod,旧 ReplicaSet 逐步缩容:
旧 ReplicaSet 的 Pod 缩到 0 后,ReplicaSet 本身保留——用于回滚:
bash
kubectl -n demo get deploy,rs,pod -l app=web
kubectl -n demo rollout history deploy/web基础 Deployment
先从一个能跑的最简 Deployment 开始:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: harbor.example.com/demo/web:v1.0.0
ports:
- containerPort: 8080apply 之后,Deployment 控制器创建 ReplicaSet,scheduler 给 Pod 选节点,kubelet 创建容器。kubectl get deploy,rs,pod -n demo 可以看到三者的关系。
revisionHistoryLimit 控制保留多少个旧 ReplicaSet(默认 10)。历史多了浪费 etcd 空间——大部分集群设 3~5 够用。
这个最简 Deployment 有个关键缺口——没有 readinessProbe。更新镜像时新 Pod 一启动就接入 Service,如果应用启动慢,请求会失败。
滚动更新
滚动更新逐批创建新 Pod、等待 Ready、删除旧 Pod。更新节奏由两个参数控制:
yaml
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0| 参数 | 含义 | 影响 |
|---|---|---|
maxSurge | 更新期间允许超出期望副本数的最大 Pod 数 | 值越大更新越快,但瞬时资源占用更高 |
maxUnavailable | 更新期间允许不可用的最大 Pod 数 | 值越大更新越快,但可用容量下降越多 |
副本数很少时(比如 2 个副本),maxUnavailable: 1 会让可用容量瞬间降 50%。小规模服务通常设 maxUnavailable: 0 配合 maxSurge: 1——先建新的,等 Ready 再删旧的。
更新镜像:
bash
kubectl -n demo set image deploy/web web=harbor.example.com/demo/web:v1.0.1
kubectl -n demo rollout status deploy/webrollout status 会阻塞到更新完成或超时(progressDeadlineSeconds,默认 600 秒)。
readinessProbe 和滚动更新的关系
没有 readinessProbe 时,滚动更新的节奏完全由容器启动速度决定——容器一启动就被认为 Ready,旧 Pod 立刻删除。新 Pod 启动后连不上数据库、缓存没热、配置没加载完成——请求已经在往它打了。
加上 readinessProbe:
yaml
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3 # 连续失败 3 × 5 = 15 秒后判定不 Ready加上之后,滚动更新会等新 Pod 的 readinessProbe 通过才删旧 Pod。readinessProbe 一直不通过时,滚动更新卡住——新 Pod 不 Ready,旧 Pod 不删除。这是保护机制,不是 bug。排查时看新 Pod 的 readinessProbe 为什么失败,而不是急着加 maxUnavailable。
回滚
bash
kubectl -n demo rollout history deploy/web # 查看历史
kubectl -n demo rollout history deploy/web --revision=2 # 看某个版本的具体内容
kubectl -n demo rollout undo deploy/web # 回滚到上一版
kubectl -n demo rollout undo deploy/web --to-revision=2 # 回滚到指定版本回滚的边界:rollout undo 只恢复 Deployment 的 Pod 模板——镜像、环境变量、资源请求。它不回滚数据库 schema 变更、不回滚配置中心里的配置、不回滚外部 API 的接口版本。只靠 Deployment 回滚对于数据库 schema 有变更的发布是不够的——schema 迁移脚本的向前兼容和回滚脚本要单独设计。
暂停和恢复
连续改多个字段时(换镜像 + 调资源 + 改环境变量),每次 apply 都触发一次滚动重建。可以先暂停,变更堆积后在恢复时一次触发:
bash
kubectl -n demo rollout pause deploy/web
kubectl -n demo set image deploy/web web=harbor.example.com/demo/web:v1.0.2
kubectl -n demo set resources deploy/web -c web --requests=cpu=200m,memory=256Mi
kubectl -n demo rollout resume deploy/web发布排查
发布卡住时:
bash
kubectl -n demo rollout status deploy/web
kubectl -n demo describe deploy web
kubectl -n demo get rs,pod -l app=web -o wide| 现象 | 原因方向 | 排查 |
|---|---|---|
| 新 Pod ImagePullBackOff | 镜像 tag 写错、仓库认证、节点到仓库网络不通 | Events → crictl pull 在节点试 |
| 新 Pod Running 但不 Ready | readinessProbe 失败、应用启动异常、依赖不可用 | kubectl logs、kubectl describe pod 看 probe 事件 |
| 新 Pod Pending | 资源不足、调度规则、PVC | kubectl describe pod 看调度事件 |
| rollout 超时 | progressDeadlineSeconds 到期,新副本一直不 Ready | 新 Pod 的状态和日志 |
发布故障分成两类:平台没创建起 Pod(看 Events 和节点)和 Pod 创建起来了但不能接流量(看探针、应用日志、入口指标)。两条路径的排查入口不同。