Kubernetes 的流量调度是以 Pod 为单位还是以容器为单位?影响 Service 中记录是否可接受流量的,是 容器的 ready 状态还是 Pod 的?
在 Kubernetes 中,这两个问题的答案非常明确:
流量调度是以 Pod 为单位,而不是容器。
影响 Service 是否转发流量的,是 Pod 的就绪状态(由容器的就绪探针综合决定)。
下面为你详细解释原因:
1. 流量调度以 Pod 为单位
Pod 是调度的原子单位:Kubernetes 中最小的部署和调度单元是 Pod。一个 Pod 内可以有一个或多个容器,但它们共享网络命名空间(IP 地址、端口等)、存储卷(Volume)和 IPC 命名空间。
Service 的后端是 Pod:当创建 Service(例如 ClusterIP、NodePort 类型)并通过标签选择器(Label Selector)关联后端时,Service 的 Endpoint(或 EndpointSlice)列表中记录的是 Pod 的 IP 地址和端口,而不是容器的 IP(容器没有独立的节点网络 IP)。
负载均衡分发粒度:kube-proxy 或 Ingress Controller 在转发流量时,会将请求分发到不同的 Pod IP 上。同一个 Pod 内的多个容器访问同一个 Service 时,流量也会被均衡到不同的后端 Pod,而不会在容器级别做区分。
举例:假设有一个 Pod 里运行了 nginx 和 sidecar 两个容器,它们共享同一个 Pod IP 10.244.1.5。Service 的 Endpoint 只会记录 10.244.1.5:80(nginx 的端口)。发往该 Service 的流量全部到达这个 Pod IP,然后由 Pod 内部的网络栈根据端口决定交给哪个容器(这里 80 端口属于 nginx)。
2. 影响 Service 流量的关键是 Pod 的就绪状态
Service 是否将某个 Pod 的 IP 加入其负载均衡列表(Endpoint),取决于 Pod 的 Ready 条件。而这个条件是由 Pod 内所有容器的就绪探针(Readiness Probe) 共同决定的。
Pod 的就绪状态规则:一个 Pod 被认为是“就绪”的当且仅当 Pod 内的所有容器都处于就绪状态(即通过各自的就绪探针检查,或未定义探针时默认就绪)。
与容器 Ready 的关系:如果 Pod 内任何一个容器的就绪探针失败(或容器未运行),那么整个 Pod 就会被标记为 NotReady。Service 控制器会立刻将该 Pod 的 IP 从 Endpoint 列表中移除,停止向它转发新流量。
与容器 Running 状态的区别:容器仅仅是 Running(进程存在)并不代表它能正常提供服务(比如应用还在加载缓存、预热连接池)。就绪探针正是用来解决这个问题的——只有容器真正“准备好接收流量”时,才允许 Service 把流量放进来。
特殊情况:
如果 Pod 里只有一个容器,那么该容器的就绪状态直接决定 Pod 的就绪状态。
如果 Pod 里有多个容器,比如一个主容器和一个 sidecar 辅助容器,那么两个都必须就绪,Pod 才会被 Service 纳入后端。若 sidecar 探针失败,即使主容器完全正常,整个 Pod 也会被踢出 Service 的负载均衡。
总结对比表
问题
答案
原因
流量调度单位
Pod
Service 的 Endpoint 记录的是 Pod IP;kube-proxy 以 Pod 为目标做负载均衡。
决定是否接收流量
Pod 的就绪状态
Pod 的就绪状态由其所有容器的就绪探针逻辑与(AND)结果决定。只有所有容器都就绪,Pod 才会被加入 Service。
实践建议
如果你希望同一个 Pod 内的不同容器独立接收 Service 流量(例如一个提供 HTTP API,另一个提供 gRPC),你需要创建两个不同的 Service,分别使用不同的端口和标签选择器来指向同一个 Pod(但监听不同容器端口)。注意:此时流量到达 Pod 后,内核会根据目标端口自动路由到正确的容器。
在定义多容器 Pod 时,务必为每个容器都配置合适的就绪探针(尤其是那些需要初始化时间或会暂时不可用的辅助容器),否则 sidecar 容器一旦探针失败,整个 Pod 就会被 Service 剔除,导致主容器也无辜“掉线”。
Query
Pod 的就绪状态与容器 Ready 分别记录在哪个资源的哪个字段?
Pod 的就绪状态和每个容器的 Ready 状态,分别记录在 Pod 资源的不同字段中。要获取这些信息,可以通过 kubectl get pod <pod-name> -o yaml 来查看完整的 YAML 输出。
📝 核心字段详解
状态类型
资源
字段路径
取值
含义
Pod 整体就绪状态
Pod
.status.conditions 数组中 type: Ready 的 status 字段
"True", "False", "Unknown"
True:Pod 整体就绪,已列入 Service 负载均衡列表[reference:0]。 False:Pod 未就绪,已从 Service 的 Endpoint 中移除。
单个容器就绪状态
Pod
.status.containerStatuses[] 数组中对应容器的 .ready 字段
true, false
true:该容器已通过就绪探针检查[reference:1]。 false:容器未就绪。
Pod 所有容器就绪状态
Pod
.status.conditions 数组中 type: ContainersReady 的 status 字段
"True", "False", "Unknown"
True:Pod 内所有容器都处于就绪状态[reference:2][reference:3]。
🔗 与流量调度机制的关系
理解这些字段是理解 Kubernetes 流量调度原理的关键:
核心规则:一个 Pod 只有在其 Ready 条件为 True 时,才会被 Service 作为流量转发的后端。这是上一轮对话的核心结论。