k8s的StatefulSet(有狀態服務)實現

StatefulSet介紹

遇到的問題:

使用Deployment創建的Pod是無狀態的,當掛在Volume之後,如果該Pod掛了,Replication Controller會再run一個來保證可用性,但是由於是無狀態的,Pod掛了的時候與之前的Volume的關係就已經斷開了,新起來的Pod無法找到之前的Pod。但是對於用戶而言,他們對底層的Pod掛了沒有感知,但是當Pod掛了之後就無法再使用之前掛載的磁盤了。

StatefulSet: 是一種給Pod提供唯一標誌的控制器,它可以保證部署和擴展的順序。

Pod一致性:包含次序(啓動、停止次序)、網絡一致性。此一致性與Pod相關,與被調度到哪個node節點無關。

穩定的次序:對於N個副本的StatefulSet,每個Pod都在[0,N)的範圍內分配一個數字序號,且是唯一的。

穩定的網絡:Pod的hostname模式爲(statefulset名稱)- (序號)。

穩定的存儲:通過VolumeClaimTemplate爲每個Pod創建一個PV。刪除、減少副本,不會刪除相關的卷。

(1) RC、 RS、Deployment、DS。-----> 無狀態服務

template(模板):根據模板 創建出來的Pod,它們J的狀態都是一模一樣的(除了名稱,IP, 域名之外)

可以理解爲:任何一個Pod, 都可以被刪除,然後用新生成的Pod進行替換。

(2) 有狀態的服務: 需要記錄前一 次或者多次通信中的相關事件,以作爲一下通信的分類標準。比如: mysql等數據庫服務。(Pod的名稱,不能隨意變化。數據持久化的目錄也是不一樣,每一個Pod都有自己獨有的數據持久化存儲目錄。)

mysql:主從關係。

如果把之前無狀態的服務比喻爲牛、羊等牲畜,因爲,這些到一定時候就可以”送出“。那麼,有狀態就比喻爲:寵物,而寵物不像牲畜一樣到達一定時候“送出”,人們往往會照顧寵物的一生。

(3) 每一個Pod---->對應一個PVC---->每一個PVC對應一個PV。

storageclass:自動創建PV

需要解決:自動創建PVC。

實現原理

與 ReplicaSet 和 Deployment 資源一樣,StatefulSet 也使用控制器的方式實現,它主要由 StatefulSetController、StatefulSetControl 和 StatefulPodControl 三個組件協作來完成 StatefulSet 的管理,StatefulSetController 會同時從 PodInformer 和 ReplicaSetInformer 中接受增刪改事件並將事件推送到隊列中:
k8s的StatefulSet(有狀態服務)實現
控制器 StatefulSetController 會在 Run 方法中啓動多個 Goroutine 協程,這些協程會從隊列中獲取待處理的 StatefulSet 資源進行同步,接下來我們會先介紹 Kubernetes 同步 StatefulSet 的過程。

1,例子

(1)創建一個statefulset的yaml文件

[root@master yaml]# vim statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: headless-svc
  labels:
    app: headless-svc
spec:
  ports:
  - port: 80
  selector:
    app: headless-pod
  clusterIP: None     #沒有同一的ip
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-test
spec:
  serviceName: headless-svc
  replicas: 3
  selector:
    matchLabels:
      app: headless-pod
  template:
    metadata:
      labels:
        app: headless-pod
    spec:
      containers:
      - name: myhttpd
        image: httpd
        ports:
        - containerPort: 80

Deployment : Deploy+RS+隨機字符串(Pod的名稱。)沒有順序的,可
以沒隨意替代的。

1、headless-svc :無頭服務。因爲沒有IP地址,所以它不具備負載均衡的功能了。因爲statefulset要求Pod的名稱是有順序的,每一個Pod都不能被隨意取代,也就是即使Pod重建之後,名稱依然不變。爲後端的每一個Pod去命名。

2、statefulSet:定義具體的應用

3、volumeClaimT emplates:自動創建PVC,爲後端的Pod提供專有的存儲。

執行一下

[root@master yaml]# kubectl apply -f statefulset.yaml 

查看一下

[root@master yaml]# kubectl get svc

k8s的StatefulSet(有狀態服務)實現

[root@master yaml]# kubectl get pod
//可看到這些pod是有順序的

k8s的StatefulSet(有狀態服務)實現

一、創建StorageClass資源對象。

1、基於NFS服務,創建NFS服務。

下載nfs所需安裝包

[root@node02 ~]# yum -y install nfs-utils  rpcbind

創建共享目錄

[root@master ~]# mkdir /nfsdata

創建共享目錄的權限

[root@master ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)

開啓nfs和rpcbind

[root@master ~]# systemctl start nfs-server.service 
[root@master ~]# systemctl start rpcbind

測試一下

[root@master ~]# showmount -e

k8s的StatefulSet(有狀態服務)實現

2、創建rbac權限。

[root@master yaml]# vim rbac-rolebind.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-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: ["watch", "create", "update", "patch"]
   -  apiGroups: [""]
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-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: ["watch", "create", "update", "patch"]
   -  apiGroups: [""]
      resources: ["services", "endpoints"]
      verbs: ["get","create","list", "watch","update"]
   -  apiGroups: ["extensions"]
      resources: ["podsecuritypolicies"]
      resourceNames: ["nfs-provisioner"]
      verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default   #必寫字段
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

執行一下

[root@master yaml]# kubectl apply -f rbac-rolebind.yaml 

3、創建Deployment資源對象,用Pod代替 真正的NFS服務。

[root@master yaml]# vim nfs-deployment.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-client-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath:  /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: bdqn
            - name: NFS_SERVER
              value: 192.168.1.21
            - name: NFS_PATH
              value: /nfsdata
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.21
            path: /nfsdata

執行一下

[root@master yaml]# kubectl apply -f nfs-deployment.yaml 

查看一下

[root@master yaml]# kubectl get pod

k8s的StatefulSet(有狀態服務)實現

4、創建storageclass的yaml文件

[root@master yaml]# vim test-storageclass.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: stateful-nfs
provisioner: bdqn  #通過provisioner字段關聯到上述Deploy
reclaimPolicy: Retain

執行一下

[root@master yaml]# kubectl apply -f test-storageclass.yaml

查看一下

[root@master yaml]# kubectl get sc

k8s的StatefulSet(有狀態服務)實現

二,解決自動創建pvc

1、創建statefulset的yaml文件

[root@master yaml]# vim statefulset.yaml 
apiVersion: v1
kind: Service
metadata:
  name: headless-svc
  labels:
    app: headless-svc
spec:
  ports:
  - port: 80
    name: myweb
  selector:
    app: headless-pod
  clusterIP: None
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-test
spec:
  serviceName: headless-svc
  replicas: 3
  selector:
    matchLabels:
      app: headless-pod
  template:
    metadata:
      labels:
        app: headless-pod
    spec:
      containers:
      - image: httpd
        name: myhttpd
        ports:
        - containerPort: 80
          name: httpd
        volumeMounts:
        - mountPath: /mnt
          name: test
  volumeClaimTemplates:  #> 自動創建PVC,爲後端的Pod提供專有的存儲。**
  - metadata:
      name: test
      annotations:   #這是指定storageclass
        volume.beta.kubernetes.io/storage-class: stateful-nfs
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 100Mi

在此示例中:

  • 創建了一個名爲 headless-svcService 對象,由 metadata: name 字段指示。該 Service 會定位一個名爲 headless-svc 的應用,由 labels: app: headless-svcselector: app: headless-pod 指示。該 Service 會公開端口 80 並將其命名爲 web。而且該 Service 會控制網域並將互聯網流量路由到 StatefulSet 部署的容器化應用。
  • 使用三個副本 Pod (replicas: 3) 創建了一個名爲 web 的 StatefulSet。
  • Pod 模板 (spec: template) 指示其 Pod 標記爲 app: headless-pod
  • Pod 規範 (template: spec) 指示 StatefulSet 的 Pod 運行一個容器 myhttpd,該容器運行版本爲 httpd 映像。容器映像由 Container Registry 管理。
  • Pod 規範使用由 Service 打開的 web 端口。
  • template: spec: volumeMounts 指定一個名爲 testmountPathmountPath 是容器中應裝載存儲卷的路徑。
  • StatefulSet 預配了一個具有 100mb 預配存儲空間的 PersistentVolumeClaimtest

執行一下

[root@master yaml]# kubectl apply -f statefulset.yaml

查看一下

[root@master yaml]# kubectl get pod

k8s的StatefulSet(有狀態服務)實現

如果第一個pod出現了問題,後面的pod就不會生成。

[root@master yaml]# kubectl get statefulsets

k8s的StatefulSet(有狀態服務)實現

2、 驗證一下數據存儲

容器中創建文件

[root@master yaml]# kubectl exec -it statefulset-test-0 /bin/sh
# cd /mnt
# touch testfile
# exit

宿主機查看一下

[root@master yaml]# ls /nfsdata/default-test-statefulset-test-0-pvc-bf1ae1d0-f496-4d69-b33b-39e8aa0a6e8d/
testfile

三、小實驗

以自己的名稱創建一個名稱空間,以下所有資源都運行在此空間中。用statefuset資源運行一個httpd web服務,要求3個Pod,但是每個Pod的主界面內容不一樣,並且都要做專有的數據持久化,嘗試刪除其中一個Pod,查看新生成的Pod,總結對比與之前Deployment資源控制器控制的Pod有什麼不同之處?

(一)創建StorageClass資源對象。

注意:nfs服務要開啓

1、創建namespace的yaml文件

[root@master yaml]# vim namespace.yaml 
kind: Namespace
apiVersion: v1
metadata:
  name: xgp-lll    #namespave的名稱

執行一下

[root@master yaml]# kubectl apply -f namespace.yaml 

查看一下

[root@master yaml]# kubectl get namespaces 

k8s的StatefulSet(有狀態服務)實現

2. 創建rbac權限。

[root@master yaml]# vim rbac-rolebind.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
  namespace: xgp-lll
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-provisioner-runner
  namespace: xgp-lll
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: ["watch", "create", "update", "patch"]
   -  apiGroups: [""]
      resources: ["services", "endpoints"]
      verbs: ["get","create","list", "watch","update"]
   -  apiGroups: ["extensions"]
      resources: ["podsecuritypolicies"]
      resourceNames: ["nfs-provisioner"]
      verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: xgp-lll
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

執行一下

[root@master yaml]# kubectl apply -f rbac-rolebind.yaml

3、創建Deployment資源對象,用Pod代替 真正的NFS服務。

[root@master yaml]# vim nfs-deployment.yaml 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: xgp-lll
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-client-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath:  /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: xgp
            - name: NFS_SERVER
              value: 192.168.1.21
            - name: NFS_PATH
              value: /nfsdata
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.21
            path: /nfsdata

執行一下

[root@master yaml]# kubectl apply -f nfs-deployment.yaml 

查看一下

[root@master yaml]# kubectl get pod  -n xgp-lll 

k8s的StatefulSet(有狀態服務)實現

4、創建storageclass的yaml文件

[root@master yaml]# vim test-storageclass.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: stateful-nfs
  namespace: xgp-lll
provisioner: xgp  #通過provisioner字段關聯到上述Deploy
reclaimPolicy: Retain

執行一下

[root@master yaml]# kubectl apply -f test-storageclass.yaml

查看一下

[root@master yaml]# kubectl get sc -n  xgp-lll

k8s的StatefulSet(有狀態服務)實現

(二)解決自動創建pvc

1、創建statefulset的yaml文件

apiVersion: v1
kind: Service
metadata:
  name: headless-svc
  namespace: xgp-lll
  labels:
    app: headless-svc
spec:
  ports:
  - port: 80
    name: myweb
  selector:
    app: headless-pod
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-test
  namespace: xgp-lll
spec:
  serviceName: headless-svc
  replicas: 3
  selector:
    matchLabels:
      app: headless-pod
  template:
    metadata:
      labels:
        app: headless-pod
    spec:
      containers:
      - image: httpd
        name: myhttpd
        ports:
        - containerPort: 80
          name: httpd
        volumeMounts:
        - mountPath: /usr/local/apache2/htdocs
          name: test
  volumeClaimTemplates:  #> 自動創建PVC,爲後端的Pod提供專有的>存儲。**
  - metadata:
      name: test
      annotations:   #這是指定storageclass
        volume.beta.kubernetes.io/storage-class: stateful-nfs
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 100Mi

執行一下

[root@master yaml]# kubectl apply -f statefulset.yaml

查看一下

[root@master yaml]# kubectl get pod -n xgp-lll 

k8s的StatefulSet(有狀態服務)實現

2、 驗證一下數據存儲

容器中創建文件

第一個
[root@master yaml]# kubectl exec -it -n xgp-lll statefulset-test-0 /bin/bash 
root@statefulset-test-0:/usr/local/apache2# echo 123 > /usr/local/apache2/htdocs/index.html

第二個
[root@master yaml]# kubectl exec -it -n xgp-lll statefulset-test-1 /bin/bash 
root@statefulset-test-2:/usr/local/apache2# echo 456 > /usr/local/apache2/htdocs/index.html

第三個
[root@master yaml]# kubectl exec -it -n xgp-lll statefulset-test-2 /bin/bash 
root@statefulset-test-1:/usr/local/apache2# echo 789 > /usr/local/apache2/htdocs/index.html

宿主機查看一下

第一個
[root@master yaml]# cat /nfsdata/xgp-lll-test-statefulset-test-0-pvc-ccaa02df-4721-4453-a6ec-4f2c928221d7/index.html 
123

第二個
[root@master yaml]# cat /nfsdata/xgp-lll-test-statefulset-test-1-pvc-88e60a58-97ea-4986-91d5-a3a6e907deac/index.html 
456

第三個
[root@master yaml]# cat /nfsdata/xgp-lll-test-statefulset-test-2-pvc-4eb2bbe2-63d2-431a-ba3e-b7b8d7e068d3/index.html 
789

訪問一下

k8s的StatefulSet(有狀態服務)實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章