写在前面
承接篇9 组件。本篇把那些组件串起来,演示两条最核心的调用链路:
- 管理面:一次
kubectl apply 怎么把一个 Deployment 跑起来(组件协作部署) - 数据面:一次外部 HTTP 请求怎么从公网打到 Pod(流量怎么进来)
读完这两条,“apiserver / etcd / controller / scheduler / kubelet / kube-proxy / CNI / CoreDNS / Ingress 这些到底怎么配合"就彻底通了——排查问题也知道该看哪个环节。
一、两条链路总览
1
2
3
4
5
6
7
8
9
10
11
| 管理面(控制流)—— 部署一个 Pod
你 → kubectl → apiserver → etcd → controller-manager → scheduler
→ kubelet → runtime → Pod Ready
这是"声明 → 调谐 → 执行"链路,组件靠 watch apiserver 协作
数据面(数据流)—— 一次外部请求
用户 → 公网 DNS → 外部入口(Gateway/Ingress/LoadBalancer 的具体实现)
→ Service 虚拟 IP 或后端地址 → 集群网络数据面 → Pod → container
这是"流量 → 路由 → 转发 → 到达"链路,靠网络组件 + 内核规则
|
两条链路分开看,但共享组件(apiserver 是管理面枢纽,kube-proxy / CNI 是数据面枢纽)。
二、管理面:kubectl apply 全流程
场景:kubectl apply -f deploy.yaml(一个 replicas: 3 的 Deployment)。
步骤拆解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| ① kubectl apply
kubectl 读 YAML;首次创建通常发 POST,apply 更新通常发 PATCH
附上 kubeconfig 里的证书/Token(认证)
② apiserver 收请求
认证(你是谁)→ 授权(你能执行该操作吗)→ mutating admission
→ 对象校验 → validating admission → 持久化
返回成功给 kubectl
③ etcd 存储
Deployment 对象持久化(期望状态:replicas=3,image=nginx)
此时还没有任何 Pod —— 只是"账本上记了要 3 个"
④ Deployment Controller(在 controller-manager 里)watch 到
它 watch apiserver 的 Deployment 资源
看到新 Deployment → 创建一个 ReplicaSet(版本 v1)
⑤ ReplicaSet Controller watch 到
看到新 RS 期望 3 副本,但当前 0 → 创建 3 个 Pod 对象(Pod 还没绑定节点)
⑥ kube-scheduler watch 到未调度的 Pod
对每个 Pod:过滤可用节点 → 打分 → 选定 → 通过 Binding 完成节点绑定
Pod 现在"知道"自己该跑在哪个节点
⑦ 目标节点的 kubelet watch 到分给自己的 Pod
kubelet 一直 watch apiserver:"有没有分给我的新 Pod?"
收到 → 调 CRI(containerd)拉镜像、起容器
挂载 volume、启动容器,并按配置执行 startup/liveness/readiness probe
⑧ kubelet 上报状态
Pod Running、容器就绪 → 写回 apiserver → etcd 更新实际状态
ReplicaSet Controller 看到实际=期望,停止创建
⑨ Service 数据面更新(如果有 Service)
EndpointSlice Controller 根据 Pod 和 Service selector 更新 EndpointSlice
kube-proxy 或替代它的数据面实现据此更新转发规则
现在 Service 的 ClusterIP 才能选择到就绪后端
⑩ 用户检查 Pod 的 Running、Ready 条件和 Deployment 可用副本
—— 链路闭合
|
关键认知:watch + reconcile
1
2
3
4
5
6
| 组件间不互相直连:
kubectl 不通知 controller,controller 不通知 scheduler
主要靠 API Server 上的 watch、list 和写操作协作;etcd 不直接暴露给这些客户端组件
控制器观察状态后主动写入下一步对象并持续 reconcile
这构成了 K8s 的事件驱动与声明式控制循环
|
排查 Pod 没起来:① kubectl get 卡在 Pending → scheduler 问题(资源 / 亲和);② ImagePullBackOff → kubelet 拉镜像失败;③ CrashLoopBackOff → kubelet 起了但容器崩(应用问题)。每个阶段对应不同组件,kubectl describe pod 的 Events 串起链路。
三、数据面:外部请求进 K8s 全流程
场景:用户访问 http://app.example.com,集群里有个 Ingress 把它路由到 web Service(后面 3 个 Pod)。
步骤拆解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| ① 用户浏览器:http://app.example.com
② 公网 DNS 解析 app.example.com → 一个公网 IP
这个 IP 是云 LoadBalancer / Ingress Controller 的对外入口
③ 流量到外部入口
它可能是云 LoadBalancer、Gateway 或 Ingress Controller 的前置负载均衡器
后续可能走节点端口,也可能由实现直接路由到节点或 Pod,不能假定只有 NodePort 一条路径
④ 所选 Gateway/Ingress 实现收到请求
读 Host: app.example.com,查 Ingress 规则
匹配到 → 找到目标 Service(web)
⑤ 控制器按实现解析 Service 与 EndpointSlice
EndpointSlice 记录 web Service 的后端地址及就绪状态
实现可以选择后端地址,也可以把流量交给 Service 虚拟 IP
⑥ 集群数据面把流量送往后端
某些控制器直接连接 EndpointSlice 中的 Pod IP,另一些会访问 Service ClusterIP
跨节点路径由所选网络实现完成,可能使用原生路由、overlay、eBPF 等机制
⑦ 流量到目标节点的 Pod 网络命名空间 → container 端口
container 处理请求,返回响应(原路或直接出网)
|
关键认知:入口路径由实现决定
1
2
3
4
| 不能把某个 Ingress Controller 的实现写成 Kubernetes 规范:
- ClusterIP 通常是虚拟 IP,由 kube-proxy 或替代数据面实现
- 控制器可能 watch EndpointSlice 后直连 Pod,也可能使用 Service ClusterIP
- 是否绕过 Service、怎样负载均衡、怎样处理连接排空,都要查具体控制器文档
|
四、对比:集群内 Pod 访问 Service
下面展示传统 kube-proxy 数据面的常见路径;使用替代数据面时,具体内核规则和转发位置会不同:
1
2
3
4
5
6
7
8
9
10
| 集群内 Pod → http://web-app(Service 名)
① CoreDNS 把 web-app 解析成 Service 的 ClusterIP(如 10.96.0.10)
② Pod 发包到 10.96.0.10:80
③ 包到达本节点内核 → 命中 kube-proxy 写的 iptables/nftables 等规则
④ 规则把目的地址 DNAT:10.96.0.10 → 某个真实 Pod IP(如 10.244.1.5)
⑤ CNI 把包路由到 Pod(本节点直连;跨节点靠 overlay/BGP)
⑥ Pod 收到
关键:ClusterIP 是"虚拟入口",真正干活的还是 Pod IP
kube-proxy 的规则就是"虚拟入口 → 真实 Pod"的映射
|
1
2
3
| 两种访问路径对比:
外部 → 入口实现 → Service ClusterIP 或 Pod IP(取决于实现)
内部 → Service 名 → CoreDNS → ClusterIP → Service 数据面 → Pod IP
|
五、组件在两条链路里的角色
1
2
3
4
5
6
7
8
9
| 管理面(apply)的主力:
apiserver(枢纽)/ etcd(账本)/ controller-manager(reconcile)
/ scheduler(调度)/ kubelet(执行)
数据面(请求)的主力:
CoreDNS(名字解析)/ Ingress Controller(七层路由)
/ EndpointSlice(后端列表)/ Service 数据面 / Pod 网络实现
共享:apiserver 是管理面 API 枢纽;具体网络实现负责数据面
|
六、按故障现象定位环节
1
2
3
4
5
6
7
8
9
10
| 现象 卡在哪 查
─────────────────────────────────────────────────────────────
kubectl apply 后 Pod 不出现 controller/调度 kubectl get events
Pod Pending scheduler kubectl describe pod(FailedScheduling)
ImagePullBackOff kubelet/runtime 镜像名/仓库权限
CrashLoopBackOff 应用 kubectl logs
Service 名解析失败 CoreDNS kubectl get pods -n kube-system(coredns)
Service ClusterIP 不通 Service/Pod 网络 EndpointSlice、数据面规则与跨节点连通性
Ingress 503/502 Ingress Controller kubectl describe ingress + controller 日志
外部访问超时 LB/Ingress 入口 LB 健康检查、NodePort、安全组
|
七、小结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| 管理面(kubectl apply):
apply → apiserver → etcd → controller 创建 RS/Pod
→ scheduler 选节点 → kubelet 起容器 → kube-proxy 更新规则
组件靠 watch apiserver 协作,不直连
数据面(外部请求):
公网 → DNS → 外部入口实现(Gateway/Ingress/LoadBalancer)
→ Service ClusterIP 或后端 Pod → 集群网络数据面
具体是否直连 Pod、使用何种规则,取决于控制器和网络实现
核心认知:
✓ apiserver/etcd 是管理面总线,组件 watch 它协作
✓ Service ClusterIP 通常是虚拟入口,由 kube-proxy 或替代数据面实现
✓ 入口控制器可能直连 Pod,也可能经过 ClusterIP,必须查看实现文档
✓ Pod 网络实现负责地址配置与跨节点连通,具体技术路径并不唯一
✓ 故障按"管理面 vs 数据面"先分流,再定位具体组件
|
至此 K8s 学习笔记 10 篇走完:资源怎么用(1-8)+ 组件是什么(9)+ 组件怎么协作(10)。配上本站「云托管 K8s 实战」5 篇(云上落地),K8s 从原理到生产就齐了。
参考资料