kubernetes | statefulset控制器详解

2023-04-17 20:36:12 浏览数 (1)

基础概念

StatefulSet 应用场景:分布式应用、集群

  • 部署有状态应用
  • 解决Pod独立生命周期,保持Pod启动顺序和唯一性
    • 稳定,唯一的网络标识符,持久存储
    • 有序,优雅的部署和扩展、删除和终止
    • 有序,滚动更新

StatefulSet 控制器的优势

  • 稳定的存储
    • StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当StatefulSet使用VolumeClaimTemplate创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC。该PVC和PV不会随着StatefulSet的删除而删除
  • 稳定的网络ID
    • StatefulSet 中的每个 POD 名称固定:<statefulset-name>-<number>
    • 通过 serviceName 字段指定 Headless Service ,可以为每个 POD 分配一个固定的 DNS 解析,重启或者重建 POD 时虽然 ip 有所变动,但 DNS 解析会保持稳定

示例yaml

代码语言:javascript复制
apiVersion: v1
kind: Service
metadata:
  name: statefulset-nginx
  labels:
    app: statefulset-nginx
spec:
  selector:
    app: statefulset-nginx
  clusterIP: None
  ports:
  - name: web
    port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-nginx
spec:
  serviceName: "statefulset-nginx"
  replicas: 2
  selector:
    matchLabels:
      app: statefulset-nginx
  template:
    metadata:
      labels:
        app: statefulset-nginx
    spec:
      terminationGracePeriodSeconds: 5
      containers:
      - name: statefulset-nginx
        image: nginx:1.22.1
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      storageClassName: "managed-nfs-storage"
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

稳定的存储

可以看到与deployment不同,statefulset中的每个pod都分配到了独立的pv,且重启pod后存储对应关系不变

代码语言:javascript复制
[root@k8s-node1 ~]# kubectl get pod,pvc,pv | awk  '{print $1}'
# pod NAME
pod/nfs-client-provisioner-66d6cb77fd-47hsf
pod/statefulset-nginx-0
pod/statefulset-nginx-1
# pvc NAME
persistentvolumeclaim/www-statefulset-nginx-0
persistentvolumeclaim/www-statefulset-nginx-1
# pv NAME
persistentvolume/pvc-17751fde-1b23-4535-98bb-a70342ddd6fe
persistentvolume/pvc-b7519f46-b2af-42e4-b66d-d7459be2e87c
[root@k8s-node1 ~]# ls  /ifs/kubernetes/
default-www-statefulset-nginx-0-pvc-17751fde-1b23-4535-98bb-a70342ddd6fe 
default-www-statefulset-nginx-1-pvc-b7519f46-b2af-42e4-b66d-d7459be2e87c

稳定的网络ID

手动删除pod后除了pod的ip会变动,主机名和dns解析都正常

代码语言:javascript复制
# POD名字固定
[root@k8s-node1 ~]# kubectl get pods -l app=statefulset-nginx
NAME                  READY   STATUS    RESTARTS   AGE
statefulset-nginx-0   1/1     Running   0          5m18s
statefulset-nginx-1   1/1     Running   0          5m17s

# 主机名固定
[root@k8s-node1 ~]# for i in 0 1; do kubectl exec "statefulset-nginx-$i" -- hostname; done
statefulset-nginx-0
statefulset-nginx-1

# DNS解析固定
[root@k8s-node1 ~]# kubectl run -it --rm --restart=Never --image busybox:1.28 dns-test -- nslookup statefulset-nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      statefulset-nginx
Address 1: 10.244.107.230 statefulset-nginx-1.statefulset-nginx.default.svc.cluster.local
Address 2: 10.244.169.157 statefulset-nginx-0.statefulset-nginx.default.svc.cluster.local
pod "dns-test" deleted

暴露应用

由于使用的是 Headless Service ,无法使用 NodePort 的方式暴露应用端口,我们可以单独创建 service 来暴露特定 pod 应用

StatefulSet 控制器中的 pod 名称都是固定的: <statefulset-name>-<number> ,可以通过 statefulset.kubernetes.io/pod-name 标签固定 pod

示例如下

代码语言:javascript复制
apiVersion: v1
kind: Service
metadata:
  name: ss-nginx-0
  labels:
    app: ss-nginx-0
spec:
  selector:
    statefulset.kubernetes.io/pod-name: statefulset-nginx-0
  type: NodePort
  ports:
  - name: web
    port: 80
    targetPort: 80
    nodePort: 30003

验证

代码语言:javascript复制
[root@k8s-node1 ~]# kubectl get svc ss-nginx-0
NAME         TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
ss-nginx-0   NodePort   10.111.69.1   <none>        80:30003/TCP   3h53m
[root@k8s-node1 ~]# kubectl get ep ss-nginx-0
NAME         ENDPOINTS           AGE
ss-nginx-0   10.244.169.188:80   3h53m

0 人点赞