3. Service ClusterIP与DNS服务发现验证

Service ClusterIP与DNS服务发现验证 学习卡片

从 Pod IP 到稳定服务入口

Deployment 管理的是 Pod 副本,但 Pod 的 IP 会随重建而变化,客户端不能直接依赖 Pod IP。ClusterIP Service 提供一个虚拟 IP 和稳定 DNS 名称,由 kube-proxy 将访问流量分发到后端就绪 Pod。本例部署 3 副本应用,创建 ClusterIP Service,并在集群内用 Service 名称和完整 DNS 域名验证访问与负载均衡。

集群内客户端 curl / wget test-client Pod CoreDNS web-svc.default.svc.cluster.local → 10.96.100.50 ClusterIP Service web-svc 10.96.100.50:80 → targetPort 8080 kube-proxy iptables/IPVS 负载均衡 Pod-1 10.244.1.5:8080 Pod-2 10.244.2.8:8080 Pod-3 10.244.3.12:8080 请求 解析 转发 验证要点 多次请求应返回不同 Pod 主机名 DNS 短名与 FQDN 均可解析 访问路径: 客户端 → DNS 解析 web-svc → ClusterIP 10.96.100.50 → kube-proxy 按 iptables 规则轮询 → 后端就绪 Pod (8080) Service 通过 selector 匹配 Pod 标签,仅将流量转发到 readinessProbe 通过的 Pod

创建 Deployment 与 ClusterIP Service

先部署一个返回自身主机名的应用,便于观察负载均衡效果。以下 YAML 定义 3 副本 Deployment 和对应 Service。

# web-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: hashicorp/http-echo:0.2.3
        args:
        - "-text=$(POD_NAME)"
        - "-listen=:8080"
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 2
          periodSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

应用并确认资源状态:

kubectl apply -f web-deploy.yaml
kubectl get deploy web -o wide
kubectl get pods -l app=web -o wide
kubectl get svc web-svc
kubectl get endpoints web-svc

预期看到 3 个 Pod 处于 Running 且 Ready,Service 的 ClusterIP 已分配,Endpoints 列出 3 个 Pod IP:8080。若 Endpoints 为空,检查 selector 标签是否与 Pod 标签一致,以及 readinessProbe 是否通过。

集群内 DNS 解析与访问验证

启动一个临时客户端 Pod,在集群内验证短名和 FQDN 解析,并多次请求观察负载均衡。

# 启动测试客户端
kubectl run test-client --image=busybox:1.36 --restart=Never -- sleep 3600

# 等待就绪后进入
kubectl exec -it test-client -- sh

# 在容器内执行:
nslookup web-svc
nslookup web-svc.default.svc.cluster.local

# 短名访问
wget -qO- http://web-svc

# FQDN 访问
wget -qO- http://web-svc.default.svc.cluster.local

# 多次请求观察负载均衡
for i in $(seq 1 10); do wget -qO- http://web-svc; echo; done

DNS 解析应返回 Service 的 ClusterIP。多次请求的响应文本应出现不同的 Pod 名称(如 web-xxxxx-aaa、web-xxxxx-bbb、web-xxxxx-ccc),说明 kube-proxy 在多个后端之间分发流量。若始终返回同一 Pod,可能是会话保持或客户端连接复用导致,可尝试新建连接或使用不同客户端验证。

ClusterIP 只能在集群内部访问。若需从集群外访问,应使用 NodePort、LoadBalancer 或 Ingress。DNS 短名仅在 Pod 所在命名空间内有效,跨命名空间需使用 service.namespace 或 FQDN。

验证清单

检查项命令预期结果
Pod 就绪kubectl get pods -l app=web3 个 Pod Running,READY 1/1
Service 创建kubectl get svc web-svcClusterIP 已分配,PORT 80/TCP
Endpoints 关联kubectl get endpoints web-svc列出 3 个 Pod IP:8080
DNS 短名解析nslookup web-svc返回 ClusterIP
DNS FQDN 解析nslookup web-svc.default.svc.cluster.local返回 ClusterIP
HTTP 访问wget -qO- http://web-svc返回某个 Pod 名称
负载均衡循环请求 10 次出现多个不同 Pod 名称

常见问题排查

  • Endpoints 为空:检查 Service selector 与 Pod labels 是否匹配;检查 readinessProbe 是否通过。
  • DNS 解析失败:确认 CoreDNS Pod 运行正常;检查客户端 Pod 的 /etc/resolv.conf 中 nameserver 和 search 域配置。
  • 连接被拒绝:确认 targetPort 与容器实际监听端口一致;检查 Pod 是否 Ready。
  • 负载不均衡:短时间连续请求可能因连接复用命中同一 Pod,属于正常现象;可通过新建连接或增加请求次数观察。
清理测试资源:kubectl delete pod test-client。保留 Deployment 和 Service 供后续案例使用,或按需删除。