Service 服务发现

Pod 的 IP 每次重建都会变化,客户端不可能追着 Pod 跑。Service 为「一组提供相同功能的 Pod」提供稳定入口:一个固定虚拟 IP 与域名,并把请求负载均衡转发到后端多个 Pod,这是集群内服务发现的基石。

为什么需要 Service:Pod IP 漂移

滚动更新、节点故障、手动删除都会让 Pod 销毁重建,IP 随之改变:

kubectl get pods -o wide          # 记下当前 Pod 的 IP
kubectl delete pod web-xxxxx      # 删掉一个 Pod
kubectl get pods -o wide          # 新 Pod 的 IP 已经变了

客户端直连 Pod IP 一变就连不上;Service 的 IP 长期稳定,后端增减自动同步。

核心机制:selector 与 Endpoint

Service 到 Pod 的稳定入口 Service 用 spec.selector 匹配带相应 Label 的 Pod,匹配结果收集为 Endpoint(新版本由 EndpointSlice 承载),kube-proxy 据此维护转发规则:

kubectl get endpoints myapp
# 输出:NAME    ENDPOINTS                         AGE
#       myapp   10.244.1.5:8080,10.244.1.6:8080   2m

Service 的四种类型

type语义典型用途
ClusterIP(默认)集群内部可达的虚拟 IP内部服务互相调用
NodePort每台节点开放固定端口集群外直接访问、测试
LoadBalancer借助云负载均衡器暴露公有云对外提供服务
ExternalName返回一条 DNS CNAME,不转发流量把集群外域名包装成内部服务

ClusterIP 的转发由各节点上的 kube-proxy 完成,常见 iptables 规则或性能更好的 ipvs 模式。

完整示例:Deployment + Service

先用命令创建带标签 app=myapp 的两个 Pod,再写 Service 指向它们:

kubectl create deployment myapp --image=nginx --replicas=2
kubectl get pods -l app=myapp -o wide    # 确认 Pod 就绪

Service 通过 selector 找到这些 Pod 并做负载均衡:

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  type: ClusterIP
  selector:
    app: myapp            # 靠标签找到上面的 Pod
  ports:
    - port: 80            # Service 对外端口
      targetPort: 80      # 转发到 Pod 的端口
kubectl apply -f svc.yaml
kubectl get svc myapp
# 输出:NAME    TYPE        CLUSTER-IP      PORT(S)   AGE
#       myapp   ClusterIP   10.96.10.10     80/TCP    10s
kubectl run tmp --image=curlimages/curl -it --rm -- sh
curl http://myapp          # 集群内用服务名即可访问

无选择器与 headless Service

无选择器 Service 不写 selector,手动建 Endpoint 指向外部 IP,让集群内通过服务名访问外部系统。headless Service 把 clusterIP 设为 None,不分配虚拟 IP,DNS 直接返回各 Pod 地址,常与 StatefulSet 配合:

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  clusterIP: None          # headless
  selector:
    app: redis
  ports:
    - port: 6379

配合 StatefulSet 时每个 Pod 得到 podname.svcname 形式的稳定域名,有状态应用靠它互相定位。

小结:Service 用 selector 把漂移的 Pod IP 收敛成稳定入口,ClusterIP 供集群内部、NodePort/LoadBalancer 暴露外部、headless 服务于有状态应用,是访问 Pod 的第一道门。

笔记加载中…