Service 到底把流量发给了谁?解密 K8s 隐藏的功臣:Endpoint
在 Kubernetes 的日常操作中,你一定遇到过这样令人抓狂的场景: 你部署了一个 Nginx 的 Pod,状态是 Running;你又为它创建了一个 Service,IP 也分配了。一切看起来都很完美,但是当你用 curl 去访问这个 Service 时,得到的却是无尽的等待(Timeout)或者连接拒绝(Connection Refused)。
“我的 Pod 活得好好的,Service 也建了,流量到底死在哪个环节了?”
今天,我们就来揭开 K8s 网络中这个最容易被忽视的隐藏功臣——Endpoint 的神秘面纱。弄懂了它,你将掌握 K8s 内部网络排错的终极密码。
☎️ 通俗类比:客服热线与接线员
在传统的认知里,很多人以为 K8s 的网络拓扑是这样的: 外部流量 -> Service -> Pod IP
但实际上,Service 根本不直接和 Pod 打交道! 中间还隔着一个对象,它叫 Endpoint。
我们可以用一个“客服中心”的例子来完美解释这个三角关系:
- Service(400 客服热线): 企业对外公布的永远是一个固定的 400 电话(ClusterIP)。不管公司内部怎么裁员、招人,这个号码绝对不能变,它代表着稳定。
- Pod(真实的客服小哥): 真正在后台接听电话的人(Pod 真实的 IP)。他们随时可能下班、生病、离职(Pod 重启、被销毁)。
- Endpoint(内部通讯录系统): 如果 400 电话直接绑定客服小哥的私人手机,小哥一旦离职电话就打不通了。所以我们需要一个**“动态通讯录”**(Endpoint)。 这个通讯录时刻记录着:当前有哪些小哥坐在工位上,并且没在喝水上厕所(处于健康可接听状态)。 当有电话打进 400 时,系统会查阅这个通讯录,把电话转接给名单里的某一个真实的客服。
🔍 Endpoint 是怎么诞生的?
当你在 K8s 里写一个 Service 的 YAML 文件时,通常会写一个 selector(标签选择器),比如:
selector:
app: my-nginx
一旦你执行了 kubectl apply,K8s 内部的 Endpoint 控制器 就像一个不知疲倦的监工,开始满场寻找:
“全场所有带有 app: my-nginx 标签的 Pod 请注意!立刻把你们的 IP 地址报给我!”收集到这些 IP 后,K8s 会自动在后台默默创建一个与 Service 同名的 Endpoint 资源。
你可以随时通过这个命令查岗:
kubectl get endpoints my-nginx
或者
kubectl get ep my-nginx
你会看到类似这样的输出: Endpoints: 10.244.1.5:80, 10.244.2.10:80 这后面的 IP,就是目前真正能干活的 Pod 们的“私人电话”。
🚨 黄金排错指南:当 Service 访问不通时看什么?
记住 K8s 网络排错的第一定律:网络不通,先看 Endpoint 为不为空!
如果你发现 Service 访问报错,马上执行 kubectl describe svc <service名称> 或 kubectl get ep <service名称>。 如果你看到 Endpoints: <none>(空的!),说明通讯录里一个人都没有,流量自然无处可去。
为什么 Endpoint 会是空的?通常只有以下三种原因(请对号入座):
坑位 1:标签(Label)写错了 这是初学者最常犯的错。Deployment 里的标签明明写的是 app: web,结果在 Service 的 selector 里手抖写成了 app: wed。标签匹配不上,Endpoint 怎么可能抓得到 IP?
坑位 2:Pod 根本没启动成功 如果 Pod 还在 Pending,或者处于 CrashLoopBackOff(无限重启)状态,Endpoint 也是不会把它们的 IP 收录进来的。因为 K8s 不会把流量导给一个病号。
坑位 3:就绪探针(Readiness Probe)失败(高阶坑!) 这是最坑的一点!有时候你看 Pod 明明是 Running 状态,但 Endpoint 就是为空。 为什么?因为你可能配置了就绪探针(Readiness Probe)。虽然容器跑起来了,但探针发现你的 Java 程序还在疯狂加载几十兆的 Spring Bean,没准备好接客。 只要 Readiness Probe 没通过,Endpoint 就会立刻把这个 Pod 的 IP 从通讯录里无情剔除! 只有探针返回 200 OK,IP 才会重新加回 Endpoint。
💡 核心总结 (Takeaways)
- 真实链路:流量的真实走向其实是:
Client -> Service(ClusterIP) -> kube-proxy 查阅 Endpoint 规则 -> 转发给具体的 Pod IP。 - 解耦的艺术:Endpoint 承担了动态感知后端节点健康状态和地址变化的所有脏活累活,从而保全了 Service 对外的绝对稳定。
- 排障口诀:遇事不决查 EP(Endpoint)。有 EP 查网络插件(如 Calico),没 EP 查标签和探针!
看透了 Endpoint,你就掌握了 K8s 网络路由的任督二脉。下次集群网络再出玄学问题,直接敲下 kubectl get ep,真相就在那里。