1. 程式人生 > 其它 >k8s--持久化儲存

k8s--持久化儲存

k8s--持久化儲存

一、k8s持久化儲存概述

1.1、為什麼要做持久化儲存

在k8s中部署的應用都是以pod容器的形式執行的,假如我們部署MySQL、Redis等資料庫,需要對這些資料庫產生的資料做備份。因為Pod是有生命週期的,如果pod不掛載資料卷,那pod被刪除或重啟後這些資料會隨之消失,如果想要長久的保留這些資料就要用到pod資料持久化儲存

1.2、k8s支援儲存型別

# 檢視k8s支援的儲存
[root@k8s-master1 ~]# kubectl explain pods.spec.volumes
    
# 常用的儲存
# emptyDir、hostPath、nfs、persistentVolumeClaim、glusterfs、cephfs、configMap、secret

我們想要使用儲存卷,需要經歷如下步驟:

  1. 定義pod的volume,這個volume指明它要關聯到哪個儲存上的
  2. 在容器中要使用volumemounts掛載對應的儲存

二、k8s常用儲存型別

2.1、emptyDir

emptyDir型別的Volume是在Pod分配到Node上時被建立,Kubernetes會在Node上自動分配一個目錄,因此無需指定宿主機Node上對應的目錄檔案。 這個目錄的初始內容為空,當Pod從Node上移除時,emptyDir中的資料會被永久刪除。emptyDir Volume主要用於某些應用程式無需永久儲存的臨時目錄,多個容器的共享目錄等。

Emptydir的官方網址:

https://kubernetes.io/docs/concepts/storage/volumes#emptydir

[root@k8s-master1 ~]# cat emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-empty
spec:
  containers:
  - name: container-empty
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - emptyDir: {}
    name: cache-volume

# 更新資源清單檔案
[root@k8s-master1 ~]# kubectl apply -f emptydir.yaml 
pod/pod-empty created

# 檢視本機臨時目錄存在的位置,可用如下方法:
# 檢視pod排程到哪個節點
[root@k8s-master1 ~]# kubectl get pods -o wide | grep empty
pod-empty   1/1     Running   0          12s   10.244.36.117   k8s-node1   <none>           <none>

# 檢視pod的uid
[root@k8s-master1 ~]# kubectl get pods pod-empty -o yaml | grep uid
uid: ba7abc07-b984-49d2-a46f-01bac9a7f5ec

# 登入到k8s-node1上
[root@k8s-node1 ~]# tree /var/lib/kubelet/pods/ba7abc07-b984-49d2-a46f-01bac9a7f5ec
/var/lib/kubelet/pods/ba7abc07-b984-49d2-a46f-01bac9a7f5ec
├── containers
│ └── container-empty
│     └── da09ccbb
├── etc-hosts
├── plugins
│ └── kubernetes.io~empty-dir
│     ├── cache-volume
│     │ └── ready
│     └── wrapped_default-token-cm4mx
│         └── ready
└── volumes
    ├── kubernetes.io~empty-dir
    │ └── cache-volume
    └── kubernetes.io~secret
        └── default-token-cm4mx
            ├── ca.crt -> ..data/ca.crt
            ├── namespace -> ..data/namespace
            └── token -> ..data/token
            
# 臨時目錄在本地的/var/lib/kubelet/pods/ba7abc07-b984-49d2-a46f-01bac9a7f5ec/volumes/kubernetes.io~empty-dir/cache-volume/下
# 在臨時目錄建立檔案並進入容器檢視
[root@k8s-node1 ~]# cd /var/lib/kubelet/pods/ba7abc07-b984-49d2-a46f-01bac9a7f5ec/volumes/kubernetes.io~empty-dir/cache-volume/
[root@k8s-node1 cache-volume]# echo 123 > a.txt
[root@k8s-master1 ~]# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
pod-empty   1/1     Running   0          4m4s
[root@k8s-master1 ~]# kubectl exec -it pod-empty -- cat /cache/a.txt
123

2.2、hostPath

hostPath Volume是指Pod掛載宿主機上的目錄或檔案。 hostPath Volume使得容器可以使用宿主機的檔案系統進行儲存,hostpath(宿主機路徑):節點級別的儲存卷,在pod被刪除,這個儲存卷還是存在的,不會被刪除,所以只要同一個pod被排程到同一個節點上來,在pod被刪除重新被排程到這個節點之後,對應的資料依然是存在的。

# 建立一個pod,掛載hostPath儲存卷
[root@k8s-master1 ~]# cat hostpath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-hostpath
spec:
  #nodeName: k8s-node1
  containers:
  - image: nginx
    name: test-nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /test-nginx
      name: test-volume
  - image: tomcat:8.5-jre8-alpine
    name: test-tomcat
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /test-tomcat
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /data1
      type: DirectoryOrCreate # DirectoryOrCreate表示本地有/data1目錄,就用本地的,本地沒有就會在pod排程到的節點自動建立一個

# 更新資源清單檔案
[root@k8s-master1 ~]# kubectl apply -f hostpath.yaml 
pod/test-hostpath created

# 檢視pod排程到了哪個物理節點
[root@k8s-master1 ~]# kubectl get pods -o wide | grep hostpath
test-hostpath   2/2     Running   0          29s   10.244.36.118   k8s-node1   <none>           <none> 

# 由上面可以知道pod排程到了k8s-node1上,登入到k8s-node1機器,檢視是否在這臺機器建立了儲存目錄
[root@k8s-node1 ~]# ll /data1/
total 0
# 上面可以看到已經建立了儲存目錄/data1,這個/data1會作為pod的持久化儲存目錄

# 在k8s-node1上的/data1下建立一個目錄
[root@k8s-node1 ~]# cd /data1/
[root@k8s-node1 data1]# mkdir aa
# 測試儲存卷是否可以正常使用,登入到nginx容器

[root@k8s-master1 ~]# kubectl exec -it test-hostpath -c test-nginx -- /bin/bash      
root@test-hostpath:/# cd /test-nginx/  
#/test-nginx/目錄存在,說明已經把宿主機目錄掛載到了容器裡
root@test-hostpath:/test-nginx# ls
aa

#測試儲存卷是否可以正常使用,登入到tomcat容器
[root@k8s-master1 ~]# kubectl exec -it test-hostpath -c test-tomcat -- /bin/bash
root@test-hostpath:/usr/local/tomcat# cd /test-tomcat/
#/test-tomcat/目錄存在,說明已經把宿主機目錄掛載到了容器裡
root@test-hostpath:/test-tomcat# ls
aa

#通過上面測試可以看到,同一個pod裡的test-nginx和test-tomcat這兩個容器是共享儲存卷的。

hostPath儲存缺點:單節點,pod刪除之後重新建立必須排程到同一個node節點,資料才不會丟失

解決方法:定義nodeName,將pod排程到指定節點

2.3、nfs

hostPath儲存,存在單點故障,pod掛載hostPath時,只有排程到同一個節點,資料才不會丟失。那可以使用nfs作為持久化儲存

1)安裝nfs

# 搭建nfs服務,以k8s的控制節點作為NFS服務端
[root@k8s-master1 ~]# yum install nfs-utils -y

# 在宿主機建立NFS需要的共享目錄
[root@k8s-master1 ~]# mkdir /data/volumes -p

# 配置nfs共享伺服器上的/data/volumes目錄
[root@k8s-master1 ~]# systemctl start nfs
[root@k8s-master1 ~]# vim /etc/exports
/data/volumes 192.168.40.0/24(rw,no_root_squash)  # no_root_squash: 使用者具有根目錄的完全管理訪問許可權
# 使NFS配置生效
[root@k8s-master1 ~]# exportfs -arv
exporting 192.168.40.0/24:/data/volumes
[root@k8s-master1 ~]# systemctl restart nfs

# 設定成開機自啟動
[root@k8s-master1 ~]# systemctl enable nfs && systemctl status nfs

# k8s-node2和k8s-node1上也安裝nfs驅動
[root@k8s-node1 ~]# yum install nfs-utils -y && systemctl enable nfs
[root@k8s-node2 ~]# yum install nfs-utils -y && systemctl enable nfs

# 在k8s-node1上手動掛載試試:

[root@k8s-node1 ~]# mkdir /test 
[root@k8s-node1 ~]# mount 192.168.40.180:/data/volumes /test/
[root@k8s-node1 ~]# df -h
192.168.40.180:/data/volumes   50G  5.2G   45G  11% /test

# 手動解除安裝:
[root@k8s-node1 ~]# umount /test

2)建立Pod,掛載NFS共享出來的目錄

[root@k8s-master1 ~]# cat nfs.yaml 
apiVersion: v1
kind: Pod
metadata:
 name: test-nfs-volume
spec:
 containers:
 - name: test-nfs
   image: nginx
   imagePullPolicy: IfNotPresent
   ports:
   - containerPort: 80
     protocol: TCP
   volumeMounts:
   - name: nfs-volumes
     mountPath: /usr/share/nginx/html
 volumes:
 - name: nfs-volumes
   nfs:
    path: /data/volumes	# nfs的共享目錄
    server: 192.168.40.180 # 安裝nfs服務的地址

# 更新資源清單檔案
[root@k8s-master1 ~]# kubectl apply -f nfs.yaml

# 檢視pod是否建立成功
[root@k8s-master1 ~]# kubectl get pods -o wide | grep nfs
test-nfs-volume   1/1     Running   0          17s     10.244.36.119   k8s-node1   <none>           <none>

# 登入到nfs伺服器,在共享目錄建立一個index.html
[root@k8s-master1 volumes]# pwd
/data/volumes
[root@k8s-master1 volumes]# cat index.html 
Hello, NFS Volume

# 請求pod,看結果
[root@k8s-master1 volumes]# curl 10.244.36.119
Hello, NFS Volume

# 登入到pod驗證下
[root@k8s-master1 volumes]# kubectl exec -it test-nfs-volume  -- /bin/bash
root@test-nfs-volume:/# cat /usr/share/nginx/html/index.html 
Hello, NFS Volume

# nfs支援多個客戶端掛載,可以建立多個pod,掛載同一個nfs伺服器共享出來的目錄;但是nfs如果宕機了,資料也就丟失了,所以需要使用分散式儲存,常見的分散式儲存有glusterfs和cephfs

2.4、PV&PVC

2.4.1、相關概念

官網:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes

1)PV是什麼?

PersistentVolume(PV)是群集中的一塊儲存,由管理員配置或使用儲存類動態配置。 它是叢集中的資源,就像pod是k8s叢集資源一樣。 PV是容量外掛,如Volumes,其生命週期獨立於使用PV的任何單個pod

2)PVC是什麼?

PersistentVolumeClaim(PVC)是一個持久化儲存卷,我們在建立pod時可以定義這個型別的儲存卷。 它類似於一個pod。 Pod消耗節點資源,PVC消耗PV資源。 Pod可以請求特定級別的資源(CPU和記憶體)。 pvc在申請pv的時候也可以請求特定的大小和訪問模式(例如,可以一次讀寫或多次只讀)。****

2.4.2、PVC和PV工作原理

PV是群集中的資源。 PVC是對這些資源的請求。 PV和PVC之間的相互作用遵循以下生命週期:

1)pv的供應方式
可以通過兩種方式配置PV:靜態或動態。

  • 靜態:叢集管理員建立了許多PV。它們包含可供群集使用者使用的實際儲存的詳細資訊。它們存在於Kubernetes API中,可供使用。
  • 動態:當管理員建立的靜態PV都不匹配使用者的PersistentVolumeClaim時,群集可能會嘗試為PVC專門動態配置卷。此配置基於StorageClasses,PVC必須請求儲存類,管理員必須建立並配置該類,以便進行動態配置。

2)繫結
使用者建立pvc並指定需要的資源和訪問模式。在找到可用pv之前,pvc會保持未繫結狀態

3)使用

a)需要找一個儲存伺服器,把它劃分成多個儲存空間;
b)k8s管理員可以把這些儲存空間定義成多個pv;
c)在pod中使用pvc型別的儲存卷之前需要先建立pvc,通過定義需要使用的pv的大小和對應的訪問模式,找到合適的pv;
d)pvc被建立之後,就可以當成儲存捲來使用了,我們在定義pod時就可以使用這個pvc的儲存卷
e)pvc和pv它們是一一對應的關係,pv如果被pvc綁定了,就不能被其他pvc使用了;
f)我們在建立pvc的時候,應該確保和底下的pv能繫結,如果沒有合適的pv,那麼pvc就會處於pending狀態。

4)回收策略

當我們建立pod時如果使用pvc做為儲存卷,那麼它會和pv繫結,當刪除pod,pvc和pv繫結就會解除,解除之後和pvc繫結的pv卷裡的資料需要怎麼處理,目前,卷可以保留,回收或刪除:

  • Retain:當刪除pvc的時候,pv仍然存在,處於released狀態,但是它不能被其他pvc繫結使用,裡面的資料還是存在的,當我們下次再使用的時候,資料還是存在的,這個是預設的回收策略
  • Recycle:(不推薦使用,1.15可能被廢棄了)
  • Delete:刪除pvc時即會從Kubernetes中移除PV,也會從相關的外部設施中刪除儲存資產

2.4.3、pod使用pvc作為持久化儲存卷

1)建立nfs共享目錄

# 在宿主機建立NFS需要的共享目錄
[root@k8s-master1 ~]# mkdir /data/volume_test/v{1,2,3,4,5,6,7,8,9,10} -p

# 配置nfs共享宿主機上的/data/volume_test/v1..v10目錄
[root@k8s-master1 ~]# cat /etc/exports
/data/volumes 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v1 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v2 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v3 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v4 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v5 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v6 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v7 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v8 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v9 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v10 192.168.40.0/24(rw,no_root_squash)

# 重新載入配置,使配置成效
[root@k8s-master1 ~]# exportfs -arv

2)建立pv

[root@k8s-master1 ~]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v1
spec:
  capacity:
    storage: 1Gi  #pv的儲存空間容量
  accessModes: ["ReadWriteOnce"]
  nfs:
    path: /data/volume_test/v1 #nfs的儲存空間建立成pv
    server: 192.168.40.180     #nfs伺服器的地址
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v2
spec:
  capacity:
      storage: 2Gi
  accessModes: ["ReadWriteMany"]
  nfs:
    path: /data/volume_test/v2
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v3
spec:
  capacity:
      storage: 3Gi
  accessModes: ["ReadOnlyMany"]
  nfs:
    path: /data/volume_test/v3
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v4
spec:
  capacity:
      storage: 4Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v4
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v5
spec:
  capacity:
      storage: 5Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v5
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v6
spec:
  capacity:
      storage: 6Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v6
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v7
spec:
  capacity:
      storage: 7Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v7
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v8
spec:
  capacity:
      storage: 8Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v8
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v9
spec:
  capacity:
      storage: 9Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v9
    server: 192.168.40.180
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  v10
spec:
  capacity:     
      storage: 10Gi
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  nfs:
    path: /data/volume_test/v10  
    server: 192.168.40.180

# 更新資源清單檔案
[root@k8s-master1 ~]# kubectl apply -f pv.yaml 
persistentvolume/v1 created
persistentvolume/v2 created
persistentvolume/v3 created
persistentvolume/v4 created
persistentvolume/v5 created
persistentvolume/v6 created
persistentvolume/v7 created
persistentvolume/v8 created
persistentvolume/v9 created
persistentvolume/v10 created

# 檢視pv資源
[root@k8s-master1 ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
v1     1Gi        RWO            Retain           Available                                   11s
v10    10Gi       RWO,RWX        Retain           Available                                   11s
v2     2Gi        RWX            Retain           Available                                   11s
v3     3Gi        ROX            Retain           Available                                   11s
v4     4Gi        RWO,RWX        Retain           Available                                   11s
v5     5Gi        RWO,RWX        Retain           Available                                   11s
v6     6Gi        RWO,RWX        Retain           Available                                   11s
v7     7Gi        RWO,RWX        Retain           Available                                   11s
v8     8Gi        RWO,RWX        Retain           Available                                   11s
v9     9Gi        RWO,RWX        Retain           Available                                   11s
# STATUS是Available,表示pv是可用的

3)建立pvc,和符合條件的pv繫結

[root@k8s-master1 ~]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 2Gi

# 更新資源清單檔案
[root@k8s-master1 ~]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/my-pvc created

# 檢視pv和pvc
[root@k8s-master1 ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON   AGE
v1     1Gi        RWO            Retain           Available                                            4m35s
v10    10Gi       RWO,RWX        Retain           Available                                            4m35s
v2     2Gi        RWX            Retain           Bound       default/my-pvc                           4m35s
v3     3Gi        ROX            Retain           Available                                            4m35s
v4     4Gi        RWO,RWX        Retain           Available                                            4m35s
v5     5Gi        RWO,RWX        Retain           Available                                            4m35s
v6     6Gi        RWO,RWX        Retain           Available                                            4m35s
v7     7Gi        RWO,RWX        Retain           Available                                            4m35s
v8     8Gi        RWO,RWX        Retain           Available                                            4m35s
v9     9Gi        RWO,RWX        Retain           Available                                            4m35s
# STATUS是Bound,表示這個pv已經被my-pvc綁定了

[root@k8s-master1 ~]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc   Bound    v2       2Gi        RWX                           31s

4)建立pod,掛載pvc

[root@k8s-master1 ~]# cat pod_pvc.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-html
    persistentVolumeClaim:
      claimName: my-pvc

# 更新資源清單檔案
[root@k8s-master1 ~]# kubectl apply -f pod_pvc.yaml 
pod/pod-pvc created

# 檢視pod狀態
[root@k8s-master1 ~]# kubectl get pods -o wide| grep pod-pvc
pod-pvc           1/1     Running   0          45s     10.244.169.151   k8s-node2   <none>           <none>
#通過上面可以看到pod處於running狀態,正常執行

2.4.4、使用pvc和pv的注意事項

1)我們每次建立pvc的時候,需要事先有劃分好的pv,這樣可能不方便,那麼可以在建立pvc的時候直接動態建立一個pv這個儲存類,pv事先是不存在的

2)pvc和pv繫結,如果使用預設的回收策略retain,那麼刪除pvc之後,pv會處於released狀態,我們想要繼續使用這個pv,需要手動刪除pv,kubectl delete pv pv_name,刪除pv,不會刪除pv裡的資料,當我們重新建立pvc時還會和這個最匹配的pv繫結,資料還是原來資料,不會丟失。

2.5、k8s儲存類:storageclass

上面介紹的PV和PVC模式都是需要先建立好PV,然後定義好PVC和pv進行一對一的Bond,但是如果PVC請求成千上萬,那麼就需要建立成千上萬的PV,對於運維人員來說維護成本很高,Kubernetes提供一種自動建立PV的機制,叫StorageClass,它的作用就是建立PV的模板。k8s叢集管理員通過建立storageclass可以動態生成一個儲存卷pv供k8s pvc使用。

每個StorageClass都包含欄位provisionerparametersreclaimPolicy

具體來說,StorageClass會定義以下兩部分:

  • 1、PV的屬性 ,比如儲存的大小、型別等;
  • 2、建立這種PV需要使用到的儲存外掛,比如Ceph、NFS等

Kubernetes就能夠根據使用者提交的PVC,找到對應的StorageClass,然後Kubernetes就會呼叫 StorageClass宣告的儲存外掛,創建出需要的PV。

provisioner:供應商,storageclass需要有一個供應者,用來確定我們使用什麼樣的儲存來建立pv

常見的provisioner:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

provisioner既可以由內部供應商提供,也可以由外部供應商提供:https://github.com/kubernetes-incubator/external-storage/

以NFS為例,要想使用NFS,我們需要一個nfs-client的自動裝載程式,稱之為provisioner,這個程式會使用我們已經配置好的NFS伺服器自動建立持久卷,也就是自動幫我們建立PV。

reclaimPolicy:回收策略

allowVolumeExpansion:允許卷擴充套件,PersistentVolume 可以配置成可擴充套件。將此功能設定為true時,允許使用者通過編輯相應的 PVC 物件來調整卷大小。當基礎儲存類的allowVolumeExpansion欄位設定為 true 時,以下型別的卷支援卷擴充套件。注意:此功能僅用於擴容卷,不能用於縮小卷

2.5.1、安裝nfs provisioner,用於配合儲存類動態生成pv

# 1、建立執行nfs-provisioner需要的sa賬號
[root@k8s-master1 nfs]# cat serviceaccount.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner

[root@k8s-master1 nfs]# kubectl apply -f serviceaccount.yaml 
serviceaccount/nfs-provisioner created

# 2、對sa授權 
[root@k8s-master1 nfs]# kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner

# 3、安裝nfs-provisioner程式
[root@k8s-master1 nfs]# mkdir /data/nfs_pro -p

#把/data/nfs_pro變成nfs共享的目錄
[root@k8s-master1 nfs]# cat /etc/exports
/data/volumes 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v1 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v2 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v3 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v4 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v5 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v6 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v7 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v8 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v9 192.168.40.0/24(rw,no_root_squash)
/data/volume_test/v10 192.168.40.0/24(rw,no_root_squash)
/data/nfs_pro 192.168.40.0/24(rw,no_root_squash)

[root@k8s-master1 nfs]# exportfs -arv
exporting 192.168.40.0/24:/data/nfs_pro
exporting 192.168.40.0/24:/data/volume_test/v10
exporting 192.168.40.0/24:/data/volume_test/v9
exporting 192.168.40.0/24:/data/volume_test/v8
exporting 192.168.40.0/24:/data/volume_test/v7
exporting 192.168.40.0/24:/data/volume_test/v6
exporting 192.168.40.0/24:/data/volume_test/v5
exporting 192.168.40.0/24:/data/volume_test/v4
exporting 192.168.40.0/24:/data/volume_test/v3
exporting 192.168.40.0/24:/data/volume_test/v2
exporting 192.168.40.0/24:/data/volume_test/v1
exporting 192.168.40.0/24:/data/volumes

[root@k8s-master1 nfs]# cat nfs-deployment.yaml 
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-provisioner
spec:
  selector:
    matchLabels:
       app: nfs-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: 192.168.40.180
            - name: NFS_PATH
              value: /data/nfs_pro
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.40.180
            path: /data/nfs_pro
            
# 更新資源清單檔案
[root@k8s-master1 nfs]# kubectl apply -f nfs-deployment.yaml 
deployment.apps/nfs-provisioner created

# 檢視nfs-provisioner是否正常執行
[root@k8s-master1 nfs]# kubectl get pods | grep nfs
nfs-provisioner-5448d86c75-j4xr9   1/1     Running   0          11s

2.5.2、建立storageclass,動態供給pv

[root@k8s-master1 nfs]# cat nfs-storageclass.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: nfs
provisioner: example.com/nfs # 跟安裝nfs provisioner時候的env下的PROVISIONER_NAME的value值保持一致

[root@k8s-master1 nfs]# kubectl apply -f nfs-storageclass.yaml

#檢視storageclass是否建立成功
[root@k8s-master1 nfs]# kubectl get storageclass
NAME   PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs    example.com/nfs   Delete          Immediate           false                  13s

2.5.3、建立pvc,通過storageclass動態生成pv

[root@k8s-master1 nfs]# cat claim.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes:  ["ReadWriteMany"]
  resources:
    requests:
      storage: 1Gi
  storageClassName:  nfs
  
[root@k8s-master1 nfs]# kubectl apply -f claim.yaml 
persistentvolumeclaim/test-claim1 created

# 檢視是否動態生成了pv,pvc是否建立成功,並和pv繫結
[root@k8s-master1 nfs]# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-claim1   Bound    pvc-bfad2595-f3e8-4f41-a1d7-4b760655c6f4   1Gi        RWX            nfs            17s

步驟總結
1、供應商:建立一個nfs provisioner
2、建立storageclass,storageclass指定剛才建立的供應商
3、建立pvc,這個pvc指定storageclass

2.5.4、建立pod,掛載storageclass動態生成的pvc

[root@k8s-master1 nfs]# cat read-pod.yaml 
kind: Pod
apiVersion: v1
metadata:
  name: read-pod
spec:
  containers:
  - name: read-pod
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
      - name: nfs-pvc
        mountPath: /usr/share/nginx/html
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim1

# 更新資源清單檔案
[root@k8s-master1 nfs]# kubectl apply -f read-pod.yaml 
pod/read-pod created

# 檢視pod是否建立成功
[root@k8s-master1 nfs]# kubectl get pods -o wide| grep read
read-pod                           1/1     Running   0          16s     10.244.36.121   k8s-node1   <none>           <none>

# 持久化目錄
[root@k8s-master1 nfs]# ll /data/nfs_pro/
total 0
drwxrwxrwx 2 root root 6 Jul 10 22:30 default-test-claim1-pvc-bfad2595-f3e8-4f41-a1d7-4b760655c6f4
作者:Lawrence 出處:http://www.cnblogs.com/hujinzhong/

-------------------------------------------

個性簽名:獨學而無友,則孤陋而寡聞。做一個靈魂有趣的人!

掃描上面二維碼關注我 如果你真心覺得文章寫得不錯,而且對你有所幫助,那就不妨幫忙“推薦"一下,您的“推薦”和”打賞“將是我最大的寫作動力! 本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線.