6323 字
32 分钟
第 8 篇:Kubernetes Pod、Node 与 Deployment

第 8 篇:Kubernetes Pod、Node 与 Deployment#

0. 本篇定位#

上一篇我们从 Docker Compose 迁移视角理解了 Kubernetes 对象拆分:无状态 API 通常会拆成 Deployment 和 Service,配置拆成 ConfigMap 与 Secret,存储拆成 PVC 或外部托管服务。本篇正式进入 Kubernetes 工作负载的核心:Pod、Node、ReplicaSet、Deployment 和 Scheduler。

后端工程师学习 Kubernetes,第一道坎不是会不会写 YAML,而是能不能理解“谁负责什么”。Pod 是最小调度单元,不是长期稳定身份;Node 是运行 Pod 的工作节点,不是业务副本声明;ReplicaSet 维持某一版本的 Pod 数量,通常由 Deployment 管理;Deployment 声明无状态应用的期望副本和发布策略;Scheduler 根据资源和约束为 Pod 选择 Node。

读完本篇后,你应该能做到三件事。第一,解释一个 Deployment 从提交到 Pod Running 的完整路径。第二,区分 Pending、ImagePullBackOff、CrashLoopBackOff、OOMKilled、rollout 卡住分别应该看哪些证据。第三,理解 requests、limits、labels、selector、probes 和 rollout 对后端 API 生产稳定性的影响。

1. 问题背景#

很多人第一次看到 Kubernetes,会把 Pod 当成“更复杂的容器”,把 Deployment 当成“启动脚本”,把 Node 当成“一台服务器”,然后在故障时把所有现象都叫作“K8s 挂了”。这种理解会让排障很慢,因为 Kubernetes 中每个对象只负责一部分工作,故障也会分阶段暴露。

例如 Pod 一直 Pending,不一定是应用问题,可能是集群没有满足 requests 的节点,也可能是 PVC 没绑定、节点选择器不匹配、污点没有容忍。ImagePullBackOff 不一定是 Kubernetes 网络问题,可能是镜像名错误、tag 不存在、仓库认证失败。CrashLoopBackOff 不一定是 Deployment 问题,通常是容器进程启动后不断退出。OOMKilled 不一定是“Java 有 bug”,也可能是内存 limit 太小或 JVM 没按容器内存调参。

Deployment 也容易被误解。你提交 Deployment 后,真正创建 Pod 的不是 Deployment 本身,而是它创建的 ReplicaSet;更新镜像后,Deployment 会创建新的 ReplicaSet,并逐步调整新旧 ReplicaSet 的副本数。rollout 卡住时,要看新 ReplicaSet 的 Pod 为什么没有 ready,而不是只看 Deployment YAML。

这篇文章的核心,就是把这条控制链路拆清楚。只要你能知道“当前卡在哪个阶段、哪个对象负责、应该看什么证据”,Kubernetes 排障就会从黑盒变成可推理系统。

2. 核心概念#

Kubernetes 工作负载链路可以先按职责边界理解。

对象负责什么不负责什么典型证据
Pod承载一个或多个紧密协作容器,是最小调度单元不长期维持副本数,不提供稳定入口Pod phase、conditions、events、container status
Node提供 CPU、内存、网络、磁盘和 kubelet 执行环境不决定业务期望副本数Node conditions、allocatable、taints、kubelet 状态
Scheduler为未绑定 Node 的 Pod 选择合适节点不拉镜像,不启动容器,不保证应用健康Pod events 中的 FailedScheduling
ReplicaSet维持某一模板版本的 Pod 数量通常不直接被业务手工管理ReplicaSet desired/current/ready
Deployment管理 ReplicaSet、无状态副本和滚动发布不直接承接流量,不替代 Servicerollout status、revision、strategy

2.1 Pod:最小调度单元,不是稳定机器#

Pod 是 Kubernetes 中最小调度单元。一个 Pod 可以包含一个或多个容器,这些容器共享网络命名空间和部分生命周期。对普通后端 API 来说,一个 Pod 通常只有一个业务容器;sidecar 场景下,可能还有日志代理、服务网格代理或辅助容器。Pod 内部容器共享同一个 Pod IP,容器之间可以用 localhost 通信。

Pod 不是稳定机器。Pod 被删除、驱逐、节点故障或滚动发布时,新的 Pod 会获得新的名称和 IP。后端调用方不应该记录 Pod IP,也不应该直接依赖某个 Pod 名称。稳定访问入口应该由 Service 提供,副本维持应该由 ReplicaSet 或 Deployment 负责。

Pod 的状态要分层看。Pod phase 可能是 Pending、Running、Succeeded、Failed、Unknown;container state 可能是 Waiting、Running、Terminated;conditions 里有 Initialized、Ready、ContainersReady、PodScheduled 等。看到 Running 不代表已经 ready,看到 Pending 也不一定是镜像问题。先区分 Pod 是否被调度,再看容器是否启动,再看 readiness 是否通过。

2.2 Node、Scheduler 与资源约束#

Node 是运行 Pod 的工作节点。每个 Node 上有 kubelet、容器运行时、网络插件和系统资源。Kubernetes 调度 Pod 时,会看 Node 的可分配资源、污点和容忍、亲和性、节点选择器、PVC 绑定、拓扑约束等条件。Node 不是业务对象,但 Node 状态会直接影响 Pod 是否能运行。

Scheduler 只负责把未调度的 Pod 绑定到某个 Node。它不拉镜像,不启动容器,也不判断业务是否健康。Pod Pending 且事件里出现 FailedScheduling 时,说明调度阶段就没过。常见原因包括 CPU 或内存 requests 太大、节点 taint 不允许调度、nodeSelector 不匹配、PVC 未绑定。

requests 和 limits 是后端服务必须认真设计的字段。requests 决定调度时预留多少资源,limits 决定容器运行时的上限。没有 requests,调度器无法准确判断容量;limits 太低,容易 OOMKilled;limits 太高,可能让单个服务影响节点稳定。Java 服务还要让 JVM 感知容器内存,避免堆和非堆内存加起来超过 limit。

2.3 Deployment 与 ReplicaSet 控制循环#

Deployment 是无状态后端 API 最常用的工作负载对象。它声明期望副本数、Pod 模板、滚动发布策略和历史版本。Deployment 不直接创建容器,它通过 ReplicaSet 管理某一版本的 Pod。当你修改 Pod 模板中的镜像、环境变量、资源或探针时,Deployment 会创建新的 ReplicaSet,并按照策略逐步替换旧 Pod。

ReplicaSet 负责维持某一版本 Pod 的数量。你通常不直接编辑 ReplicaSet,因为它由 Deployment 管理。rollout 过程中,旧 ReplicaSet 副本数减少,新 ReplicaSet 副本数增加。rollout 卡住时,不要只看 Deployment,要看新 ReplicaSet 创建的 Pod 为什么没有 ready。

Deployment 的成功不等于业务一定可用。Deployment 只知道 Pod 是否 ready,不知道你的业务指标是否正常、数据库迁移是否兼容、接口延迟是否升高。生产发布还要结合 Service、Ingress、监控、日志、trace、错误率和回滚策略一起判断。

3. 运行机制#

一个后端 Deployment 从提交到可用,大致经历下面的链路。

kubectl apply
-> API Server stores Deployment
-> Deployment controller creates ReplicaSet
-> ReplicaSet creates Pods
-> Scheduler assigns Nodes
-> kubelet pulls image and starts containers
-> probes update Pod readiness
-> Service selects ready endpoints

3.1 从 YAML 到 Pod 的控制链路#

当你提交 Deployment YAML 时,API Server 保存的是期望状态。Deployment 控制器观察到期望状态后,会计算是否需要创建或更新 ReplicaSet。ReplicaSet 控制器继续观察副本数量,如果当前 Pod 少于期望,就创建新的 Pod 对象。此时 Pod 还没有运行,只是 API Server 中的对象。

Scheduler 观察到没有绑定 Node 的 Pod 后,会尝试选择合适 Node。它会检查资源 requests、节点状态、调度约束、污点容忍、亲和性、存储绑定等。如果找不到合适节点,Pod 会停留在 Pending,并在 events 中记录 FailedScheduling。这个阶段应用容器还没启动,所以查应用日志没有意义。

Pod 被绑定到 Node 后,目标 Node 上的 kubelet 开始工作。kubelet 会拉取镜像、准备 volume、设置网络、启动容器、运行探针,并把状态回写 API Server。镜像拉取失败会出现 ImagePullBackOff;进程启动后反复退出会出现 CrashLoopBackOff;内存超限可能出现 OOMKilled;readiness 失败会让 Pod 不接 Service 流量。

3.2 滚动发布和版本切换#

Deployment 更新时,关键变化通常发生在 Pod template。只要 spec.template 发生变化,例如镜像 tag、环境变量、资源、探针、label 等,Deployment 就会创建新的 ReplicaSet。仅修改 Deployment 外层 metadata,不一定触发新 Pod。

滚动发布的核心是逐步增加新 ReplicaSet 副本,逐步减少旧 ReplicaSet 副本。maxSurge 控制最多可以额外创建多少新 Pod,maxUnavailable 控制发布过程中最多允许多少旧 Pod 不可用。对后端 API 来说,readinessProbe 是滚动发布是否安全的关键。新 Pod 未 ready 之前,不应该被 Service 接流量。

rollout 卡住通常有三类原因。第一,新 Pod 无法调度或拉镜像。第二,新 Pod 启动后崩溃或探针失败。第三,资源不足导致新旧 Pod 无法同时存在。排障时用 kubectl rollout status 看 Deployment,再看 ReplicaSet 和新 Pod 事件,才能找到具体卡点。

3.3 伪代码:Deployment 控制循环#

下面用伪代码理解 Deployment、ReplicaSet、Scheduler 和 kubelet 的分工。

function reconcileDeployment(deployment):
desiredTemplate = deployment.spec.template
desiredReplicas = deployment.spec.replicas
currentReplicaSet = findReplicaSetByTemplate(desiredTemplate)
if currentReplicaSet is None:
currentReplicaSet = createReplicaSet(desiredTemplate)
rolloutPlan = calculateRollout(
newReplicaSet = currentReplicaSet,
oldReplicaSets = findOldReplicaSets(deployment),
strategy = deployment.spec.strategy
)
scaleReplicaSets(rolloutPlan)
function reconcileReplicaSet(replicaSet):
while replicaSet.readyPods < replicaSet.desiredReplicas:
createPod(replicaSet.template)
function schedulePod(pod):
candidates = filterNodesByResourcesAndConstraints(pod)
if candidates.isEmpty():
recordEvent(pod, "FailedScheduling")
return
bindPodToNode(pod, chooseBestNode(candidates))
function kubeletSyncPod(pod):
pullImages(pod.containers)
mountVolumes(pod.volumes)
startContainers(pod.containers)
runProbes(pod)
reportStatus(pod)

这段伪代码说明:Deployment 不拉镜像,ReplicaSet 不选 Node,Scheduler 不启动容器,kubelet 不决定期望副本。排障时必须沿着职责链路看证据,不能把所有异常都归到一个对象上。

4. 最小可运行示例#

下面是一个最小但较完整的后端 API Deployment。它包含副本数、selector、资源、端口和探针。

4.1 编写 Deployment#

apiVersion: apps/v1
kind: Deployment
metadata:
name: order-api
labels:
app: order-api
spec:
replicas: 2
selector:
matchLabels:
app: order-api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: order-api
spec:
containers:
- name: api
image: registry.example.com/order-api:1.0.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 1Gi
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 15
periodSeconds: 5
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10

这个示例没有写 Service,因为下一篇会专门讲 Service 和 Ingress。这里先聚焦工作负载本身:Deployment 如何管理 Pod 副本,Pod 如何被调度到 Node,容器如何启动和暴露健康状态。

4.2 应用和观察对象链#

应用 Deployment:

Terminal window
kubectl apply -f order-api-deployment.yaml

观察对象链:

Terminal window
kubectl get deployment order-api
kubectl get rs -l app=order-api
kubectl get pod -l app=order-api -o wide
kubectl rollout status deployment/order-api

kubectl get pod -o wide 可以看到 Pod 被调度到哪个 Node,以及 Pod IP。Pod IP 只是当前实例地址,不应该写进业务配置。kubectl get rs 可以看到当前版本和历史版本对应的 ReplicaSet。rollout 状态能告诉你发布是否完成。

4.3 模拟更新和回滚#

更新镜像:

Terminal window
kubectl set image deployment/order-api api=registry.example.com/order-api:1.0.1
kubectl rollout status deployment/order-api

查看历史:

Terminal window
kubectl rollout history deployment/order-api
kubectl get rs -l app=order-api

回滚:

Terminal window
kubectl rollout undo deployment/order-api

这里要注意,回滚只是回到上一个 Deployment revision。它不能自动回滚数据库 schema,不能撤销外部配置变更,也不能保证业务状态兼容。后端发布必须把镜像、配置、数据库迁移和业务兼容性一起设计。

5. 配置逐行拆解#

这一节拆解 Deployment 中最影响后端稳定性的字段。理解它们,比背更多命令更重要。

5.1 apiVersion、kind、replicas 和 selector#

apiVersion: apps/v1kind: Deployment 决定对象类型。Kubernetes 根据类型把对象交给对应控制器处理。写成 Pod、Deployment、StatefulSet 或 Job,背后的控制逻辑完全不同。后端 API 通常用 Deployment,因为它适合无状态副本和滚动发布。

replicas 是期望副本数。副本数为 2,不是“启动两个容器后结束”,而是控制器持续维持两个 Pod 副本。某个 Pod 被删掉,ReplicaSet 会创建新的 Pod。副本数设计要结合可用性、容量、成本和依赖承载能力。副本变多会增加数据库连接、缓存连接和下游调用压力。

selector.matchLabels 是控制器识别 Pod 的依据。它必须和 template.metadata.labels 匹配。这个字段一旦创建后通常不应随意改变。selector 错误会导致 Deployment 管不到 Pod,Service 也可能选不到后端。Kubernetes 排障里,label 和 selector 是第一等证据。

5.2 template、image、ports 和 probes#

template 是 Pod 模板。Deployment 的版本变化主要由 spec.template 决定。修改镜像、环境变量、资源、探针或模板 label,会触发新的 ReplicaSet。理解这一点后,你就能解释为什么有些 YAML 修改不会触发滚动发布。

image 是容器制品引用。生产环境最好使用明确版本 tag 或 digest,不要依赖可变的 latest。如果出现 ImagePullBackOff,要看镜像名、tag、仓库地址、网络、认证和 imagePullSecret。不要先去改 Deployment 副本数,那和拉取失败没有直接关系。

ports.containerPort 主要是声明容器监听端口,方便文档化和被其他对象引用。它不等于外部访问入口。真正的集群访问入口要靠 Service,外部访问还要靠 Ingress、Gateway 或 LoadBalancer。探针会访问容器端口,因此端口和探针路径必须和应用真实监听一致。

readinessProbe 和 livenessProbe 语义不同。readiness 失败时,Pod 不应接流量;liveness 失败时,kubelet 会重启容器。后端 API 不要把依赖短暂波动直接放进 liveness,否则数据库抖一下可能触发应用反复重启。启动慢的应用可以再加 startupProbe。

5.3 requests、limits、Node 和调度#

resources.requests 决定调度时预留资源。Scheduler 会根据 requests 判断哪个 Node 能容纳 Pod。如果 requests 设置过高,Pod 可能 Pending;设置过低,多个 Pod 可能挤在同一 Node 上,运行时竞争严重。requests 是容量规划输入,不是装饰字段。

resources.limits 决定容器运行上限。内存超过 limit 时,容器可能被 OOMKilled;CPU limit 则可能导致 throttling。Java 后端要让 JVM 最大堆、直接内存、元空间、线程栈和容器 limit 之间留出余量。只设置 -Xmx 不看容器 limit,很容易在高峰期被杀。

Node 约束包括 nodeSelector、affinity、taints/tolerations、拓扑分布和 PVC 绑定。它们决定 Pod 能不能调度到合适位置。学习阶段可以先不写复杂约束,但生产环境至少要知道 Pending 时可能不是应用问题,而是资源或调度约束问题。

6. 后端工程场景#

Pod、Node 和 Deployment 的知识,最终要落到后端 API 的发布、容量和排障上。

6.1 无状态 API 的标准部署#

无状态 API 最适合用 Deployment。应用状态放在数据库、缓存或外部服务里,Pod 可以随时重建。每个 Pod 输出标准日志,暴露健康接口,优雅处理 SIGTERM,不把关键数据写在本地文件系统中。这样的服务才能真正享受 Kubernetes 的副本和滚动发布能力。

标准部署至少应该包含 replicas、resources、readinessProbe、livenessProbe、清晰 labels、镜像版本和发布策略。Service 和 Ingress 会在下一篇讲,但 Deployment 本身已经决定了实例是否稳定、是否可调度、是否能安全滚动。

后端服务还要考虑连接池。replicas 从 2 扩到 10,数据库连接池如果每个实例 50 个连接,总连接数就会从 100 变成 500。Kubernetes 可以扩副本,但下游依赖能否承受,是应用和架构设计问题。

6.2 发布、扩容和容量治理#

扩容不是只改 replicas。水平扩容会影响 CPU、内存、下游连接、缓存命中、消息消费并发和外部接口限流。扩容前要看资源使用率、请求延迟、错误率和依赖容量。盲目扩副本可能把瓶颈从 API 转移到数据库。

滚动发布要依赖 readiness。新 Pod 只有在准备好接流量时才应该进入 Service endpoints。应用收到 SIGTERM 后,也要停止接收新请求、等待正在处理的请求结束,再退出。否则滚动发布会制造 5xx 或请求中断。

容量治理要从 requests 开始。requests 太低,调度看起来省资源,但节点可能超卖严重;requests 太高,资源利用率低,Pod 也更容易 Pending。后端团队应该根据压测和历史指标给出初始 requests,再通过监控持续调整。

6.3 订单服务排障案例#

假设订单 API 发布后一直 Pending。第一步看 kubectl describe pod,如果 events 显示 Insufficient memory,说明调度阶段资源不足,应该调整 requests、扩容节点或优化资源占用,而不是查应用日志。因为应用根本还没启动。

如果订单 API 是 CrashLoopBackOff,说明容器启动后反复退出。此时看 kubectl logs --previous、环境变量、配置引用、启动命令和数据库连接。不要先怀疑 Scheduler,因为 Pod 已经调度并启动过。

如果发布后 rollout 卡住,但 Pod Running,继续看 readinessProbe。健康接口可能因为数据库连接失败而返回非 200,Pod 因此不进入 ready。此时 Service 可能没有新版本 endpoints,rollout 会等待。修复方向是配置、依赖或探针语义,而不是盲目把 probe 删除。

7. 常见错误与排障#

Kubernetes 排障的关键,是先判断卡在哪个阶段。不同阶段看不同证据。

7.1 Pending、ImagePullBackOff 和调度问题#

Pod Pending 时,先看事件。

Terminal window
kubectl describe pod <pod-name>
kubectl get node
kubectl describe node <node-name>

如果事件里是 FailedScheduling,重点看资源 requests、nodeSelector、affinity、taints/tolerations、PVC 绑定和节点可用资源。此时不要查应用日志,因为容器还没有运行。

ImagePullBackOff 时,看镜像引用和仓库认证。

Terminal window
kubectl describe pod <pod-name>
kubectl get secret
kubectl logs <pod-name>

很多时候 kubectl logs 没有内容,因为容器根本没启动。真正证据在 Pod events 里,例如镜像不存在、认证失败、拉取超时。

7.2 CrashLoopBackOff、OOMKilled 和探针失败#

CrashLoopBackOff 表示容器进程反复退出。看当前日志和上一次退出日志。

Terminal window
kubectl logs <pod-name>
kubectl logs <pod-name> --previous
kubectl describe pod <pod-name>

常见原因包括启动命令错误、环境变量缺失、配置文件不存在、数据库连接失败、应用启动后立即退出。--previous 很重要,因为容器重启后当前日志可能只剩新一轮启动内容。

OOMKilled 要看容器状态和资源限制。

Terminal window
kubectl describe pod <pod-name>
kubectl top pod <pod-name>

如果内存 limit 过低,先调整 limit 和 JVM 参数,再结合内存指标判断是否存在泄漏。不要只把副本数加大,因为单 Pod 内存超限并不会因副本数增加自动消失。

探针失败时,看探针路径、端口、initialDelay、timeout、period,以及应用实际健康接口。readiness 失败会影响接流量,liveness 失败会触发重启。两者后果不同,不能混用。

7.3 Deployment 不更新和 rollout 卡住#

Deployment 修改后没有新 Pod,先确认是否修改了 spec.template。只有 Pod 模板变化才会触发新 ReplicaSet。可以查看 rollout 历史和 ReplicaSet。

Terminal window
kubectl rollout history deployment/order-api
kubectl get rs -l app=order-api
kubectl describe deployment order-api

rollout 卡住时,看新 ReplicaSet 的 Pod 状态。

Terminal window
kubectl get pod -l app=order-api -o wide
kubectl describe pod <new-pod-name>
kubectl logs <new-pod-name> --tail=200

如果新 Pod 不 ready,Deployment 会等待,旧 Pod 可能继续保留。不要为了让 rollout 通过就删除 readinessProbe。正确做法是修复新版本为什么不 ready,或者回滚到上一个版本。

8. 生产化边界#

Deployment 能管理副本和滚动发布,但生产稳定性还依赖应用设计、资源治理、观测和发布纪律。

8.1 应用生命周期边界#

后端应用必须正确处理启动、ready、运行、终止四个阶段。启动阶段可以慢,但要用 startupProbe 或合理 initialDelay 避免误杀;ready 阶段要只在能处理请求时返回成功;运行阶段要输出可观测日志和指标;终止阶段要处理 SIGTERM,停止接新请求并等待正在处理的请求结束。

不要让 livenessProbe 承担业务依赖判断。数据库短暂不可用时,应用可能应该暂时不 ready,而不是被重启。重启不能修复外部依赖故障,反而可能造成连接风暴。readiness 和 liveness 的边界,是后端 Kubernetes 稳定性的基础。

Pod 本地文件系统也要谨慎使用。Pod 可以重建,本地状态会丢失。临时文件可以写 emptyDir,业务数据应该放外部存储或数据库。把关键业务状态写在 Pod 本地目录里,是和 Kubernetes 可替换实例模型冲突的。

8.2 资源、调度和高可用边界#

资源配置要来自压测和线上指标。requests 决定调度容量,limits 决定运行上限。后端团队要知道自己的服务在不同 QPS 下的 CPU、内存、线程、连接池和延迟表现。没有这些数据,Kubernetes 只能执行你写的数字,不能替你判断是否合理。

高可用还需要考虑 Pod 分布。多个副本如果都调度到同一节点,节点故障会同时影响全部副本。生产环境可以通过 topology spread constraints、pod anti-affinity 或平台默认策略让副本分散。但这些策略也会增加调度约束,需要和资源容量一起评估。

Deployment 不适合所有工作负载。无状态 API 用 Deployment;有状态服务可能用 StatefulSet;一次性任务用 Job;定时任务用 CronJob;节点级守护进程用 DaemonSet。选错工作负载对象,会让后续治理非常别扭。

8.3 发布、回滚和观测边界#

rollout 成功只是 Kubernetes 视角的成功,不等于业务成功。业务还要看错误率、延迟、吞吐、关键接口、日志和 trace。一个版本可能所有 Pod 都 ready,但业务逻辑错误仍然存在。生产发布需要 Kubernetes 状态和业务指标共同验收。

回滚也有边界。Deployment 可以回滚 Pod 模板,但不能自动回滚数据库 schema、消息格式、缓存数据和外部配置。后端发布要保持向前兼容,数据库迁移要能安全回滚或双写过渡。不要把 kubectl rollout undo 当成万能撤销按钮。

观测要围绕对象链路组织。Deployment 看 rollout,ReplicaSet 看版本副本,Pod 看事件和日志,Node 看资源和状态,Service 看 endpoints。业务层再看指标、日志和 trace。只有平台证据和业务证据结合,事故复盘才不会停留在“Pod 重启了”这种表面描述。

9. 什么时候用,什么时候不用#

Pod、Node 和 Deployment 是 Kubernetes 无状态服务的基础,但不是所有场景都应该用 Deployment。

9.1 适合使用 Deployment 的场景#

无状态 HTTP API、内部 RPC 服务、后台消费者、网关层服务,通常适合 Deployment。它们可以水平扩副本,实例之间没有稳定身份要求,状态在外部数据库、缓存或消息系统中。

需要滚动发布、快速回滚和副本自愈的服务,也适合 Deployment。Deployment 能保留历史 ReplicaSet,能逐步替换旧版本,能在 Pod 异常时创建新副本。前提是应用本身支持健康检查、优雅关闭和无状态运行。

团队想统一后端交付模板时,也应该从 Deployment 开始。它是 Kubernetes 中最常见的后端工作负载模型,和 Service、Ingress、ConfigMap、Secret、HPA、监控等对象都能自然组合。

9.2 不适合使用 Deployment 的场景#

需要稳定网络身份和稳定存储身份的有状态组件,不应该默认使用 Deployment。数据库、部分消息队列和有状态集群组件更可能需要 StatefulSet,或者直接使用外部托管服务。

一次性数据库迁移、批处理、初始化任务,不适合长期 Deployment。它们更适合 Job 或 CronJob。用 Deployment 跑一次性任务,会让控制器不断维持副本,和任务完成语义冲突。

每个节点都要运行一个实例的组件,例如日志采集 agent、网络插件、节点监控 agent,也不适合 Deployment。它们通常应该用 DaemonSet,让每个目标 Node 上运行一个 Pod。

9.3 默认建议#

默认建议是:后端无状态 API 用 Deployment,配齐 resources、readinessProbe、livenessProbe、清晰 labels 和稳定镜像版本;外部入口交给 Service 和 Ingress;配置和密钥交给 ConfigMap/Secret;状态数据不要写在 Pod 本地。

排障默认顺序是:先看 Deployment rollout,再看 ReplicaSet,再看 Pod events 和 logs,再看 Node 与资源,最后结合业务指标。不要只看一条日志就下结论,也不要把所有问题都归因于 Kubernetes。

学习顺序上,先理解 Pod 和 Deployment,再理解 Service 和 Ingress。Pod 能不能稳定运行,是流量入口之前的基础;如果 Pod 自己都不 ready,Service 和 Ingress 配得再漂亮也没有意义。

10. 下一篇衔接#

下一篇会进入 Kubernetes Service 与 Ingress,重点解释流量如何从集群内部或外部进入后端 Pod。本文已经讲清楚 Deployment 如何维持后端 API 副本,但还没有解决稳定访问入口。Service 会负责选择 ready Pod 并提供稳定 DNS,Ingress 或 Gateway 会负责外部 HTTP/HTTPS 入口。

读下一篇前,可以先确认自己能回答:Pod 为什么不是稳定机器,Deployment 和 ReplicaSet 如何协作,Pod Pending 为什么通常没有应用日志,CrashLoopBackOff 和 ImagePullBackOff 有什么区别,readiness 和 liveness 为什么不能混用。

11. 官方参考#

第 8 篇:Kubernetes Pod、Node 与 Deployment
https://jupiter-ws.cn/posts/backend/container/08_kubernetes_pod_node_deployment/
作者
Jupiter
发布于
2026-07-05
许可协议
CC BY-NC-SA 4.0