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。

我们可以用一个“客服中心”的例子来完美解释这个三角关系:

  1. Service(400 客服热线): 企业对外公布的永远是一个固定的 400 电话(ClusterIP)。不管公司内部怎么裁员、招人,这个号码绝对不能变,它代表着稳定。
  2. Pod(真实的客服小哥): 真正在后台接听电话的人(Pod 真实的 IP)。他们随时可能下班、生病、离职(Pod 重启、被销毁)。
  3. 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)

  1. 真实链路:流量的真实走向其实是:Client -> Service(ClusterIP) -> kube-proxy 查阅 Endpoint 规则 -> 转发给具体的 Pod IP
  2. 解耦的艺术:Endpoint 承担了动态感知后端节点健康状态和地址变化的所有脏活累活,从而保全了 Service 对外的绝对稳定。
  3. 排障口诀:遇事不决查 EP(Endpoint)。有 EP 查网络插件(如 Calico),没 EP 查标签和探针!
看透了 Endpoint,你就掌握了 K8s 网络路由的任督二脉。下次集群网络再出玄学问题,直接敲下 kubectl get ep,真相就在那里。

阅读更多

再也不为底层发愁:用“租房模型”秒懂 Kubernetes 的 PV 与 PVC

如果你刚接触 Kubernetes,在搞定了 Pod 和 Deployment 后,往往会一头撞死在“持久化存储”的墙上。 在传统的单机时代,我们要存数据,直接把宿主机的目录挂载(Volume 映射)进容器就行了。但在 K8s 这种到处漂移的分布式集群里,如果 Pod 挂了,被重新调度到另一台机器上,它原本写在本地硬盘上的数据就全丢了。 为了解决这个问题,K8s 引入了网络存储(如 NFS、Ceph、阿里云云盘等)。但是,如果让写业务代码的程序员去关心底层挂载的是 Ceph 还是阿里云盘,还要写一堆复杂的连接配置,这就太反人类了。 于是,K8s 架构师们大笔一挥,发明了两个伟大的抽象概念:PV 和 PVC。 今天,我们不扯枯燥的官方文档,直接用“租房模型”让你秒懂这套机制。 🏠 角色一:

By GFrank

K8s 零信任实战:如何用 NetworkPolicy 拦截集群内的“非法访问”?

在很多人的潜意识里,Kubernetes 内部是一个绝对安全的“乌托邦”:只要把服务部署到了集群里,不暴露 NodePort 或者 Ingress,外部黑客就打不进来,内部服务也是绝对安全的。 但现实往往很骨感。Kubernetes 的默认网络模型是“扁平且全开放”的。 这意味着什么?这意味着如果你的集群里运行着一个电商系统和一个内部财务系统,只要它们在同一个集群网络下,电商系统里的任意一个微服务,都可以畅通无阻地 ping 通财务系统里的核心数据库!一旦某个边缘微服务存在漏洞被拿下,攻击者就能以此为跳板,在集群内部横向移动(Lateral Movement)。 今天,我们就来实战演练一把:如何打破这种“全连通”的默认状态,用 NetworkPolicy(网络策略) 给核心服务穿上防弹衣。 🔪 场景重现:合法的 API 与非法的“黑客” 假设我们在 auth-space 命名空间下,运行着一个极其重要的数据库服务 mysql(带有标签 db=mysql)

By GFrank
鄂ICP备2026019394号-1