K8s 学习笔记(九):架构与核心组件

写在前面

承接前八篇。前面讲了 Pod/Deployment/Service/配置/调度/安全/运维——都是"资源怎么用"。本篇补上地基:K8s 到底由哪些组件组成、各自干什么。

篇1 的架构概览只列了组件名,这篇把每个组件掰开讲透:控制平面、工作节点、插件体系。理解组件,才能看懂下一篇(篇10)的调用链路——一次 kubectl apply、一次外部请求,在组件之间到底怎么流转;也才能排查"Pod 没调度上"“Service 不通"这类深层问题。


一、K8s 架构总览

K8s 是主从架构:一个控制平面(Control Plane,俗称 master)管着一堆工作节点(Worker Node)。控制平面是"大脑”,工作节点是"手脚"。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
                    ┌─────────────────────────────────┐
                    │       Control Plane(控制平面)  │
                    │  ┌──────────┐ ┌───────────────┐  │
                    │  │apiserver │ │     etcd      │  │
                    │  └──────────┘ └───────────────┘  │
                    │  ┌────────────┐ ┌─────────────┐  │
                    │  │ scheduler  │ │ controllers │  │
                    │  └────────────┘ └─────────────┘  │
                    └─────────────────────────────────┘
                   kubectl / 应用 / 组件 都走 apiserver
        ┌──────────────┬──────────────┬──────────────┐
        ▼              ▼              ▼              ▼
   ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
   │ Worker1 │    │ Worker2 │    │ Worker3 │    │  ...    │
   │ kubelet │    │ kubelet │    │ kubelet │    │         │
   │kube-proxy│   │kube-proxy│   │kube-proxy│   │         │
   │ runtime │    │ runtime │    │ runtime │    │         │
   │  Pods   │    │  Pods   │    │  Pods   │    │         │
   └─────────┘    └─────────┘    └─────────┘    └─────────┘

三类角色:

  • 控制平面组件:决策(调度、reconcile)、存状态(etcd)、对外暴露 API(apiserver)
  • 工作节点组件:执行(跑 Pod、转发流量)
  • 插件(addons):必需但不在核心二进制里,以 Pod 形式跑在 kube-system 命名空间

二、控制平面(Control Plane)

2.1 kube-apiserver —— 唯一入口

整个集群唯一的对外接口。所有操作(kubectl、组件间通信、dashboard、CI/CD)都通过它。

1
2
3
4
5
6
7
职责:
  ✓ RESTful API(HTTPS),所有资源的 CRUD
  ✓ 认证(你是谁)→ 授权(你能干啥,RBAC)→ 准入(改不改请求体)
  ✓ 唯一能直接读写 etcd 的组件
  ✓ 无状态(状态全在 etcd),可水平扩展(多实例 + LB)

  口诀:apiserver 是"前台",etcd 是"账本",前台不存钱只转手

为什么所有组件都走 apiserver 而不直接读写 etcd?因为 apiserver 做认证 / 授权 / 准入 / 校验 / 乐观锁 / 审计 / watch 机制——这些不该让每个组件自己实现。集中到 apiserver,安全且一致。

2.2 etcd —— 集群的大脑

强一致性的键值存储,K8s 把所有集群状态(有哪些 Pod / Service / 节点 / 配置…)都存在 etcd 里。

1
2
3
4
5
6
7
特点:
  ✓ KV 存储(不是关系库),key 按资源路径组织
  ✓ Raft 共识协议:强一致(写要多数节点确认)
  ✓ 整个集群唯一有状态的组件 → 必须备份!
  ✓ etcd 挂了 = 集群失忆(apiserver 读不到现状,但已跑的 Pod 不影响)

  备份:etcdctl snapshot save;恢复 = 从快照重建

etcd 是 K8s 的"唯一真相源"。控制平面其他组件(apiserver / scheduler / controller)都是无状态的——它们从 apiserver(背后是 etcd)读状态、写期望。所以etcd 备份 = 集群备份

2.3 kube-scheduler —— 决定 Pod 跑在哪

新 Pod 创建后(还没绑定节点),scheduler 负责"给它选一个节点"。

1
2
3
4
5
6
7
调度两步:
  1. 过滤(Filter):哪些节点能用?(资源够、亲和、污点容忍、nodeSelector)
  2. 打分(Score):能用里挑最优(资源均衡、亲和优先、反亲和)

  选定后 → 写 Pod 的 nodeName(绑定),交给 kubelet 去起

  注意:scheduler 只"决定",不"启动"——启动是 kubelet 的活

Pod 卡在 Pending 多半是 scheduler 没找到合适节点(资源不足 / 亲和冲突 / 污点)。kubectl describe pod 看 Events 里的 FailedScheduling 是关键线索。

2.4 kube-controller-manager —— 调谐循环

跑一堆控制器,每个控制器管一类资源,核心是 reconcile(调谐)循环:持续观察"实际状态",趋近"期望状态"。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
内置控制器(部分):
  Deployment Controller   → 维持 N 个副本、滚动更新
  ReplicaSet Controller   → 维持 Pod 副本数(Deployment 底层用它)
  Node Controller         → 节点失联检测、标记 NotReady
  Endpoint Controller     → 维护 Service 的 Endpoints(哪些 Pod)
  ServiceAccount Controller → 保证每个 ns 有默认 SA
  Job / CronJob Controller → 批处理任务的完成 / 重试

  统一模式:
    期望状态(存在 etcd,如 replicas: 3)
       ↕  reconcile
    实际状态(从 apiserver 观察到的运行 Pod 数)
    不一致 → 创建 / 删除 Pod,直到匹配

这是 K8s “声明式"的本质:你声明 replicas: 3,controller 替你维持。Pod 挂了它补,多了它删——你不用写"创建 3 个 Pod"的命令,只声明期望。

2.5 cloud-controller-manager —— 云特定逻辑

把"和云厂商打交道"的逻辑从核心分离(节点管理 / 负载均衡 / 路由)。这样 K8s 核心不知道"是 Azure 还是 AWS”,云厂商各自实现自己的 CCM。

1
2
3
4
内部控制器:
  Node Controller    → 给云上 VM 打标签、检查存活
  Route Controller   → 配置云路由(Pod 网段到节点)
  Service Controller → 创建云 LoadBalancer(type=LoadBalancer 时)

自建集群通常不跑 CCM;云托管(AKS/EKS/GKE)一定跑——type=LoadBalancer 的 Service 就是 CCM 调云 API 建的。


三、工作节点(Worker Node)

3.1 kubelet —— 节点代理

每个节点上跑一个,管这个节点上的 Pod。

1
2
3
4
5
6
7
8
职责:
  ✓ 接收 apiserver 下发的 Pod 清单("这个节点该跑哪些 Pod")
  ✓ 调 container runtime(CRI)起 / 停容器
  ✓ 执行健康检查(liveness / readiness probe)
  ✓ 上报节点 / Pod 状态给 apiserver("这个 Pod Running / 这个节点 CPU 60%")
  ✓ 挂载 volume

  口诀:kubelet 是节点上的"包工头",按 apiserver 的图施工、汇报进度

3.2 kube-proxy —— 服务转发

每个节点上跑一个,负责 Service 的网络规则。

1
2
3
4
5
6
7
8
职责:
  ✓ 监听 Service / Endpoints 变化
  ✓ 在节点上维护 iptables 或 ipvs 规则:
      访问 Service 的 ClusterIP → DNAT 到某个 Pod IP
  ✓ 默认 iptables 模式(小集群),大规模用 ipvs(性能好)

  注意:kube-proxy 不真正转发流量(那是内核 netfilter 干的)
        它只是"写规则的人",规则匹配后内核改目的地址

Service 的 ClusterIP 是个"虚拟 IP",没有真实网卡。流量能到 Pod,全靠每个节点上 kube-proxy 写的 iptables / ipvs 规则做 DNAT。篇10 数据面链路会详演。

3.3 container runtime —— 跑容器

真正启动容器的组件,通过 CRI(Container Runtime Interface)和 kubelet 交互。

1
2
3
4
5
6
主流 runtime:
  containerd    ← 当前主流(Docker 内核部分独立出来)
  CRI-O         ← Red Hat 系(OpenShift 默认)
  Docker        ← 已弃(K8s 1.24 起移除 dockershim),新集群别用

  K8s 不关心你用哪个 runtime,只要实现 CRI 接口

“K8s 不再支持 Docker"的真相:K8s 通过 CRI 调 runtime,Docker 曾需要 dockershim 适配,1.24 移除了 shim。但 Docker 构建的镜像(OCI 格式)任何 runtime 都能跑——镜像照用,只是 K8s 不直接调 Docker daemon 了


四、组件协作一览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
kubectl apply → apiserver → etcd(存期望)
                           ↓ watch
              controller-manager(看到要 3 副本,创建 Pod 对象)
                           ↓ watch
                  scheduler(给 Pod 选节点,写 nodeName)
                           ↓ watch
            目标节点的 kubelet(收到,调 runtime 起容器)
              kube-proxy(Service 变了,更新 iptables)
                 Pod 跑起来,Service 可访问

每个组件都是独立被动的——它们不互相直接调用,而是通过 watch apiserver(背后 etcd)感知变化、各自干活。这种"事件驱动 + watch"的解耦是 K8s 架构的精髓。完整链路留篇10 详演。


五、插件体系(Addons)

addons 是"集群跑起来必需、但不在核心二进制里"的组件,以 Pod / DaemonSet 形式跑在 kube-system 命名空间。

1
2
3
4
5
什么是 addon:
  ✓ 不是 K8s 核心(不在 kubelet / apiserver 等二进制里)
  ✓ 但集群要正常工作离不开它们(DNS、网络、监控)
  ✓ 通常以 Deployment / DaemonSet 部署在 kube-system
  ✓ 可替换(CNI 选 Calico 还是 Cilium,DNS 用 CoreDNS 还是别的)

5.1 CoreDNS —— 集群 DNS

1
2
3
4
5
6
7
职责:Service 名字解析
  访问 http://web-app         → 同 ns 内解析到 Service ClusterIP
  访问 http://web-app.default  → 跨 ns 显式指定
  访问 web-app.default.svc.cluster.local → 完整 FQDN

  形式:Deployment(2 副本)+ Service,跑在 kube-system
  没它:Service 名字不通,只能用 IP(痛苦)

5.2 CNI —— Pod 网络

1
2
3
4
5
6
职责:给 Pod 分配 IP + 跨节点 Pod 互通
  主流:Calico(BGP / 网络策略强)、Cilium(eBPF,新锐)、Flannel(简单老牌)
  云托管:Azure CNI / Amazon VPC CNI / GKE alias(Pod 拿 VPC IP)

  没它:Pod 拿不到 IP、跨节点 Pod ping 不通
  K8s 核心(apiserver 等)不管网络——网络全是 CNI 插件干的

CNI 的对比详见本站「云托管 K8s 实战」系列,以及本系列网络篇(04)。

5.3 Metrics Server —— 指标源

1
2
3
4
5
职责:聚合各节点资源用量(CPU / 内存),通过 Metrics API 暴露
  下游:HPA(按 CPU 扩缩)、kubectl top(看节点 / Pod 占用)

  没它:HPA 不工作、kubectl top 报错
  形式:单 Pod,从 kubelet 的 summary API 抓数据

5.4 Ingress Controller —— 七层入口

1
2
3
4
5
职责:把外部 HTTP / HTTPS 流量按 Host / Path 路由到 Service
  主流:NGINX Ingress(最常见)、Traefik、HAProxy、云厂商 Ingress
  本质:一个反向代理 Pod + 读 Ingress 资源动态配置

  没它:Ingress 资源没人执行(声明了也没用)

5.5 CSI —— 存储插件

1
2
3
4
5
职责:对接具体存储后端(云盘、NFS、Ceph、分布式存储)
  三阶段:Provision(建卷)→ Attach(挂到节点)→ Mount(挂进 Pod)
  形式:一堆组件(Controller / Node Plugin)以 Pod 跑

  没它:PV / PVC 只能用手动建好的静态卷;动态分配靠 CSI

5.6 其他常见 addon

1
2
3
4
Dashboard          Web UI(生产慎开,安全风险)
认证 Webhook       扩展认证授权(对接 LDAP/OIDC)
Cluster Autoscaler 节点自动扩缩(节点不够加机器)
cert-manager       自动 TLS 证书(Let's Encrypt 等)

六、实地看:kubectl get pods -n kube-system

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kubectl get pods -n kube-system
# NAME                               READY   STATUS    AGE
# coredns-xxx-xxx                    1/1     Running   10d     ← CoreDNS addon
# etcd-master                        1/1     Running   10d     ← 控制平面(静态 Pod)
# kube-apiserver-master              1/1     Running   10d     ← 控制平面(静态 Pod)
# kube-controller-manager-master     1/1     Running   10d     ← 控制平面(静态 Pod)
# kube-proxy-xxxxx                   1/1     Running   10d     ← DaemonSet(每节点一个)
# kube-scheduler-master              1/1     Running   10d     ← 控制平面(静态 Pod)
# metrics-server-xxx-xxx             1/1     Running   10d     ← Metrics addon
# calico-node-xxxxx                  1/1     Running   10d     ← CNI(DaemonSet)

几个现象:

  • 控制平面组件是"静态 Pod”(由 kubelet 直接管,清单在 /etc/kubernetes/manifests),自建集群如此;云托管的控制平面你看不到(微软 / AWS / Google 替你跑了)。
  • kube-proxy / CNI 是 DaemonSet(每节点一个)。
  • addons 是普通 Deployment / DaemonSet

七、小结

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
K8s 组件全景:
  控制平面(决策 + 存状态)
    apiserver   唯一入口,认证授权
    etcd        集群状态库(唯一有状态,必须备份)
    scheduler   Pod 选节点
    controller-manager  reconcile 循环维持期望
    cloud-controller-manager  云特定逻辑
  工作节点(执行)
    kubelet     管 Pod 生命周期
    kube-proxy  写 Service 转发规则(iptables / ipvs)
    runtime     跑容器(containerd / CRI-O)
  插件(以 Pod 跑在 kube-system)
    CoreDNS / CNI / Metrics Server / Ingress Controller / CSI / ...
1
2
3
4
5
核心认知:
  ✓ 所有组件通过 apiserver(背后 etcd)通信,互相 watch,不直连
  ✓ 声明式 = 你写期望状态,controller / scheduler 替你维持
  ✓ apiserver 无状态可横扩;etcd 唯一有状态,是命脉
  ✓ 网络全靠 CNI、DNS 全靠 CoreDNS——K8s 核心不管这些

下一篇:调用链路深挖——一次 kubectl apply 在组件间怎么流转(管理面),一次外部 HTTP 请求怎么从公网打到 Pod(数据面),把本篇的组件全串起来。