StorageClass-動態PVC

StorageClass

 以前咱們部署了PV 和 PVC 的使用方法,可是前面的 PV 都是靜態的,什麼意思?就是我要使用的一個 PVC 的話就必須手動去建立一個 PV,咱們也說過這種方式在很大程度上並不能知足咱們的需求,好比咱們有一個應用須要對存儲的併發度要求比較高,而另一個應用對讀寫速度又要求比較高,特別是對於 StatefulSet 類型的應用簡單的來使用靜態的 PV 就很不合適了,這種狀況下咱們就須要用到動態 PV,也就是咱們今天要講解的 StorageClass。html

建立

要使用 StorageClass,咱們就得安裝對應的自動配置程序,好比咱們這裏存儲後端使用的是 nfs,那麼咱們就須要使用到一個 nfs-client 的自動配置程序,咱們也叫它 Provisioner,這個程序使用咱們已經配置好的 nfs 服務器,來自動建立持久卷,也就是自動幫咱們建立 PV。node

  • 自動建立的 PV 以${namespace}-${pvcName}-${pvName}這樣的命名格式建立在 NFS 服務器上的共享數據目錄中
  • 而當這個 PV 被回收後會以archieved-${namespace}-${pvcName}-${pvName}這樣的命名格式存在 NFS 服務器上。

固然在部署nfs-client以前,咱們須要先成功安裝上 nfs 服務器,前面的課程中咱們已通過了,服務地址是10.151.30.57,共享數據目錄是/data/k8s/,而後接下來咱們部署 nfs-client 便可,咱們也能夠直接參考 nfs-client 的文檔:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client,進行安裝便可。nginx

第一步:配置 Deployment,將裏面的對應的參數替換成咱們本身的 nfs 配置(nfs-client.yaml)git

kind: Deployment apiVersion: extensions/v1beta1 metadata: name: nfs-client-provisioner spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: fuseim.pri/ifs - name: NFS_SERVER value: 10.151.30.57 - name: NFS_PATH value: /data/k8s volumes: - name: nfs-client-root nfs: server: 10.151.30.57 path: /data/k8s 

第二步:將環境變量 NFS_SERVER 和 NFS_PATH 替換,固然也包括下面的 nfs 配置,咱們能夠看到咱們這裏使用了一個名爲 nfs-client-provisioner 的serviceAccount,因此咱們也須要建立一個 sa,而後綁定上對應的權限:(nfs-client-sa.yaml)github

apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- 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"] verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.io 

咱們這裏新建的一個名爲 nfs-client-provisioner 的ServiceAccount,而後綁定了一個名爲 nfs-client-provisioner-runner 的ClusterRole,而該ClusterRole聲明瞭一些權限,其中就包括對persistentvolumes的增、刪、改、查等權限,因此咱們能夠利用該ServiceAccount來自動建立 PV。web

第三步:nfs-client 的 Deployment 聲明完成後,咱們就能夠來建立一個StorageClass對象了:(nfs-client-class.yaml)shell

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: course-nfs-storage provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME' 

咱們聲明瞭一個名爲 course-nfs-storage 的StorageClass對象,注意下面的provisioner對應的值必定要和上面的Deployment下面的 PROVISIONER_NAME 這個環境變量的值同樣。後端

如今咱們來建立這些資源對象吧:api

$ kubectl create -f nfs-client.yaml
$ kubectl create -f nfs-client-sa.yaml
$ kubectl create -f nfs-client-class.yaml

建立完成後查看下資源狀態:服務器

$ kubectl get pods
NAME                                             READY     STATUS             RESTARTS   AGE
...
nfs-client-provisioner-7648b664bc-7f9pk          1/1       Running            0          7h
...
$ kubectl get storageclass
NAME                 PROVISIONER      AGE
course-nfs-storage   fuseim.pri/ifs   11s

新建

上面把StorageClass資源對象建立成功了,接下來咱們來經過一個示例測試下動態 PV,首先建立一個 PVC 對象:(test-pvc.yaml)

kind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Mi 

咱們這裏聲明瞭一個 PVC 對象,採用 ReadWriteMany 的訪問模式,請求 1Mi 的空間,可是咱們能夠看到上面的 PVC 文件咱們沒有標識出任何和 StorageClass 相關聯的信息,那麼若是咱們如今直接建立這個 PVC 對象可以自動綁定上合適的 PV 對象嗎?顯然是不能的(前提是沒有合適的 PV),咱們這裏有兩種方法能夠來利用上面咱們建立的 StorageClass 對象來自動幫咱們建立一個合適的 PV:

  • 第一種方法:在這個 PVC 對象中添加一個聲明 StorageClass 對象的標識,這裏咱們能夠利用一個 annotations 屬性來標識,以下:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc annotations: volume.beta.kubernetes.io/storage-class: "course-nfs-storage" spec: accessModes: - ReadWriteMany resources: requests: storage: 1Mi 
  • 第二種方法:咱們能夠設置這個 course-nfs-storage 的 StorageClass 爲 Kubernetes 的默認存儲後端,咱們能夠用 kubectl patch 命令來更新:
$ kubectl patch storageclass course-nfs-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' 

上面這兩種方法都是能夠的,固然爲了避免影響系統的默認行爲,咱們這裏仍是採用第一種方法,直接建立便可:

$ kubectl create -f test-pvc.yaml
persistentvolumeclaim "test-pvc" created $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE ... test-pvc Bound pvc-73b5ffd2-8b4b-11e8-b585-525400db4df7 1Mi RWX course-nfs-storage 2m ... 

咱們能夠看到一個名爲 test-pvc 的 PVC 對象建立成功了,狀態已是 Bound 了,是否是也產生了一個對應的 VOLUME 對象,最重要的一欄是 STORAGECLASS,如今是否是也有值了,就是咱們剛剛建立的 StorageClass 對象 course-nfs-storage。

而後查看下 PV 對象呢:

$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE ... pvc-73b5ffd2-8b4b-11e8-b585-525400db4df7 1Mi RWX Delete Bound default/test-pvc course-nfs-storage 8m ... 

能夠看到是否是自動生成了一個關聯的 PV 對象,訪問模式是 RWX,回收策略是 Delete,這個 PV 對象並非咱們手動建立的吧,這是經過咱們上面的 StorageClass 對象自動建立的。這就是 StorageClass 的建立方法。

測試

接下來咱們仍是用一個簡單的示例來測試下咱們上面用 StorageClass 方式聲明的 PVC 對象吧:(test-pod.yaml)

kind: Pod apiVersion: v1 metadata: name: test-pod spec: containers: - name: test-pod image: busybox imagePullPolicy: IfNotPresent command: - "/bin/sh" args: - "-c" - "touch /mnt/SUCCESS && exit 0 || exit 1" volumeMounts: - name: nfs-pvc mountPath: "/mnt" restartPolicy: "Never" volumes: - name: nfs-pvc persistentVolumeClaim: claimName: test-pvc 

上面這個 Pod 很是簡單,就是用一個 busybox 容器,在 /mnt 目錄下面新建一個 SUCCESS 的文件,而後把 /mnt 目錄掛載到上面咱們新建的 test-pvc 這個資源對象上面了,要驗證很簡單,只須要去查看下咱們 nfs 服務器上面的共享數據目錄下面是否有 SUCCESS 這個文件便可:

$ kubectl create -f test-pod.yaml
pod "test-pod" created 

而後咱們能夠在 nfs 服務器的共享數據目錄下面查看下數據:

$ ls /data/k8s/ default-test-pvc-pvc-73b5ffd2-8b4b-11e8-b585-525400db4df7 

咱們能夠看到下面有名字很長的文件夾,這個文件夾的命名方式是否是和咱們上面的規則:${namespace}-${pvcName}-${pvName}是同樣的,再看下這個文件夾下面是否有其餘文件:

$ ls /data/k8s/default-test-pvc-pvc-73b5ffd2-8b4b-11e8-b585-525400db4df7 SUCCESS 

咱們看到下面有一個 SUCCESS 的文件,是否是就證實咱們上面的驗證是成功的啊。

另外咱們能夠看到咱們這裏是手動建立的一個 PVC 對象,在實際工做中,使用 StorageClass 更多的是 StatefulSet 類型的服務,StatefulSet 類型的服務咱們也能夠經過一個 volumeClaimTemplates 屬性來直接使用 StorageClass,以下:(test-statefulset-nfs.yaml)

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: nfs-web
spec:
  serviceName: "nginx"
  template:
    metadata:
      labels:
        app: nfs-web
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
      annotations:
        volume.beta.kubernetes.io/storage-class: course-nfs-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nfs-web
spec:
  type: NodePort
  selector:
    app: nfs-web
  ports:
  - name: nfs-port
    protocol: TCP
    port: 80
    targetPort: web
    nodePort: 8613

實際上 volumeClaimTemplates 下面就是一個 PVC 對象的模板,就相似於咱們這裏 StatefulSet 下面的 template,實際上就是一個 Pod 的模板,咱們不單首創建成 PVC 對象,而用這種模板就能夠動態的去建立了對象了,這種方式在 StatefulSet 類型的服務下面使用得很是多。

直接建立上面的對象:

$ kubectl create -f test-statefulset-nfs.yaml
statefulset.apps "nfs-web" created $ kubectl get pods NAME READY STATUS RESTARTS AGE ... nfs-web-0 1/1 Running 0 1m nfs-web-1 1/1 Running 0 1m nfs-web-2 1/1 Running 0 33s ... 

建立完成後能夠看到上面的3個 Pod 已經運行成功,而後查看下 PVC 對象:

$ kubectl get pvc
NAME            STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
... www-nfs-web-0 Bound pvc-cc36b3ce-8b50-11e8-b585-525400db4df7 1Gi RWO course-nfs-storage 2m www-nfs-web-1 Bound pvc-d38285f9-8b50-11e8-b585-525400db4df7 1Gi RWO course-nfs-storage 2m www-nfs-web-2 Bound pvc-e348250b-8b50-11e8-b585-525400db4df7 1Gi RWO course-nfs-storage 1m ... 

咱們能夠看到是否是也生成了3個 PVC 對象,名稱由模板名稱 name 加上 Pod 的名稱組合而成,這3個 PVC 對象也都是 綁定狀態了,很顯然咱們查看 PV 也能夠看到對應的3個 PV 對象:

$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE ... 1d pvc-cc36b3ce-8b50-11e8-b585-525400db4df7 1Gi RWO Delete Bound default/www-nfs-web-0 course-nfs-storage 4m pvc-d38285f9-8b50-11e8-b585-525400db4df7 1Gi RWO Delete Bound default/www-nfs-web-1 course-nfs-storage 4m pvc-e348250b-8b50-11e8-b585-525400db4df7 1Gi RWO Delete Bound default/www-nfs-web-2 course-nfs-storage 4m ... 

查看 nfs 服務器上面的共享數據目錄:

$ ls /data/k8s/ ... default-www-nfs-web-0-pvc-cc36b3ce-8b50-11e8-b585-525400db4df7 default-www-nfs-web-1-pvc-d38285f9-8b50-11e8-b585-525400db4df7 default-www-nfs-web-2-pvc-e348250b-8b50-11e8-b585-525400db4df7 ... 

是否是也有對應的3個數據目錄,這就是咱們的 StorageClass 的使用方法,對於 StorageClass 多用於 StatefulSet 類型的服務,在後面的課程中咱們還學不斷的接觸到。

相關文章
相關標籤/搜索