Kubernetes Service

Service、EndpointSlice、CoreDNS、服务发现和集群内访问链路说明。

Kubernetes Service

Service 为一组 Pod 提供稳定访问入口。Pod IP 会随重建变化,Service 通过 selector 匹配 Pod,并通过 EndpointSlice 维护后端地址。

Service 类型

类型说明
ClusterIP集群内访问,默认类型
NodePort在每个节点暴露端口
LoadBalancer由云厂商或负载均衡控制器分配外部入口
ExternalName返回外部 DNS 名称
Headless ServiceclusterIP: None,直接返回后端 Pod 地址

ClusterIP

# API 版本。Service 是核心资源,使用 v1。
apiVersion: v1
# 资源类型。这里表示创建 Service。
kind: Service
metadata:
  # Service 名称,也是集群内 DNS 名称的一部分。
  name: order-api
spec:
  # Service 类型。ClusterIP 表示只在集群内访问。
  type: ClusterIP
  # 通过标签选择后端 Pod。
  selector:
    # 匹配 label app=order-api 的 Pod。
    app: order-api
  # Service 暴露的端口列表。
  ports:
    # 端口名称,便于区分多端口 Service。
    - name: http
      # Service 端口,客户端访问这个端口。
      port: 80
      # 后端 Pod 容器监听端口。
      targetPort: 8080

访问方式:

curl http://order-api.default.svc.cluster.local

NodePort

# API 版本。Service 是核心资源,使用 v1。
apiVersion: v1
# 资源类型。这里表示创建 Service。
kind: Service
metadata:
  # Service 名称。
  name: order-api-nodeport
spec:
  # NodePort 会在每个节点暴露一个端口。
  type: NodePort
  # 通过标签选择后端 Pod。
  selector:
    app: order-api
  ports:
    # Service 集群内端口。
    - port: 80
      # 后端 Pod 容器监听端口。
      targetPort: 8080
      # 节点上暴露的端口,默认范围通常是 30000-32767。
      nodePort: 30080

访问:

curl http://<node-ip>:30080

NodePort 适合测试或内部临时暴露,生产入口通常使用 LoadBalancer、Ingress 或 Gateway。

Headless Service

# API 版本。Service 是核心资源,使用 v1。
apiVersion: v1
# 资源类型。这里表示创建 Service。
kind: Service
metadata:
  # Headless Service 名称。
  name: redis-headless
spec:
  # None 表示不分配 ClusterIP,DNS 直接返回后端 Pod 地址。
  clusterIP: None
  # 通过标签选择后端 Pod。
  selector:
    app: redis
  ports:
    # Service 端口。
    - port: 6379
      # 后端 Pod 容器监听端口。
      targetPort: 6379

常用于 StatefulSet,让客户端直接发现每个 Pod。

EndpointSlice

查看 Service 后端:

kubectl get svc order-api -n default -o wide
kubectl get endpointslice -n default -l kubernetes.io/service-name=order-api
kubectl describe endpointslice -n default -l kubernetes.io/service-name=order-api

如果 EndpointSlice 为空,通常说明:

  • Service selector 和 Pod labels 不匹配。
  • Pod 未 Ready。
  • Pod 不在同一命名空间。

DNS

常见 DNS 名称:

<service-name>
<service-name>.<namespace>
<service-name>.<namespace>.svc
<service-name>.<namespace>.svc.cluster.local

测试 DNS:

kubectl run dns-test --image=busybox:1.36 -it --rm -- nslookup order-api.default.svc.cluster.local

访问链路

集群内访问通常是:

client pod -> service dns -> clusterIP -> kube-proxy / dataplane -> endpoint pod

排查时按顺序确认:

  1. DNS 是否解析。
  2. Service 是否存在。
  3. EndpointSlice 是否有后端。
  4. 后端 Pod 是否 Ready。
  5. targetPort 是否和容器监听端口一致。
  6. NetworkPolicy、CNI、防火墙是否拦截。

常见排查命令

kubectl get svc order-api -n default -o yaml
kubectl get pod -n default -l app=order-api -o wide
kubectl get endpointslice -n default -l kubernetes.io/service-name=order-api
kubectl describe svc order-api -n default

进入调试容器:

kubectl run netshoot --image=nicolaka/netshoot -it --rm -- bash

在调试容器中执行:

dig order-api.default.svc.cluster.local
curl -v http://order-api.default.svc.cluster.local
curl -v http://<pod-ip>:8080

常见问题

现象排查方向
DNS 解析失败检查 CoreDNS、Service 名称和命名空间
Service 有 IP 但不通检查 EndpointSlice、Pod Ready、targetPort
NodePort 不通检查节点防火墙、安全组、kube-proxy
访问偶发失败检查后端 Pod 健康、连接池、滚动发布窗口