基于StatefulSet部署有状态服务

一、StatefulSet介绍

官网介绍:https://kubernetes.io/zh/docs/concepts/workloads/controllers/statefulset/

  • StatefulSet 是用来管理有状态应用的工作负载 API 对象。
  • StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
  • 如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。 尽管 StatefulSet 中的单个 Pod 仍可能出现故障, 但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。

使用 StatefulSet
StatefulSet 对于需要满足以下一个或多个需求的应用程序很有价值:

  • 稳定的、唯一的网络标识符。
  • 稳定的、持久的存储。
  • 有序的、优雅的部署和扩缩。
  • 有序的、自动的滚动更新。

在上面描述中,“稳定的”意味着 Pod 调度或重调度的整个过程是有持久性的。 如果应用程序不需要任何稳定的标识符或有序的部署、删除或扩缩, 则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如 Deployment 或者 ReplicaSet 可能更适用于你的无状态应用部署需要。

限制

  • 给定 Pod 的存储必须由 PersistentVolume Provisioner 基于所请求的 storage class 来制备,或者由管理员预先制备。
  • 删除或者扩缩 StatefulSet 并不会删除它关联的存储卷。 这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。
  • StatefulSet 当前需要无头服务来负责 Pod 的网络标识。你需要负责创建此服务。
  • 当删除一个 StatefulSet 时,该 StatefulSet 不提供任何终止 Pod 的保证。 为了实现 StatefulSet 中的 Pod 可以有序且体面地终止,可以在删除之前将 StatefulSet 缩容到 0。
  • 在默认 Pod 管理策略(OrderedReady) 时使用滚动更新, 可能进入需要人工干预才能修复的损坏状态。

使用场景

  • Statefulset为了解决有状态服务的集群部署、 集群之间的数据同步问题(MySQL主从等)
  • Statefulset所管理的Pod拥有唯一且固定的Pod名称
  • Statefulset按照顺序对pod进行启停、 伸缩和回收
  • Headless Services(无头服务, 请求的解析直接解析到pod IP)

运行逻辑

二、基于StatefulSet部署有状态服务

2.1、准备nfs 动态存储类

root@easzlab-deploy:~/jiege-k8s/nfs-pv-pvc# cat nfs-deployment.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints","services"]
    verbs: ["get", "list", "watch","create","update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: kube-system 
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-provisioner-01
  namespace: kube-system
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-provisioner-01
  template:
    metadata:
      labels:
        app: nfs-provisioner-01
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: registry.cn-qingdao.aliyuncs.com/zhangshijie/nfs-subdir-external-provisioner:v4.0.2  
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: nfs-provisioner-01
            - name: NFS_SERVER
              value: 172.16.88.169
            - name: NFS_PATH
              value: /data
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.16.88.169
            path: /data
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-dynamic-class
  annotations:
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: nfs-provisioner-01
parameters:
  archiveOnDelete: "false"

root@easzlab-deploy:~/jiege-k8s/nfs-pv-pvc# 
root@easzlab-deploy:~/jiege-k8s/nfs-pv-pvc# kubectl apply -f nfs-deployment.yaml 
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
deployment.apps/nfs-provisioner-01 created
storageclass.storage.k8s.io/nfs-dynamic-class created
root@easzlab-deploy:~/jiege-k8s/nfs-pv-pvc# kubectl get pod -n kube-system
NAMESPACE              NAME                                                READY   STATUS    RESTARTS        AGE
kube-system            calico-kube-controllers-5c8bb696bb-5nrbl            1/1     Running   3 (2d18h ago)   3d23h
kube-system            calico-node-68k76                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-bz8pp                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-cfl2g                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-hsrfh                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-j8kgf                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-kdb5j                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-mqmhp                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-x6ctf                                   1/1     Running   2 (2d18h ago)   3d21h
kube-system            calico-node-xh79g                                   1/1     Running   2               3d21h
kube-system            coredns-69548bdd5f-9md6c                            1/1     Running   2 (2d18h ago)   3d23h
kube-system            coredns-69548bdd5f-n6rvg                            1/1     Running   2 (2d18h ago)   3d23h
kube-system            kuboard-7dc6ffdd7c-njhnb                            1/1     Running   2 (2d18h ago)   3d23h
kube-system            metrics-server-686ff776cf-dbgq6                     1/1     Running   4 (2d18h ago)   3d18h
kube-system            nfs-provisioner-01-599b7bfc9d-ldl99                 1/1     Running   0               3s
kubernetes-dashboard   dashboard-metrics-scraper-8c47d4b5d-5cxhb           1/1     Running   2 (2d18h ago)   3d19h
kubernetes-dashboard   kubernetes-dashboard-f778f96c9-s5dk7                1/1     Running   4 (2d18h ago)   3d16h
velero-system          velero-858b9459f9-4jbns                             1/1     Running   4 (2d18h ago)   3d20h
root@easzlab-deploy:~/jiege-k8s/nfs-pv-pvc# kubectl get sc -A
NAME                               PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
ceph-storage-class-k8s (default)   kubernetes.io/rbd    Delete          Immediate           true                   3d19h
nfs-dynamic-class                  nfs-provisioner-01   Delete          Immediate           false                  10s
root@easzlab-deploy:~/jiege-k8s/nfs-pv-pvc# 

2.2、准备有状态部署文件

官网案例:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/

root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# vi StatefulSet-nginx.yaml
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# cat StatefulSet-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx 
  serviceName: "nginx"
  replicas: 3
  minReadySeconds: 10 
  template:
    metadata:
      labels:
        app: nginx 
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.cn-shenzhen.aliyuncs.com/cyh01/nginx-slim:0.8 #这里镜像在国外,只能先想办法上传到自己私仓
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs-dynamic-class"
      resources:
        requests:
          storage: 10Gi
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# 
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# kubectl apply -f StatefulSet-nginx.yaml 
service/nginx created
statefulset.apps/web created
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# 
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# 
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# kubectl get statefulset -A
NAMESPACE   NAME                            READY   AGE
argocd      argocd-application-controller   1/1     3d18h
argocd      argocd-redis-ha-server          3/3     3d18h
default     web                             3/3     18m
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# 
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# kubectl get pod -owide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE            NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          78s   10.200.104.238   172.16.88.163   <none>           <none>
web-1   1/1     Running   0          38s   10.200.105.166   172.16.88.164   <none>           <none>
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# kubectl get svc 
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   3d23h
nginx        ClusterIP   None         <none>        80/TCP    87s
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# kubectl get pvc -A
NAMESPACE   NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
default     www-web-0   Bound    pvc-f981dab0-b708-49b9-8b36-a6700cbefa96   10Gi       RWO            nfs-dynamic-class   3m51s
default     www-web-1   Bound    pvc-d3ccbf91-3541-4b33-b7fc-3f54e27f2759   10Gi       RWO            nfs-dynamic-class   3m11s
default     www-web-2   Bound    pvc-e5c7d9f2-2808-4086-bc7c-3aefd6c75012   10Gi       RWO            nfs-dynamic-class   2m31s
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7# kubectl get pv -A
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS        REASON   AGE
pvc-d3ccbf91-3541-4b33-b7fc-3f54e27f2759   10Gi       RWO            Delete           Bound    default/www-web-1   nfs-dynamic-class            3m15s
pvc-e5c7d9f2-2808-4086-bc7c-3aefd6c75012   10Gi       RWO            Delete           Bound    default/www-web-2   nfs-dynamic-class            2m34s
pvc-f981dab0-b708-49b9-8b36-a6700cbefa96   10Gi       RWO            Delete           Bound    default/www-web-0   nfs-dynamic-class            3m55s
root@easzlab-deploy:~/jiege-k8s/pod-test/case-yaml/case7#

上述例子中:

  • 名为 nginx 的 Headless Service 用来控制网络域名。
  • 名为 web 的 StatefulSet 有一个 Spec,它表明将在独立的 3 个 Pod 副本中启动 nginx 容器。
  • volumeClaimTemplates 将通过 PersistentVolume 制备程序所准备的 PersistentVolumes 来提供稳定的存储。
posted @ 2022-10-22 17:04  cyh00001  阅读(98)  评论(0编辑  收藏  举报