kubernetes Service 详解
Kubernetes 的 Service 代表的是 Kubernetes 后端服务的入口,它主要包含服务的访问 IP(虚拟 IP)和端口,工作在 L4.
Service 只存储服务的入口信息(IP:PORT),不存储后端 Pod 信息,Service 是通过 Label Selector
选择与之匹配的后端 Pod。当被 Service 选择的后端 Pod 运行且能正常向外提供服务时,Kubernetes 的 Endpoint Controller
会生成一个新的 Endpoint 对象,指向此 Pod 的 IP:PORT。Service 接收到访问请求,会将请求转发到对应的 Endpoint。同时,Service 的访问 IP 和 Endpoint/Pod 的 IP 都会在 Kubernetes 的 DNS 服务里面进行注册以记录域名和 IP 的对应关系,因此用户可以在集群中通过域名的方式访问 Service 和 Pod。
用户创建 Service 后,Kubernetes 会从集群的可用服务 IP 池中为 Service 分配一个稳定的集群内访问 IP,称为 Cluster IP。Kubernetes 还会通过注册 DNS 条目为 Cluster IP 分配 域名(主机名)。Cluster IP 和 域名 在集群内是独一无二的,并且在服务的整个生命周期中保持不变,直到将 Service 从集群中删除,Kubernetes 才会释放 Cluster IP 和 域名 。通过此方法,Service 作为代理,向客户端提供了稳定不变的访问后端服务的入口。
Service 除了作为 代理 功能,同时也提供了 负载均衡 和 高可用。当后端的 Pod 有多个时,默认会通过 轮询 将请求流量均匀分布到多个 Pod 上,当某个 Pod 不可用是,Service 不会将请求调度到问题节点。
Kubernetes 使用节点上运行的 kube-proxy
组件管理各 Service 和后端 Pod 的连接。kube-proxy
是一个基于出战流量的 负载均衡控制器,它监控 Kubernetes API Service 并持续将 Service IP (ClusterIP)映射到运行状况良好的后端 Pod,具体实现是通过主机上的 iptables/IPVS
的规则。访问 Service 的 IP 会被这些(路由)规则直接 DNAT 到后端 Pod 的 IP。
环境信息
- Centos 7 3.10.0-1160
- Kubernetes v1.24.7
kube-proxy iptables 模式下的规则解析
kube-proxy 默认使用 iptables
模式实现 Service 的代理转发和负载均衡。检查 kube-proxy
使用的代理模式
本示例使用相关信息如下
kubectl get services |
针对 api-service
,后端的 Pod 就绪后,生成了 ENDPOINTS,kube-proxy 会为该服务创建以下 iptables 规则
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES |
具体工作流程如下:
- 所有进入
PREROUTING
链的流量会被跳转到KUBE-SERVICES
自定义链 - 本示例中请求
api-service
的访问数据包(目的地址为10.106.126.96:10302
)在PREROUTING
链中被-d 10.106.126.96/32 -p tcp -m comment --comment "default/api-service:api-pord cluster IP" -m tcp --dport 10302
匹配到,根据规则跳转到自定义链KUBE-SVC-DVTQLPR6DVOLBZS4
- 在自定义链
KUBE-SVC-DVTQLPR6DVOLBZS4
中,实现了负载均衡,一半的流量会被跳转到链KUBE-SEP-JXBL7O23XHVFQV2I
,另一半的流量会被跳转到KUBE-SEP-BBPDSOPRICLINLPY
- 在自定义链
KUBE-SEP-JXBL7O23XHVFQV2I
和KUBE-SEP-BBPDSOPRICLINLPY
中,流量分别被 DNAT 分配到了后端的 Pod(就绪的 Endpoints)。 - Pod 处理完数据请求,向客户端返回请求结果时,在
POSTROUTING
链上要对数据包做 SNAT 处理,以确保客户端接收到的数据包的源地址是其发送请求时的目标地址。
通过以上 kube-proxy 管理的规则,Service 实现了对后端 Pod 的服务代理及负载均衡功能。
综上所述,iptables 模式最主要的链是 KUBE-SERVICES
、KUBE-SVC-*
、KUBE-SEP-*
KUBE-SERVICES
- 访问集群服务的数据包入口,它会根据匹配到的目标 IP:PORT 将数据包分发到相应的链KUBE-SVC-*
KUBE-SVC-*
- 相当于一个负载均衡器,它会将数据包平均分配到KUBE-SEP-*
链。每个KUBE-SVC-*
链后面的KUBE-SEP-*
链的数量和 Service 后端就绪的 Pod 数量一致。KUBE-SEP-*
- 通过 DNAT 将数据包的目的地址(IP:PORT)修改为后端就绪的 Pod 的 IP:PORT,从而将流量转发到相应的 Pod
kube-proxy
的 iptables 模式因为使用 DNAT 转发数据包,存在一定的性能损耗,另外,当集群中的 Service 数量上万时,节点上的 iptables rules 会非常庞大,对管理是个不小的负担,性能也会大打折扣。