EndpointSlice 到底解决了 Endpoints 的什么问题?后端多了会怎样拆分?一个 Pod 变化时 kube-proxy 要重新接收多少数据?Pod 终止期间 endpoint 的状态是什么?这篇在真集群里把一个 Service 的后端扩到 205 个,逐项看出来。
Service s3 有 1 个 EndpointSlice;名字 s3-ls98l;labels={'endpointslice.kubernetes.io/managed-by': 'endpointslice-controller.k8s.io', 'kubernetes.io/service-name': 's3'}
addressType=IPv4;ports=[('', 80, 'TCP')];ownerReferences=[('Service', 's3')]
endpoints[0]:addresses=['10.244.1.45'];conditions={'ready': True, 'serving': True, 'terminating': False};nodeName=kx-main-worker;targetRef=Pod/s3-756c4bd7f-v82f9…
共 3 个 endpoint,与 Pod 数一致:True
旧的 Endpoints 对象 s3 也还在,含 3 个地址(kubectl 会提示 v1 Endpoints is deprecated in v1.33+,由控制器同时维护)3 个 Pod 的 Service s3 有 1 个 EndpointSlice,带标签 kubernetes.io/service-name=s3 和 endpointslice.kubernetes.io/managed-by=endpointslice-controller.k8s.io,ownerReference 指向 Service。每个 endpoint 有 addresses(Pod IP)、conditions(ready/serving/terminating)、nodeName、指向 Pod 的 targetRef。旧的 Endpoints 对象还在被同步生成,kubectl 提示 v1 Endpoints is deprecated in v1.33+。
扩到 205 个副本,22 秒后所有 Pod 都进了切片:3 个 EndpointSlice,各含 [100, 100, 5] 个 endpoint 同一个 Service 的 Endpoints 对象:205 个地址,JSON 34891 字节;其中最大的一个 EndpointSlice(100 个 endpoint)的 JSON 24749 字节
扩到 205 个副本,22 秒后 3 个切片里装下了所有 Pod,分别是 100、100、5 个 endpoint(默认每片最多 100 个)。同一个 Service 的 Endpoints 是单个对象,含 205 个地址,JSON 有 34891 字节;最大的 EndpointSlice(100 个 endpoint)是 24749 字节。后端越多,Endpoints 越大。
删掉 1 个 Pod 之后(Deployment 会补一个新的):1 个 EndpointSlice 的 resourceVersion 变了(共 3 个);Endpoints 对象 resourceVersion 110321 → 110344 watch 的客户端(kube-proxy)收到更新时:Endpoints 要整个对象(34891 字节)重发一遍,EndpointSlice 只重发变了的那个切片(约 24749 字节) 缩回 3 个副本:切片数 1(空的切片会被回收,可能保留一个)
删掉 1 个 Pod 后 Deployment 补了一个新的:3 个切片里只有 1 个的 resourceVersion 变了(这次删除和新增落在同一个切片里;不同位置可能触发 2 个)。Endpoints 则必须整个 34891 字节的对象重发给每个 watch 的客户端(kube-proxy 每个节点一个)。缩回 3 个副本后切片数回到 1:空的切片会被回收。
Pod t4-7655bccb99-74… 终止前 endpoint 条件:{'ready': True, 'serving': True, 'terminating': False}
删除后 3 秒(sleep 作 1 号进程不理 SIGTERM,要等 40 秒的 terminationGracePeriod):{'ready': False, 'serving': True, 'terminating': True}
Service 的另一个 Pod 的条件仍是 ready:[{'ready': True, 'serving': True, 'terminating': False}]
37 秒后这个 endpoint 从切片里消失(Pod 真正退出)Pod 正常时 conditions 是 ready=true, serving=true, terminating=false。kubectl delete 之后(sleep 作 1 号进程不处理 SIGTERM,要等 40 秒的 terminationGracePeriodSeconds)3 秒时变成 ready=false, serving=true, terminating=true:不再接收新流量,但仍标记为在服务;同一个 Service 的另一个 Pod 仍是 ready。约 37 秒后这个 endpoint 才从切片里消失。