Kubernetes 里的 Service 实现服务发现,本质上是把一组随时会漂移的 Pod IP 抽象成一个稳定的虚拟 IP 和 DNS 名称;负载均衡则由 kube-proxy 在节点上维护转发规则,把流量按策略分散到后端 Pod。 你可以把 Service 理解为集群内部的一个“固定前台”,后端 Pod 怎么重启、扩容,前台地址都不变,这个机制贯穿整个集群网络,也是生产环境服务暴露的第一步。
Kubernetes Service 服务发现原理是什么?从 Pod 漂移说起
Pod 在 Kubernetes 里是短暂的,每次重建,IP 都会变,直接依赖 Pod IP 会让服务间调用变成灾难,Service 的解决办法是引入中间层。
- Service 通过 selector 匹配一组 Pod 的标签,只要 Pod 标签不变,哪怕 Pod 换 IP,也会被自动纳入后端列表。
- 后端列表存储在两个对象里:传统 Endpoints 和新版 EndpointSlice,EndpointSlice 把大列表拆成小块,适合大规模集群,避免单个对象过大拖慢更新。
- 集群内每个节点上的 kube-proxy 会监听 Service 和 Endpoints 变化,更新本机 iptables 或 IPVS 规则。
- DNS 服务(通常是 CoreDNS)为每个 Service 生成一条 A/AAAA 记录,格式为
<service>.<namespace>.svc.cluster.local。
实操验证可以这样走:
kubectl get svc kubectl get endpoints <service-name> kubectl run curl-test --image=curlimages/curl -it --rm -- sh curl http://<service-name>.<namespace>.svc.cluster.local:8080
当你访问这个域名时,CoreDNS 先把它解析成 ClusterIP,随后包被送到某个节点,由 iptables/IPVS 规则改写成某个 Pod 的地址,这就是服务发现与转发的完整链路,业内专家指出,这种解耦方式让服务间调用不再依赖固定 IP,是 Kubernetes 能被大规模采用的关键设计之一。
Service 负载均衡和 Ingress 有什么区别?先分清四层与七层
这个对比问题经常出现在集群网络设计阶段,简单说:Service 主要工作在 OSI 四层,Ingress 工作在七层。
| 对比项 | Service(四层) | Ingress(七层) |
|---|---|---|
| 处理协议 | TCP/UDP/SCTP | HTTP/HTTPS |
| 流量入口 | ClusterIP/NodePort/LoadBalancer | 域名 + 路径 |
| 路由依据 | IP 和端口 | Host 头、URL 路径 |
| 典型场景 | 内部微服务、数据库、缓存 | 外部 HTTP API、Web 控制台 |
| 是否直接暴露 | 视类型而定 | 通常配合控制器 |
实际链路里,Ingress 并不会替代 Service,外部流量先到 Ingress Controller,再由它转发到后端的 Service,最终到达 Pod,也就是说,Ingress 帮你解决“怎么根据域名和路径把 HTTP 请求分给不同服务”,Service 帮你解决“每个服务内部怎么把请求分给多个 Pod”。
一个常见误区是认为有了 Ingress 就可以不要 Service,Ingress 的后端配置里仍然要写 Service 名称和端口,二者是上下游关系,不是二选一。
生产环境 Service 怎么选型?ClusterIP、NodePort、LoadBalancer 实操对比
生产环境选错 Service 类型,轻则增加暴露面,重则造成不必要的云资源费用,先看四种主要类型:
- ClusterIP:默认类型,只在集群内可达,适合服务间调用,比如订单服务访问库存服务。
- NodePort:在集群每个节点上开一个固定端口,把流量转到 Service,端口范围默认
30000-32767,适合调试或临时对外暴露,不建议长期作为生产入口。 - LoadBalancer:调用云厂商接口创建外部负载均衡器,自动分配公网或内网地址,适合生产环境对外服务,但会按实例和带宽产生费用。
- ExternalName:把 Service 映射到外部 DNS 名称,常用于把外部数据库接入集群。
- Headless Service:设置
clusterIP: None,DNS 直接返回 Pod IP 列表,适合需要直接感知实例的场景,StatefulSet。
下面是一个 LoadBalancer 的基础示例:
apiVersion: v1
kind: Service
metadata:
name: web-frontend
spec:
type: LoadBalancer
selector:
app: web-frontend
ports:
- port: 80
targetPort: 8080
创建后可以这样查看外部地址:
kubectl get svc web-frontend -o wide
生产环境多数情况下会采用 Ingress + ClusterIP Service 的组合,而不是给每个服务单独建 LoadBalancer,这样既节省云负载均衡器费用,又方便统一管理 TLS 和路由规则。
云厂商 Kubernetes Service 价格对比与北京地区部署常见坑
提到 LoadBalancer,就绕不开云厂商 Kubernetes Service 价格对比,不同云平台对 LoadBalancer 型 Service 的计费方式有差异,但主要成本集中在三块:
- 负载均衡器实例费:按小时或按月收取。
- 带宽/流量费:按固定带宽或按实际流量计费。
- 跨可用区流量费:如果后端 Pod 分布在多个可用区,负载均衡器到非本可用区的 Pod 可能产生额外流量费。
以北京地区 K8s 服务发现配置为例,有几个实操层面容易踩的坑:
- 网段重叠:VPC 子网、Pod CIDR、Service CIDR 三者不能重叠,否则路由表会冲突,服务发现时通时断。
- 安全组放行:云负载均衡器到节点端口(NodePort)的流量必须放行,漏掉安全组规则会导致外部健康检查失败。
- kube-proxy 模式差异:部分云平台托管集群默认用 IPVS,部分用 iptables,IPVS 在高并发下性能更好,但排查规则需要不同命令。
-
地域与可用区:北京地区通常有多个可用区,跨可用区部署能提高可用性,但会带来额外延迟和流量成本。
检查 Service 是否正常暴露,可以通过以下命令验证:
kubectl get svc -n default kubectl describe svc web-frontend curl -I http://<EXTERNAL-IP>
EXTERNAL-IP 长时间显示 <pending>,多数情况下是云控制器创建负载均衡器失败,需要检查云账号权限、安全组和配额,行业共识认为,托管集群的网络问题排查,先从 Service 类型和云资源状态入手,往往比直接改应用配置更有效。
Kubernetes Service 的服务发现与负载均衡,不是某个单一组件的功劳,而是标签选择器、CoreDNS、kube-proxy、云控制器协同工作的结果,把 Service 当成稳定的逻辑入口,把 Pod 当成可替换的执行单元,集群网络的可预测性就会强很多。
Q&A:Kubernetes Service 服务发现与负载均衡常见问题
Service 的 ClusterIP 为什么 ping 不通?
ClusterIP 是虚拟 IP,只响应 Service 定义的端口,不实现 ICMP 协议,ping 不通是正常现象,不代表服务不可用,判断服务是否可用应使用 curl、telnet 或 nc 测试具体端口。
Headless Service 和服务发现有什么关系?
Headless Service 通过设置 clusterIP: None,让 DNS 查询直接返回后端 Pod 的 IP 列表,而不是返回一个 ClusterIP,这样客户端可以自行决定连接哪个 Pod,适合需要主从感知或分片感知的中间件,Kafka、Redis Cluster。
Service 负载均衡策略可以改成最少连接吗?
可以,但需要先将 kube-proxy 切换到 IPVS 模式,IPVS 模式支持轮询、最少连接、源地址哈希等调度算法,而传统 iptables 模式只提供随机选择,修改 kube-proxy 配置后需重启相关组件,具体算法可通过 ipvsadm -Ln 查看。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/641220.html




