一、StatefulSet 内部通信为什么稳定

StatefulSet 的内部通信通常依赖 Headless Service。因为它没有统一的 ClusterIP 去做负载均衡,而是把每个 Pod 的身份直接交给 DNS 和 Endpoint。

典型域名格式是:

statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local

例如:

  • web-0.nginx.default.svc.cluster.local
  • web-1.nginx.default.svc.cluster.local

正因为名字稳定,服务之间才可以做固定节点发现、主从关系声明和集群注册。

二、同命名空间里怎么互相访问

同一命名空间下,访问可以写短很多。原文示例里,在 web-0 容器内直接访问 web-1.nginx 就能成功:

kubectl exec -it web-0 -- sh
wget web-1.nginx

在同命名空间里,通常不必把 .namespace.svc.cluster.local 全部写出来,这也是很多状态服务能用短地址互联的原因。

三、跨命名空间访问时要把命名空间补上

如果目标 Pod 在别的命名空间,就需要把命名空间显式写进域名。例如原文在 test 命名空间中访问 default 命名空间下的实例:

kubectl create ns test
kubectl exec -it web-0 -n test -- sh
wget web-1.nginx.default

再严谨一点,也可以直接使用完整 FQDN。记住这个规则后,跨命名空间排查 StatefulSet 通信问题会快很多。

四、OrderedReady 和 Parallel 会影响集群启动方式

StatefulSet 默认的 podManagementPolicyOrderedReady,也就是必须等 web-0 就绪之后,才会继续创建 web-1。这对要求严格初始化顺序的应用很友好。

如果你更看重并行拉起,可以改成:

spec:
  podManagementPolicy: Parallel

这样 Pod 的创建和删除就可以并发进行。原文示例里正是通过这个配置,观察到了 web-0web-1 同时创建、同时删除。

经验上可以这样理解:

  • OrderedReady:更强调稳定顺序
  • Parallel:更强调启动和收缩速度

五、Eureka 集群为什么非常适合 StatefulSet

原文最后用 Eureka 做了一个很典型的状态集群示例。核心思路是:

  • 先建 Headless Service demo-eureka
  • 再建 3 副本的 StatefulSet
  • 通过固定域名把 3 个节点互相注册起来

关键配置如下:

apiVersion: v1
kind: Service
metadata:
  name: demo-eureka
spec:
  ports:
  - name: http-web
    protocol: TCP
    port: 8761
    targetPort: 8761
  selector:
    app: demo-eureka
  clusterIP: None
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: demo-eureka
spec:
  serviceName: demo-eureka
  replicas: 3
  podManagementPolicy: Parallel
  selector:
    matchLabels:
      app: demo-eureka
  template:
    metadata:
      labels:
        app: demo-eureka
    spec:
      containers:
      - name: eureka
        image: registry.cn-hangzhou.aliyuncs.com/abroad_images/demo-eureka:latest
        ports:
        - containerPort: 8761
          name: http-web
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: k8s
        - name: SERVER_PORT
          value: "8761"
        - name: EUREKA_SERVER_ADDRESS
          value: "http://demo-eureka-0.demo-eureka:8761/eureka/,http://demo-eureka-1.demo-eureka:8761/eureka/,http://demo-eureka-2.demo-eureka:8761/eureka/"

创建后可以观察:

kubectl apply -f sts-eureka.yaml
kubectl get pods | grep demo

如果还要从集群外访问,可以再补一个 NodePort Service:

apiVersion: v1
kind: Service
metadata:
  name: demo-eureka-np
spec:
  ports:
  - name: http-web
    protocol: TCP
    port: 8761
    targetPort: 8761
  selector:
    app: demo-eureka
  type: NodePort

这正是 StatefulSet 的典型价值:不是简单地“多起几个 Pod”,而是让每个节点都带着稳定身份加入同一个有状态集群。