Kubernetes 是一个把“期望状态”存进 etcd,再由一组控制器不断把实际状态拉回期望的分布式系统。
用户提交的是期望状态:Deployment 要几个副本、Pod 用什么镜像、Service 选哪些标签。对象分为 spec(期望)和 status(实际),apiserver 负责认证、授权、准入、校验和持久化。kubectl apply 不是立即执行命令,而是提交或更新一份声明;真正的动作由控制器异步完成。声明式的好处是幂等和可对账,代价是结果不是同步返回的。
控制器持续 watch 资源变化,比较期望状态和实际状态,执行动作并更新 status。这个循环是 level-triggered 的:它不关心中间经历了多少次变化,只关心当前差异。Deployment 控制 ReplicaSet,ReplicaSet 控制 Pod,Node 控制器处理节点失联,kubelet 保证本节点容器运行。系统没有中央调度所有事情的“总控”,可靠性来自多个独立循环的收敛。
Pod 是最小调度单元,包含一个或多个共享网络 namespace、IP 和卷的容器。控制器通过标签选择器和 ownerReferences 管理 Pod:ReplicaSet 维持副本数,StatefulSet 提供稳定身份和顺序,DaemonSet 保证每节点一份,Job 追求完成。Pod 本身不是持久实体,删除后由控制器重建,名称和 IP 都会变化。容器只是 Pod 里的执行单元,不是调度边界。
Pod IP 会随重建变化,Service 提供稳定的虚拟 IP 和 DNS 名称。选择器匹配到的 Pod 会被写入 EndpointSlice,只有通过 readinessProbe 的 Pod 才会成为可用后端。kube-proxy 或 eBPF 数据面把访问虚拟 IP 的流量转发到后端,CoreDNS 负责名字解析。ClusterIP、NodePort、LoadBalancer 和 Headless 是不同暴露方式,Headless 直接返回 Pod 地址,常用于有状态服务。
kube-scheduler 监听尚未绑定节点的 Pod,先过滤掉不满足条件的节点(资源请求、污点与容忍、亲和性、PVC、端口),再对候选节点打分并绑定。绑定之后,目标节点的 kubelet 才拉镜像、创建容器并上报状态。Pod 处于 Pending 通常表示还没调度成功,或者容器尚未创建;此时应用日志往往不存在。requests 影响调度,limits 由 cgroup 在运行时强制执行。
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。
kubectl apply 会立即启动容器,忽略控制器和调度是异步的。requests 和 limits 混为一谈,不知道前者影响调度、后者影响运行时。合上页面,先回答,再展开对照。
kubectl describe pod 看 Events,检查资源不足、污点与容忍、亲和性、PVC 未绑定等原因。