Kubernetes 心智模型:声明式状态、控制循环与调度

一句话模型

Kubernetes 是一个把“期望状态”存进 etcd,再由一组控制器不断把实际状态拉回期望的分布式系统。

核心概念

1. 声明式 API

用户提交的是期望状态:Deployment 要几个副本、Pod 用什么镜像、Service 选哪些标签。对象分为 spec(期望)和 status(实际),apiserver 负责认证、授权、准入、校验和持久化。kubectl apply 不是立即执行命令,而是提交或更新一份声明;真正的动作由控制器异步完成。声明式的好处是幂等和可对账,代价是结果不是同步返回的。

2. 控制循环

控制器持续 watch 资源变化,比较期望状态和实际状态,执行动作并更新 status。这个循环是 level-triggered 的:它不关心中间经历了多少次变化,只关心当前差异。Deployment 控制 ReplicaSet,ReplicaSet 控制 Pod,Node 控制器处理节点失联,kubelet 保证本节点容器运行。系统没有中央调度所有事情的“总控”,可靠性来自多个独立循环的收敛。

3. Pod 与控制器

Pod 是最小调度单元,包含一个或多个共享网络 namespace、IP 和卷的容器。控制器通过标签选择器和 ownerReferences 管理 Pod:ReplicaSet 维持副本数,StatefulSet 提供稳定身份和顺序,DaemonSet 保证每节点一份,Job 追求完成。Pod 本身不是持久实体,删除后由控制器重建,名称和 IP 都会变化。容器只是 Pod 里的执行单元,不是调度边界。

4. Service 与 Endpoint

Pod IP 会随重建变化,Service 提供稳定的虚拟 IP 和 DNS 名称。选择器匹配到的 Pod 会被写入 EndpointSlice,只有通过 readinessProbe 的 Pod 才会成为可用后端。kube-proxy 或 eBPF 数据面把访问虚拟 IP 的流量转发到后端,CoreDNS 负责名字解析。ClusterIP、NodePort、LoadBalancer 和 Headless 是不同暴露方式,Headless 直接返回 Pod 地址,常用于有状态服务。

5. 调度

kube-scheduler 监听尚未绑定节点的 Pod,先过滤掉不满足条件的节点(资源请求、污点与容忍、亲和性、PVC、端口),再对候选节点打分并绑定。绑定之后,目标节点的 kubelet 才拉镜像、创建容器并上报状态。Pod 处于 Pending 通常表示还没调度成功,或者容器尚未创建;此时应用日志往往不存在。requests 影响调度,limits 由 cgroup 在运行时强制执行。

6. etcd

etcd 是强一致的键值存储,保存整个集群的对象和状态,是事实来源。它用 Raft 达成共识,需要多数节点存活才能写入;apiserver 是主要客户端,控制器通过 apiserver watch 变化而不是直连 etcd。etcd 丢失或失去 quorum,集群就无法可靠读写,已运行的容器可能继续跑但无法调度和变更。备份、恢复和磁盘性能是控制面稳定性的核心。

概念关系

组件 读什么 写什么 失败后的现象
apiserver 请求、etcd etcd 对象 kubectl 超时、API 不可用
etcd 键值数据 Raft 日志 无法写入、leader 选举失败
控制器 watch 对象 spec/status 副本不符、资源不收敛
scheduler 未绑定 Pod、Node binding Pod 一直 Pending
kubelet 本节点 Pod 容器状态、status Pod 未启动、节点 NotReady
kube-proxy/eBPF Service、EndpointSlice 转发规则 Service 无后端、连接失败

期望状态从 apiserver 写入 etcd,控制器把差异转化为新对象,scheduler 决定 Pod 去哪,kubelet 在节点上执行,状态再回流到 apiserver。

常见误解

读完自测

合上页面,先回答,再展开对照。

  1. 为什么删除一个由 Deployment 管理的 Pod 后,Service 的访问地址仍然可用?
  2. Pod 一直 Pending,为什么通常没有应用日志?应该先看什么?
  3. etcd 失去 quorum 后,已经在运行的容器会怎样?
答案
  1. Deployment 的 ReplicaSet 控制器发现副本数不足,会创建新 Pod;新 Pod 的 IP 会变,但 Service 通过标签选择器把新 Pod 加入 EndpointSlice,虚拟 IP 和 DNS 名称保持不变,数据面把流量转发到新后端。
  2. Pending 表示 Pod 还没有被调度到节点,或者容器还没有创建,应用根本没有开始运行,所以没有日志。先 kubectl describe pod 看 Events,检查资源不足、污点与容忍、亲和性、PVC 未绑定等原因。
  3. 已运行的容器通常继续运行,kubelet 也会维持本节点状态;但 apiserver 无法可靠写入,控制器不能收敛,新的调度、发布、扩缩容和配置变更都会失败。恢复 quorum 后系统才能继续对账。

相关条目