一、简述
kube‑apiserver 负责解析、校验并保存 service.yaml;再由其他组件配合完成后续工作。 整个过程分 4 个角色分工,一步走通:
- kubectl(客户端工具):仅仅把 yaml 文本发送给 apiserver,它不做真正解析;
- kube‑apiserver(控制平面入口)【核心解析者】:解析 yaml 语法、校验字段合法性,校验通过后把 Service 对象存入 etcd;
- Endpoint 控制器(kube‑controller‑manager 内部的一个控制器) :监控新建的 Service,用
selector标签去匹配 Pod,自动生成 Endpoint(保存后端 Pod 真实 IP 列表); - 每个节点的 kube‑proxy:持续监听 apiserver,感知 Service/Endpoint 变化,在本机内核生成负载均衡规则;
- CoreDNS:监听 Service,把 service 名称解析成 ClusterIP,提供集群内域名解析。
完整时序(执行 kubectl apply -f service.yaml 时发生了什么)
- 你执行
kubectl apply -f service.yamlkubectl 读取本地 yaml 文件,原样转为 json,发送 HTTPS 请求给 apiserver。
kubectl 只是一个提交工具,不懂 K8s 资源业务逻辑,不会解析 selector、port 这些语义。
- apiserver 解析并校验这份 Service 定义 apiserver 内部解析 yaml/json:
- 识别
kind:Service - 检查 metadata.name、spec.selector、ports 等字段格式是否合法 校验没问题 → 将 Service 持久存入 etcd(集群数据库);
到此 Service 在集群创建成功,但还没有后端 Pod 列表,也没有转发规则。
- controller-manager 里的Endpoint 控制器开始干活 它一直 watch apiserver 的 Service 资源: 拿到新建的 Service,读取
spec.selector(例如app: queryB) 去 apiserver 查询所有标签匹配的 Pod,收集它们真实 PodIP,自动创建 Endpoint 资源存入 etcd。
⚠注意:我们不需要写 Endpoint.yaml,自动生成!
- 所有节点上的 kube‑proxy 感知 Service+Endpoint 变更 每个节点 kube‑proxy 持续 watch apiserver:一旦发现 Service 或者 Endpoint 改动,立刻更新本机内核 iptables/ipvs 负载均衡规则。
- CoreDNS(集群 DNS)同样监听 apiserver 中的 Service 自动把
metadata.name(service‑queryB)注册为 DNS 域名,集群 Pod 可以通过域名解析得到 ClusterIP。
重点误区澄清
- ❌不是 kube‑proxy 解析 service.yaml kube‑proxy 看不到你本地的 yaml 文件,它只从 apiserver 获取已经解析好的 Service/Endpoint 数据。
- ❌不是 kube‑controller-manager 解析 yaml controller-manager 不接收 yaml,只监控 apiserver 里已经保存好的资源。
- ❌CoreDNS 只负责域名解析,不处理负载均衡转发规则。
极简链条记忆
本地 yaml → kubectl (提交) → apiserver (解析 + 校验 + 存入 etcd) → Endpoint 控制器生成后端 IP 列表 → kube‑proxy 生成内核 LB 规则 → CoreDNS 提供域名解析
延伸对比(Deployment yaml 是谁解析)
deployment.yaml 同样由 apiserver 解析存入 etcd; 然后由Deployment 控制器(controller‑manager) 根据副本数创建 Pod。
apiserver 是所有 yaml 统一的解析和入库入口,所有控制器都只是被动监听 apiserver 的数据。
二、K8s yaml 提交后完整数据流简图(文字拓扑图)
以执行
kubectl apply -f service.yaml为例
【你的电脑/管理节点】
↓读取本地文本yaml(kubectl只负责转发,不解析业务逻辑)
kubectl客户端
↓HTTPS发送JSON请求
┌────────────────────────────────┐
│ kube‑apiserver │←【唯一解析、校验yaml的组件】
│ 1.解析yaml字段,语法校验 │
│ 2.合法数据存入etcd集群数据库 │
└───────────┬────────────────────┘
│数据变更事件通知(watch机制)
┌─────────┴──────────┬────────────────┬────────────────┐
▼ ▼ ▼ ▼
【controller-manager】 【所有节点kube‑proxy】【CoreDNS】
Endpoint控制器 每个节点独立监听 集群DNS服务
1、读取Service的selector标签 ↓ ↓
2、查询匹配标签的PodIP 在本机内核 注册域名:service‑xxx
3、自动生成Endpoint资源 创建ipvs/iptables规则 解析得到ClusterIP
存入etcd (负载均衡转发规则)
再补充 Deployment 的数据流(deployment.yaml)
kubectl apply -f deployment.yaml
↓
kube‑apiserver(解析校验存入etcd)
↓watch事件
【controller-manager中Deployment控制器】
↓根据副本数,向apiserver提交创建Pod请求
kube‑apiserver
↓watch事件
【scheduler调度器】挑选合适worker节点
↓通知apiserver绑定节点
kube‑apiserver
↓watch事件
目标节点上【kubelet】
↓拉起容器,生成Pod
两条链路合并一句话总结分工
- apiserver:总入口,解析 yaml、存数据,所有组件都监听它的变更事件
- controller-manager 包含很多内置控制器(Deployment 控制器 / Endpoint 控制器),负责业务逻辑
- kube‑proxy、CoreDNS、kubelet 都是被动订阅者,不会读取本地 yaml,只从 apiserver 拿已经解析完成的数据
- kubectl 只是提交工具,没有任何业务解析能力
业务 A 调用业务 B 完整串联整条端到端链路
- 运维提交 service‑queryB.yaml → apiserver 解析入库
- Endpoint 控制器收集 B 的 PodIP 生成 Endpoint
- 所有节点 kube‑proxy 生成内核负载均衡规则
- CoreDNS 注册域名 service‑queryB
- 业务 A Pod 发起调用 http://service‑queryB
- Pod 内 DNS 查询 CoreDNS → 返回 ClusterIP
- 本机内核 ipvs/iptables 规则匹配 ClusterIP,负载均衡转发到某个真实 B Pod
三、拓扑:浏览器外网访问(Ingress‑Nginx + Service + kube‑proxy + CoreDNS)
整体架构文字图
外网浏览器
↓域名访问(www.query-a.com)
【Ingress‑Nginx Pod(七层负载)】
↓路由匹配成功,转发到Service域名 service‑queryA
【CoreDNS】←查询域名service‑queryA→返回ClusterIP
↓数据包目标地址=ClusterIP
【本机内核ipvs/iptables规则(kube‑proxy维护)】
↓四层负载均衡,随机转发
业务A‑Pod1、业务A‑Pod2、业务A‑Pod3
组件角色说明
- Ingress‑Nginx :外网唯一入口,七层 HTTP 负载,解析域名、路径、证书;不能直接识别 Pod 列表,只能转发给 Service。
- Service(ClusterIP):稳定虚拟入口,保存一组 Pod 集合;由 yaml 定义。
- CoreDNS:集群 DNS,把 service‑queryA 解析成 ClusterIP。
- kube‑proxy :监听 Service/Endpoint 变化,在所有节点内核生成转发规则,本身不中转数据包。
- Endpoint(自动生成,不用写 yaml):存放后端所有真实 PodIP。
完整时序分步拆解(结合 yaml)
1、运维编写两份 yaml 并部署
-
ingress.yaml:定义域名
www.query‑a.com,指向 service‑queryA -
service‑queryA.yaml:创建 Service,selector 匹配业务 A 的 Pod 标签
#ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-queryA
spec:
rules:
- host: www.query-a.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-queryA #指向Service名称
port:
number: 80#service-queryA.yaml
apiVersion: v1
kind: Service
metadata:
name: service-queryA
spec:
type: ClusterIP
selector:
app: queryA
ports:
- port: 80
targetPort: 8080
2、kubectl apply提交 yaml → apiserver 解析校验存入 etcd 3、Endpoint 控制器自动收集带app:queryA标签的 PodIP,生成 Endpoint 4、
- kube‑proxy 感知 Service/Endpoint 变更,所有节点内核写入 LB 规则
- CoreDNS 注册域名
service‑queryA,解析到 ClusterIP - Ingress 控制器(Ingress‑Nginx)监听 Ingress 资源,加载域名路由规则
5、用户浏览器发起请求 http://www.query-a.com 6、流量到达 Ingress‑Nginx Pod,匹配 host 和 path,确定后端是service‑queryA:80 7、Ingress Pod 向 CoreDNS 解析service‑queryA,拿到 ClusterIP 8、数据包发给 ClusterIP,命中本机内核 ipvs/iptables 规则 9、内核负载均衡,转发到某一个真实业务 A Pod,处理请求原路返回
两条流量路线对比(重点分清边界,不容易混淆)
路线 1:外部浏览器 → Ingress‑Nginx → Service → Pod(外网访问)
Ingress 负责七层路由、外网接入 ;Service+kube‑proxy 负责集群内部四层负载均衡 ✅Ingress 不能替代 Service,二者必须配合!
路线 2:集群内部 业务 A Pod 调用业务 B Pod(微服务互相调用,无 Ingress 参与)
业务 A Pod → CoreDNS 解析 service‑queryB → ClusterIP → kube‑proxy 内核 LB → 业务 B Pod 👉内部调用完全不走 Ingress
汇总一张全链路组件分工清单
- apiserver:接收所有 yaml,解析校验,存入 etcd;所有组件监听它
- Ingress‑Nginx:外网入口,七层 HTTP 负载(外部流量专用)
- Service:定义一组 Pod 的稳定访问域名 / 虚拟 IP
- Endpoint(自动生成):后端 Pod 真实 IP 清单
- kube‑proxy:维护内核转发规则,四层负载均衡(不处理 HTTP 协议)
- CoreDNS:集群域名解析
- Deployment:管理 Pod 副本数量,滚动更新
常见误区再次总结
- ❌Ingress 直接转发到 Pod:不行,Ingress 后端只能填 Service
- ❌Ingress 负责 Pod 之间内部调用:不行,内部 Pod 访问不需要 Ingress
- ❌kube‑proxy 处理 HTTP 域名、路径:不行,它只做四层 TCP/IP 转发,不懂 HTTP
- ❌CoreDNS 做负载均衡:不行,DNS 只返回 IP,负载均衡由内核 ipvs/iptables 完成