k8s 網路持久化儲存之StorageClass(如何一步步實現動態持久化儲存)

2022-09-02 06:01:14

StorageClass的作用:

建立pv時,先要建立各種固定大小的PV,而這些PV都是手動建立的,當業務量上來時,需要建立很多的PV,過程非常麻煩。
而且開發人員在申請PVC資源時,還不一定有匹配條件的PV可用,這又帶來了新的問題。
於是Kubernetes提供了StorageClass來動態建立PV,StorageClass大大簡化了PV的建立過程。
當申請PVC資源時, 如果匹配到滿足條件的StorageClass,還會自動為PVC建立對應大小的 PV並進行繫結。

下面就來仔細講講現在如何一步步的通過建立StorageClass動態建立PV從而實現持久化儲存的。

網路儲存卷

Kubernetes是分散式容器叢集,如何在多個Pod之間或多 個Node之間進行資料儲存和共用是非常重要的問題。

Kubernetes引入了網路儲存卷,它支援為數眾多的雲提供商的產品和網路儲存方案,如 NFS/iSCSI/GlusterFS/RDB/azureDisk/flocker等

網路儲存卷還能夠 滿足持久化資料的要求,這些資料將永久儲存。

網路儲存卷是整合各種第三方的儲存系統,不同的服務商提供的設定有一些不同,NFS只是其中一種。

一. 安裝NFS

安裝NFS伺服器

資源有限,此處我選擇了master作為NFS伺服器

安裝NFS伺服器應用:yum install -y nfs-utils rpcbind

建立NFS共用目錄:mkdir -p /data/k8snfs

編輯NFS組態檔:vim /etc/exports


重啟服務:

檢查伺服器端是否正常載入 了/etc/exports的設定:


注意:如果使用雲伺服器,需要開放一下埠,否則使用者端連線不上。使用:rpcinfo -p 檢視需要開放的埠。注意有tcp和udp:

安裝NFS使用者端

注意:每臺需要使用NFS的Node都需要安裝NFS

安裝使用者端:yum install -y nfs-utils

檢查是否能存取遠端的NFS伺服器:sudo showmount -e {NFS伺服器IP地址}


如果出現clnt_create: RPC: Port mapper failure - Timed out,使用雲服務的話大概率是介面沒開放。

持久儲存卷

Kubernetes支援為數眾多的 雲提供商和網路儲存方案,如 NFS/iSCSI/GlusterFS/RDB/azureDisk/flocker等。但因為網路儲存卷 通常是整合各種第三方的儲存系統,所以在設定上各有差別。

不同的儲存的設定引數不太一樣,這些引數應該是儲存管理員關注的,而非開發人員,Kubernetes提供了3種基於儲存的抽象物件—— PersistentVolume(PV)、StorageClass和 PersistentVolumeClaim(PVC),以支援基礎設施和應用之間的分離。

儲存管理人員設定 PV或StorageClass,並在裡面設定儲存系統和引數

開發人員只 需要建立PVC來申請指定空間的資源以儲存與共用資料即可,無須再關 注儲存的具體實現和操作。

當刪除PVC時,它寫入具體儲存資源中的資料可以根據回收策略自動清理。

PV和PVC

PV表示持久儲存卷,定義了Kubernetes叢集中可用的儲存資源, 其中包含儲存資源實現的細節,如包含如何使用 NFS/iSCSI/GlusterFS/RDB/azureDisk/flocker 等資源的具體設定。

PVC表示持久儲存卷的申請,是由使用者發起的對儲存資源的請求。 申請中只包含請求資源的大小和讀寫存取模式,無須關注具體的資源 實現細節,Kubernetes會自動為其繫結符合條件的PV

二.部署StorageClass

StorageClass是通過儲存分配器(provisioner)來動態分配PV 的,但是Kubernetes官方內建的儲存分配器並不支援NFS,所以需要額外安裝NFS儲存分配器。

1. 安裝NFS儲存分配器

第一步:設定儲存分配器的許可權

因為storage自動建立pv需要經過kube-apiserver,所以要進行授權

在node節點建立nfs-client-provisioner-authority.yaml檔案

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: default
---
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: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

第二步:安裝NFS儲存分配器

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  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    # NFS伺服器地址
              value: xx.xx.236.113
            - name: NFS_PATH       # NFS共用目錄地址
              value: /data/k8snfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: xx.xx.236.113  # NFS伺服器地址
            path: /data/k8snfs     # NFS共用目錄

第三步: 建立StorageClass

建立nfs-storage-class.yml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage   # StorageClass名稱

  # 儲存分配器名稱
provisioner: fuseim.pri/ifs  # 對應「nfs-client-provisioner.yaml」檔案中env.PROVISIONER_NAME.value

  # 允許pvc建立後擴容
allowVolumeExpansion: True

parameters:
  archiveOnDelete: "false"  # 資源刪除策略,「true」表示刪除PVC時,同時刪除繫結的PV,false刪除PVC時,對應的PV不會刪除

建立PVC

StorageClass 建立完成後就可以建立 PVC 了。
建立:testpvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: testpvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "managed-nfs-storage"
  resources:
    requests:
      storage: 500Mi


此時發現,pvc一直是pending狀態,並沒有預設分配PV。 分析,可能是儲存分配器除了問題

selfLink was empty 在k8s叢集 v1.20之前都存在,在v1.20之後被刪除,需要在/etc/kubernetes/manifests/kube-apiserver.yaml 新增引數 - --feature-gates=RemoveSelfLink=false
如下所示:


稍等一會,再進行檢視PV和PVC

可以看到PV已經被自動建立,且PV,PVC的狀態已經均為繫結狀態。

NFS和PV,PVC關係圖:

本文參考部落格:https://blog.csdn.net/zhang19903848257/article/details/125887017