Pod 是动态的:重建后 IP 可能变化,副本数量也会随扩缩容调整。Service 为一组 Pod 提供稳定访问入口,让客户端不需要跟踪每个 Pod 的地址。
一、Service 如何找到 Pod
大多数 Service 通过 selector 匹配 Pod 标签:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- name: http
port: 80
targetPort: 8080
如果 Pod 带有 app=web 标签,控制平面会为 Service 维护相应的 EndpointSlice。数据面实现再把访问 Service 的流量转发给可用后端。
检查关系时,不要只看 Service:
kubectl get service web -o yaml
kubectl get pod -l app=web --show-labels
kubectl get endpointslice \
-l kubernetes.io/service-name=web
Service 有 ClusterIP 但没有 EndpointSlice,通常意味着 selector 没有匹配到 Ready Pod,或者端口配置不正确。
二、port、targetPort 与 nodePort
port 是客户端访问 Service 时使用的端口。
targetPort 是后端 Pod 实际接收流量的端口,可以使用数字,也可以引用容器端口名称。
nodePort 只用于 NodePort 或部分 LoadBalancer 实现,是节点上对外开放的端口。
建议给容器端口命名,并让 targetPort 引用名称。这样应用容器端口变化时,Service 规则更容易维护。
三、ClusterIP
ClusterIP 是默认类型,只在集群网络内提供虚拟 IP 和 DNS 名称:
web.default.svc.cluster.local
同一命名空间通常可以直接使用 web 访问。跨命名空间访问时,可以使用 web.default 或完整域名。
ClusterIP 适合内部微服务、数据库代理和不需要直接暴露公网的应用。
四、NodePort
NodePort 在每个符合条件的节点上开放同一个端口,客户端可以通过 NodeIP:NodePort 访问。
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 8080
它适合实验、受控内网入口或作为某些外部负载均衡器的后端,但不适合大量服务直接暴露公网。还应结合节点防火墙、安全组和 source IP 策略评估风险。
五、LoadBalancer
LoadBalancer 请求云厂商或集群内负载均衡实现创建外部入口。能否获得外部地址、如何收费、健康检查和 source IP 如何保留,都取决于具体环境。
kubectl get service web -w
如果 EXTERNAL-IP 长期 Pending,常见原因是集群没有配置负载均衡控制器、云权限不足、配额不足或注解参数错误。
不要继续依赖已经弃用且语义不统一的 spec.loadBalancerIP。固定地址的配置方式应遵循云厂商或负载均衡实现的当前文档。
六、ExternalName
ExternalName 不创建代理或虚拟 IP,而是通过 DNS CNAME 把集群内名称映射到外部域名:
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.example.com
它适合做 DNS 级别的名称抽象,但 HTTP Host 和 TLS 证书可能因为访问域名与真实目标域名不同而出现问题。
七、Headless Service
把 clusterIP 设置为 None,可以创建 Headless Service:
apiVersion: v1
kind: Service
metadata:
name: database
spec:
clusterIP: None
selector:
app: database
ports:
- port: 5432
Headless Service 不提供普通虚拟 IP 负载均衡,DNS 会返回后端端点地址。它常用于 StatefulSet、成员发现或客户端自己选择后端的场景。
八、没有 selector 的 Service
Service 也可以不写 selector,再由管理员或控制器维护 EndpointSlice,把 Kubernetes 服务名映射到集群外或特殊后端。
这种方式需要谨慎:地址生命周期、健康检查和安全责任不再由普通 Pod selector 自动管理。EndpointSlice 中也不能把另一个 Service 的 ClusterIP 当作后端地址。
九、Service 与 Ingress 的关系
Service 主要提供稳定服务发现和四层转发;Ingress 或 Gateway 负责按 HTTP Host、Path 等七层规则把外部流量路由到 Service。
常见链路是:
客户端 → LoadBalancer/Ingress Controller → Service → EndpointSlice → Pod
Ingress 后端配置正确但访问失败时,仍需要继续检查 Service selector、EndpointSlice 和 Pod readiness。
十、常见故障排查
先确认 DNS:
kubectl run -it --rm dns-test \
--image=registry.k8s.io/e2e-test-images/agnhost:2.39 \
--command -- nslookup web.default.svc.cluster.local
检查 Service 和后端:
kubectl describe service web
kubectl get endpointslice \
-l kubernetes.io/service-name=web -o wide
kubectl get pod -l app=web -o wide
再从集群内直接测试 Service:
kubectl run -it --rm curl-test \
--image=curlimages/curl -- \
curl -v http://web:80/
重点检查:
1. selector 与 Pod 标签是否完全匹配。
2. Pod 是否 Ready。
3. targetPort 是否为容器实际监听端口。
4. NetworkPolicy 是否允许流量。
5. kube-proxy 或替代的数据面是否正常。
6. NodePort、LoadBalancer 的安全组和健康检查是否正确。
总结
Service 把动态 Pod 变成稳定服务。ClusterIP 用于集群内部,NodePort 在节点开放端口,LoadBalancer申请外部入口,ExternalName 提供 DNS 映射,Headless Service 则把后端发现交给客户端。排障时,Service、EndpointSlice、Pod 标签和 readiness 必须一起检查。
参考资料:
https://kubernetes.io/docs/concepts/services-networking/service/
https://kubernetes.io/docs/tasks/debug/debug-application/debug-service/