跳到主要内容

StatefulSet Service

2024年11月28日
柏拉文
越努力,越幸运

一、认识


StatefulSetKubernetes 中专门用于管理有状态应用的控制器。它为每个 Pod 提供稳定的网络标识和独立的存储卷,同时支持有序部署、扩展和缩减。适用于需要数据一致性和稳定性的场景,例如数据库、分布式存储系统和消息队列等。与 Deployment 相比,StatefulSet 主要用于那些需要稳定网络标识、持久存储以及有序部署和扩展的场景,例如数据库、分布式文件系统或队列服务。StatefulSet 通常与 Headless Service 配合使用(clusterIP: None),为每个 Pod 提供固定的 DNS 名称,用于直接访问特定的 Pod。适用于需要稳定标识和数据一致性的有状态应用, 每个 Pod 有固定的 DNS 名称,通常结合 Headless Service 使用。

1.1 绑定规则

StatefulSetService 的绑定规则为: ServiceselectorStatefulSet 中的 Pod 标签匹配,用于绑定 Pod; StatefulSet 中的 serviceName 用于匹配 Service 的名称。

service.yaml: selector 用于匹配 statefulSet.yaml 中的 spec.selector.matchLabels

apiVersion: v1
kind: Service
metadata:
name: test-service
spec:
selector:
app: test-nginx

statefulSet.yaml: spec.selector.matchLabels 用于匹配 service.yaml 中的 selector。但是 statefulSet.yaml 中的 spec.selector.matchLabels 必须与 spec.template.metadata.labels 一致;spec.serviceName 用于匹配 service.yaml 中的 metadata.name

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "web" # 绑定上面的 Headless Service
replicas: 3
selector:
matchLabels:
app: test-nginx
template:
metadata:
labels:
app: test-nginx

1.2 StatefulSet

StatefulSet 每个 Pod 有固定的名称(如 myapp-0, myapp-1)。Pod 的重启或迁移不会改变其名称和身份。每个 Pod 都有一个与之绑定的持久存储卷(PersistentVolume),即使 Pod 被删除或重建,其存储仍然保持不变。Pod 按顺序创建(0 -> 1 -> 2)或删除(2 -> 1 -> 0)。更新时也会按顺序进行,确保服务不中断。每个 Pod 都有一个固定的 DNS 名称(如 myapp-0.myservice.default.svc.cluster.local)。

1.3 Headless Service

Service 配置中,将 clusterIp 置为 None, 将服务配置为无头服务 Headless Service,使每个 Pod 都有独立的 DNSHeadless ServiceDNS 格式:

  • 单个 PodDNS 名称<Pod 名称>.<Service 名称>.<命名空间>.svc.cluster.local。例如,对于 StatefulSet 名为 webPodweb-0.web.default.svc.cluster.local, web-1.web.default.svc.cluster.local

  • 服务的 DNS 名称<Service 名称>.<命名空间>.svc.cluster.local。例如:web.default.svc.cluster.local

二、操作


2.1 编写 Service 文件

编写 test-service.yaml 文件,注意: 将 clusterIP: None 将服务配置为无头服务,使每个 Pod 都有独立的 DNS

apiVersion: v1
kind: Service
metadata:
name: test-headless-service
spec:
clusterIP: None
ports:
- name: http
port: 80
targetPort: 80
selector:
app: test-stateful-set-nginx

2.2 创建 Service 服务

应用这个 Service

kubectl apply -f test-service.yaml

2.3 编写 StatefulSet 文件

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: test-stateful-set
spec:
serviceName: "test-headless-service"
replicas: 3
selector:
matchLabels:
app: test-stateful-set-nginx
template:
metadata:
labels:
app: test-stateful-set-nginx
spec:
containers:
- name: nginx
image: registry.cn-hangzhou.aliyuncs.com/bolawen/nginx:1.27.1-perl-linux-arm64
ports:
- containerPort: 80
volumeMounts:
- name: test-volume
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: test-volume
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi

2.4 创建 SateFulSet 应用

应用这个 SateFulSet

kubectl apply -f test-stateFulSet.yaml

2.5 查看 SateFulSet 状态

kubectl get svc
kubectl get statefulset
kubectl get pods

kubectl describe statefulSet [statefulSet Name]

2.6 验证 DNS 和网络

进入任意 Pod 中测试 DNS 解析和访问:

kubectl exec -it web-0 -- sh
# 测试访问其他 Pod
ping web-1.web.default.svc.cluster.local
curl web-1.web.default.svc.cluster.local