一、StatefulSet 内部通信为什么稳定¶
StatefulSet 的内部通信通常依赖 Headless Service。因为它没有统一的 ClusterIP 去做负载均衡,而是把每个 Pod 的身份直接交给 DNS 和 Endpoint。
典型域名格式是:
statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
例如:
web-0.nginx.default.svc.cluster.localweb-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 默认的 podManagementPolicy 是 OrderedReady,也就是必须等 web-0 就绪之后,才会继续创建 web-1。这对要求严格初始化顺序的应用很友好。
如果你更看重并行拉起,可以改成:
spec:
podManagementPolicy: Parallel
这样 Pod 的创建和删除就可以并发进行。原文示例里正是通过这个配置,观察到了 web-0 和 web-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”,而是让每个节点都带着稳定身份加入同一个有状态集群。