Kubernetes 的对象模型只有放进真实的生产拓扑里,组件职责和故障边界才会变得清楚。控制面负责接受期望状态、保存状态并作出调度与调谐决策;节点侧负责把已经绑定到本节点的 Pod 变成容器、网络和存储挂载。两侧通过 API 对象协作,而不是彼此直接调用全部内部组件。

本文集中画出生产环境里最容易混淆的十四条关系:控制面与工作节点、API 请求、控制器、调度器、节点执行、服务流量、存储与网络插件、探针、滚动发布、节点故障、etcd 仲裁、备份恢复和多可用区部署。图中的路径采用 Kubernetes 官方文档当前公开的稳定机制;具体版本的 feature gate、默认值和版本偏斜范围仍应以目标版本文档为准。

控制面与工作节点

图 1:Kubernetes 控制面与工作节点的生产拓扑

flowchart TB
    U[kubectl / CI / Controller] --> LB[API Server 负载均衡入口]
    LB --> A1[kube-apiserver A]
    LB --> A2[kube-apiserver B]
    LB --> A3[kube-apiserver C]
    A1 & A2 & A3 --> E[(etcd quorum)]
    CM[kube-controller-manager<br/>leader election] --> A1
    S[kube-scheduler<br/>leader election] --> A2
    subgraph N1[Worker Node 1]
        K1[kubelet]
        R1[CRI runtime]
        P1[Pods]
        X1[kube-proxy 或等价数据面]
        K1 --> R1 --> P1
    end
    subgraph N2[Worker Node 2]
        K2[kubelet]
        R2[CRI runtime]
        P2[Pods]
        X2[kube-proxy 或等价数据面]
        K2 --> R2 --> P2
    end
    A1 & A2 & A3 <--> K1
    A1 & A2 & A3 <--> K2

API Server 可以多实例同时服务,controller-manager 和 scheduler 通常多副本部署但通过 leader election 保持单个活动领导者。kube-proxy 是可选组件:如果网络实现已经提供等价的 Service 转发能力,节点不必再运行 kube-proxy。

控制面组件的职责边界

图 2:API Server、etcd、scheduler 与 controller-manager 的职责分工

flowchart LR
    C[客户端] --> API[API Server<br/>认证、授权、准入、API]
    API <--> ETCD[(etcd<br/>持久化 API 状态)]
    API --> WATCH[Watch / List]
    WATCH --> CTRL[Controller Manager<br/>调谐期望状态]
    WATCH --> SCH[Scheduler<br/>为未绑定 Pod 选择节点]
    CTRL --> API
    SCH --> API
    API -. 不直接启动容器 .-> NODE[kubelet]

etcd 不承担调度或控制器逻辑,API Server 也不直接在节点上启动容器。调度器写回 Pod 的节点绑定结果,控制器持续写回对象变化,节点 kubelet 再观察与本节点相关的 PodSpec。

API 请求的写入路径

图 3:kubectl 写请求经过认证、授权、准入与持久化

sequenceDiagram
    participant K as kubectl
    participant A as kube-apiserver
    participant N as Authentication
    participant Z as Authorization
    participant M as Mutating Admission
    participant V as Validation / Validating Admission
    participant E as etcd
    K->>A: HTTPS API request
    A->>N: 识别调用者
    N-->>A: user / groups
    A->>Z: 检查 verb、resource、namespace
    Z-->>A: allow 或 deny
    A->>M: 对写请求执行变更准入
    M-->>A: mutated object
    A->>V: schema 与验证准入
    V-->>A: valid 或 reject
    A->>E: 持久化新状态
    E-->>A: revision / result
    A-->>K: API response

认证先确定身份,授权决定该身份能否执行动作,准入控制只处理已经通过授权的相关请求。动态准入 webhook 属于 API Server 请求链的一部分,超时与失败策略会直接影响写入可用性。

Deployment 的控制循环

图 4:Deployment、ReplicaSet 与 Pod 的分层调谐

flowchart TB
    D[Deployment<br/>期望版本与副本数] --> DC[Deployment Controller]
    DC -->|创建或缩放| NEW[新 ReplicaSet]
    DC -->|缩容| OLD[旧 ReplicaSet]
    NEW --> RSC[ReplicaSet Controller]
    OLD --> RSC
    RSC -->|创建或删除| P[Pods]
    P --> STATUS[Ready / Available 状态]
    STATUS --> D

Deployment 不直接管理每一个 Pod。它管理新旧 ReplicaSet 的比例,ReplicaSet 再维持 Pod 数量。滚动发布是否继续取决于可用副本、maxSurge、maxUnavailable 和就绪状态。

调度器的过滤、打分与绑定

图 5:一个 Pending Pod 的调度周期与绑定周期

flowchart LR
    Q[Scheduling Queue] --> PRE[PreFilter]
    PRE --> F[Filter<br/>排除不可行节点]
    F -->|无可行节点| POST[PostFilter<br/>可能触发抢占]
    F -->|可行节点集| SCORE[PreScore / Score<br/>加权排序]
    SCORE --> RES[Reserve]
    RES --> PERMIT[Permit]
    PERMIT --> BIND[PreBind / Bind / PostBind]
    BIND --> API[写回 spec.nodeName]

调度周期负责选节点,绑定周期负责应用这个决定。Filter 是硬约束,Score 是偏好;资源请求、亲和性、污点容忍、拓扑分布和卷绑定分别通过调度框架插件参与不同扩展点。

节点上的 Pod 执行链

图 6:kubelet 通过 CRI、CNI 与 CSI 落实 PodSpec

flowchart TB
    API[API Server 中已绑定的 PodSpec] --> K[kubelet]
    K --> CRI[CRI]
    CRI --> RT[containerd / CRI-O]
    RT --> S[Pod sandbox]
    S --> C[应用容器]
    RT --> CNI[CNI plugin<br/>配置 Pod 网络]
    K --> CSI[CSI node plugin<br/>stage / publish volume]
    K --> PROBE[startup / readiness / liveness probes]
    CNI --> NET[Pod IP 与路由]
    CSI --> VOL[容器挂载点]
    PROBE --> STATUS[Pod / Container 状态]
    STATUS --> API

kubelet 是节点执行的协调者,容器运行时负责容器生命周期,CNI 负责 Pod 网络,CSI node plugin 负责节点侧卷操作。探针结果由 kubelet执行并影响容器重启或 Pod 是否进入可服务端点。

Service、EndpointSlice 与入口流量

图 7:Service、EndpointSlice、Gateway/Ingress 的数据路径

flowchart LR
    EXT[外部客户端] --> GW[Gateway / Ingress 实现]
    IN[集群内客户端] --> VIP[Service ClusterIP / DNS name]
    GW --> VIP
    SVC[Service selector] --> ESC[EndpointSlice Controller]
    PODS[Ready Pods] --> ESC
    ESC --> EPS[EndpointSlices]
    VIP --> DP[kube-proxy 或等价 Service 数据面]
    EPS --> DP
    DP --> P1[Pod A]
    DP --> P2[Pod B]

EndpointSlice 是当前 Service 后端发现的标准 API。控制面根据 Service selector 和 Pod 状态维护切片,节点数据面读取 Service 与 EndpointSlice 后编程转发规则。Gateway API 或 Ingress 负责入口层路由,但必须有对应实现控制器和数据面才会生效。

CNI、CSI 与 CoreDNS 的边界

图 8:网络、存储与服务发现插件分别接入哪条链路

flowchart TB
    POD[Pod] --> DNS["/etc/resolv.conf"]
    DNS --> COREDNS[CoreDNS]
    COREDNS --> SVC[Service DNS records]
    POD --> VETH[Pod network namespace]
    VETH --> CNI[CNI implementation]
    CNI --> ROUTE[跨节点路由 / NetworkPolicy]
    POD --> MOUNT[volumeMount]
    MOUNT --> CSIN[CSI Node Plugin]
    CSIC[CSI Controller Plugin] --> STORAGE[存储后端 API]
    CSIN --> STORAGE
    PVC[PVC / PV / StorageClass] --> CSIC

CoreDNS 负责把名称解析成 Service 或 Pod 相关记录;CNI 负责网络命名空间、接口和路由;CSI 负责存储卷生命周期与挂载。三者都能以集群插件形式部署,但它们不是同一条数据路径。

探针与滚动发布

图 9:startup、readiness、liveness 对发布过程的不同影响

stateDiagram-v2
    [*] --> Starting
    Starting --> Starting: startup probe 失败但未超阈值
    Starting --> Restart: startup probe 超过失败阈值
    Starting --> RunningNotReady: startup probe 成功
    RunningNotReady --> Ready: readiness probe 成功
    Ready --> RunningNotReady: readiness probe 失败\n从 Service 端点移除
    Ready --> Restart: liveness probe 超过失败阈值
    RunningNotReady --> Restart: liveness probe 超过失败阈值
    Restart --> Starting

readiness 失败不会重启容器,只会阻止流量继续送入该 Pod;liveness 失败达到阈值后触发容器重启;startup probe 成功前,liveness 和 readiness 不执行。把三种探针指向同一个过严的下游依赖检查,可能把局部依赖故障放大成大面积重启。

滚动发布的容量边界

图 10:Deployment 滚动发布如何受可用性与容量约束

sequenceDiagram
    participant D as Deployment Controller
    participant N as New ReplicaSet
    participant O as Old ReplicaSet
    participant S as Service / EndpointSlice
    D->>N: 按 maxSurge 增加新 Pod
    N->>S: 新 Pod readiness 成功后进入端点
    S-->>D: availableReplicas 增加
    D->>O: 按 maxUnavailable 缩减旧 Pod
    O->>S: 终止端点退出
    loop 直到新版本达到期望副本
        D->>N: 继续扩新
        D->>O: 继续缩旧
    end

滚动更新需要同时满足调度容量和应用就绪条件。maxSurge 允许短时超出期望副本数,maxUnavailable 限制发布期间不可用副本数;PDB 主要约束自愿驱逐,不替代 Deployment 自身的滚动更新参数。

节点故障、驱逐与 PDB

图 11:节点故障与自愿维护使用不同的驱逐路径

flowchart TB
    H[Node heartbeat / Lease] --> NC[Node Controller]
    NC -->|节点不可达| TAINT[NoExecute taint 与 Pod 容忍计时]
    TAINT --> REPLACE[上层控制器在可用节点补 Pod]
    ADMIN[kubectl drain] --> EVICT[Eviction API]
    EVICT --> PDB{PDB 允许?}
    PDB -->|允许| TERM[优雅终止并重建]
    PDB -->|不允许| WAIT[阻塞或重试]
    PRESSURE[节点内存/磁盘压力] --> KUBELET[kubelet node-pressure eviction]
    KUBELET --> DIRECT[直接终止选中的 Pod]

PDB 保护的是通过 Eviction API 发起的自愿中断,不是所有故障的统一保险。节点压力驱逐由 kubelet执行,不遵守 PDB;节点失联后的处理还取决于 Node 条件、污点和 Pod 的容忍时间。生产设计需要副本分散、容量冗余和 PDB 共同配合。

etcd 仲裁与写入可用性

图 12:三个 etcd 成员用多数派提交控制面状态

flowchart LR
    API[kube-apiserver] --> L[etcd Leader<br/>AZ-A]
    L --> F1[etcd Follower<br/>AZ-B]
    L --> F2[etcd Follower<br/>AZ-C]
    L -. proposal .-> F1
    L -. proposal .-> F2
    F1 -. ack .-> L
    F2 -. ack .-> L
    L -->|多数派确认后提交| COMMIT[(Committed revision)]

三个成员可以容忍一个成员失效,五个成员可以容忍两个。增加偶数成员不会增加可容忍故障数,却会增加通信成本。etcd 失去多数派后,已运行的工作负载可能继续运行,但控制面不能可靠提交新的集群状态。

etcd 备份与恢复

图 13:快照备份、完整性校验与隔离恢复链路

flowchart LR
    LIVE[(运行中的 etcd)] --> SNAP[etcdctl snapshot save]
    SNAP --> CHECK[etcdutl snapshot status]
    CHECK --> STORE[异地加密存储]
    STORE --> TEST[定期恢复演练]
    TEST --> RESTORE[etcdutl snapshot restore\n写入新的 data-dir]
    RESTORE --> CFG[更新 etcd / API Server 指向]
    CFG --> VERIFY[验证 Nodes、Namespaces、Workloads]

当前官方运维文档建议用 etcdutl 执行恢复;etcdctl snapshot restore 在 etcd 3.5 起已弃用。快照只有经过状态校验、异地保存和恢复演练才构成可用备份。恢复期间控制面组件可能丢失 leader lock 并重启,因此恢复应在隔离、可回退的维护流程中完成。

多可用区生产拓扑

图 14:跨三个可用区部署控制面、etcd 与工作负载

flowchart TB
    CLIENT[运维与自动化客户端] --> LB[跨可用区 API 负载均衡]
    subgraph A[AZ-A]
        AAPI[API Server]
        AE[etcd member]
        AW[Worker pool A]
    end
    subgraph B[AZ-B]
        BAPI[API Server]
        BE[etcd member]
        BW[Worker pool B]
    end
    subgraph C[AZ-C]
        CAPI[API Server]
        CE[etcd member]
        CW[Worker pool C]
    end
    LB --> AAPI & BAPI & CAPI
    AAPI & BAPI & CAPI --> AE & BE & CE
    AE <--> BE
    BE <--> CE
    CE <--> AE
    AW & BW & CW --> LB
    APP[Deployment / StatefulSet] --> SPREAD[topologySpreadConstraints<br/>与反亲和性]
    SPREAD --> AW & BW & CW

多可用区只在故障域真正独立、负载均衡器健康检查正确、etcd 成员跨区分布、工作负载使用拓扑分散约束时成立。把三个控制面实例放在同一机架,再给它们不同名称,不会获得可用区级容错。

生产故障边界

控制面短时不可用时,节点上已经运行的容器不会因为 API Server 暂时不可达而立即退出,现有 Service 数据面规则通常也会继续工作;新建、扩缩容、重新调度和需要新控制面状态的操作会受阻。数据面是否继续可用还取决于 DNS、网络插件、证书、节点状态和应用自身依赖,不能把“已有 Pod 继续运行”扩展成“集群业务一定无损”。

etcd 多数派、API Server 入口、节点容量和应用副本是四个不同故障域。生产演练应分别验证:控制面实例丢失、单可用区丢失、节点失联、Service 后端变化、存储故障和备份恢复,而不是只做一次 Pod 删除测试。

系列导航

参考资料