(九)Kubernetes 存儲卷


Kubernetes存儲卷概述

Pod本身具有生命周期,這就帶了一系列的問題,第一,當一個容器損壞之后,kubelet會重啟這個容器,但是文件會丟失-這個容器會是一個全新的狀態;第二,當很多容器在同一Pod中運行的時候,很多時候需要數據文件的共享。Docker支持配置容器使用存儲卷將數據持久存儲於容器自身文件系統之外的存儲空間之中,它們可以是節點文件系統或網絡文件系統之上的存儲空間。相應的,kubernetes也支持類似的存儲卷功能,不過,其存儲卷是與Pod資源綁定而非容器。

簡單來說,存儲卷是定義在Pod資源之上、可被其內部的所有容器掛載的共享目錄,它關聯至某外部的存儲設備之上的存儲空間,從而獨立於容器自身的文件系統,而數據是否具有持久能力取決於存儲卷自身是否支持持久機制。Pod、容器與存儲卷的關系圖如下。

Kubernetes支持的存儲卷類型

Kubernetes支持非常豐富的存儲卷類型,包括本地存儲(節點)和網絡存儲系統中的諸多存儲機制,還支持SecretConfigMap這樣的特殊存儲資源。例如,關聯節點本地的存儲目錄與關聯GlusterFS存儲系統所需要的配置參數差異巨大,因此指定存儲卷類型時也就限定了其關聯到的后端存儲設備。通過命令# kubectl explain pod.spec可以查看當前kubernetes版本支持的存儲卷類型。常用類型如下:

  • 非持久性存儲

  • emptyDir

  • hostPath

  • 網絡連接性存儲

  • SAN:iscsi

  • NFS:nfs、cfs

  • 分布式存儲

  • glusterfs、cephfs、rbd

  • 雲端存儲

  • awsElasticBlockStore、azureDisk、gitRepo

存儲卷的使用方式

在Pod中定義使用存儲卷的配置由兩部分組成:一是通過.spec.volumes字段定義在Pod之上的存儲卷列表,其支持使用多種不同類型的存儲卷且配置參數差別很大;另一個是通過.spce.containers.volumeMounts字段在容器上定義的存儲卷掛載列表,它只能掛載當前Pod資源中定義的具體存儲卷,當然,也可以不掛載任何存儲卷。

在Pod級別定義存儲卷時,.spec.volumes字段的值為對象列表格式,每個對象為一個存儲卷的定義,由存儲卷名稱(.spec.volumes.name <string>)或存儲卷對象(.spec.volumes.VOL_TYPE <Object>)組成,其中VOL_TYPE是使用的存儲卷類型名稱,它的內嵌字段隨類型的不同而不同。下面示例定義了由兩個存儲卷組成的卷列表,一個為emptyDir類型,一個是gitRepo類型。

......
volumes:
- name: data
  emptyDir: {}
- name: example
  gitRepo:
    repository: https://github.com/ikubernetes/k8s_book.git
    revision: master
    directory:

無論何種類型的存儲卷,掛載格式基本上都是相同的,通過命令# kubectl explain pod.spec.containers.volumeMounts 可以進行查看。在容器中頂一個掛載卷時的通用語法形式如下:

......
volumeMounts:
- name    <string> -required-      #指定要掛載的存儲卷的名稱,必選字段
  mountPath    <string> -required-  #掛載點路徑,容器文件系統的路徑,必選字段
  readOnly    <boolean>            #是否掛載為只讀卷
  subPath    <string>             #掛載存儲卷時使用的子路徑,及mountPath指定的路徑下使用一個子路徑作為其掛載點。

示例,容器myapp將上面定義的data存儲卷掛載於/var/log/myapp,將examply掛載到/webdata/example目錄。

spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: data
      mountPath: /var/log/myapp/
    - name: example
      mountPath: /webdata/example/

存儲卷使用示例

下面的所有示例的資源清單文件都放在新建的storage目錄中。

[root@k8s-master ~]# mkdir storage
[root@k8s-master ~]# cd storage/

emptyDir 存儲卷

emptyDir存儲卷是Pod對象生命周期中的一個臨時目錄,類似於Docker上的“docker 掛載卷”,在Pod對象啟動時即被創建,而在Pod對象被移除時會被一並刪除(永久刪除)。Pod中的容器都可以讀寫這個目錄,這個目錄可以被掛載到各個容器相同或者不相同的路徑下。注意:一個容器崩潰了不會導致數據的丟失,因為容器的崩潰並不移除Pod

emptyDir的作用:

  1. 普通空間,基於磁盤的數據存儲

  2. 作為從崩潰中恢復的備份點

  3. 存儲那些需要長久保存的數據,例如web服務中的數據

emptyDir字段說明:

[root@k8s-master ~]# kubectl explain pod.spec.volumes.emptyDir
medium    <string>:    #此目錄所在的存儲介質的類型,可取值為“default”或“Memory”,默認為default,表示使用節點的的默認存儲介質;Memory表示使用基於RAM的臨時的文件系統temfs,空間受限於內存,但性能非常好,通常用於為容器中的應用提供緩存空間。
sizeLimit    <string>    #當前存儲卷的空間限額,默認值為nil,表示不限制;不過,在medium字段值為“Memory”時建議務必定義此限額。

emptyDir示例:

這里定義了一個Pod資源對象(vol-emptydir-pod),在其內部定義了兩個容器,其中一個容器是輔助容器sidecar,每隔10秒生成一行信息追加到index.html文件中;另一個是nginx容器,將存儲卷掛載到站點家目錄。然后訪問nginxhtml頁面驗證兩個容器之間掛載的emptyDir實現共享。

1)編輯資源清單文件

[root@k8s-master storage]# vim vol-emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: vol-emptydir-pod
spec:
  volumes:    #定義存儲卷
  - name: html    #定義存儲卷的名稱
    emptyDir: {}    #定義存儲卷的類型
  containers:
  - name: nginx
    image: nginx:1.12
    volumeMounts:    #在容器中定義掛載存儲卷的名和路徑
    - name: html
      mountPath: /usr/share/nginx/html
  - name: sidecar
    image: alpine
    volumeMounts:    #在容器中定義掛載存儲卷的名和路徑
    - name: html
      mountPath: /html
    command: ["/bin/sh", "-c"]
    args:
    - while true; do
        echo $(hostname) $(date) >> /html/index.html;
      sleep 10;
      done

2)創建並查看狀態

[root@k8s-master storage]# kubectl apply -f vol-emptydir.yaml 
pod/vol-emptydir-pod created
[root@k8s-master storage]# kubectl get pods -o wide 
NAME               READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
vol-emptydir-pod   2/2     Running   0          63s   10.244.2.79   k8s-node2   <none>           <none>

3)訪問測試

[root@k8s-master storage]# curl 10.244.2.79
vol-emptydir-pod Wed Oct 9 03:32:43 UTC 2019
vol-emptydir-pod Wed Oct 9 03:32:53 UTC 2019
vol-emptydir-pod Wed Oct 9 03:33:03 UTC 2019
vol-emptydir-pod Wed Oct 9 03:33:13 UTC 2019
vol-emptydir-pod Wed Oct 9 03:33:23 UTC 2019
......

#進入vol-emptydir-pod中的sidecar容器中查看掛載目錄下的index.html文件
[root@k8s-master storage]# kubectl exec vol-emptydir-pod -c sidecar -it -- /bin/sh
/ # ls 
bin    etc    html   media  opt    root   sbin   sys    usr
dev    home   lib    mnt    proc   run    srv    tmp    var
/ # ls /html
index.html
/ # cat /html/index.html 
vol-emptydir-pod Wed Oct 9 03:32:43 UTC 2019
vol-emptydir-pod Wed Oct 9 03:32:53 UTC 2019
vol-emptydir-pod Wed Oct 9 03:33:03 UTC 2019
......

#進入vol-emptydir-pod中的nginx容器中查看掛載目錄下的index.html文件
[root@k8s-master storage]# kubectl exec vol-emptydir-pod -c nginx -it -- /bin/sh
# cat /usr/share/nginx/html/index.html
vol-emptydir-pod Wed Oct 9 03:32:43 UTC 2019
vol-emptydir-pod Wed Oct 9 03:32:53 UTC 2019
vol-emptydir-pod Wed Oct 9 03:33:03 UTC 2019
......

hostPath 存儲卷

hostPath類型的存儲卷是指將工作節點上的某文件系統的目錄或文件掛載於Pod中的一種存儲卷,獨立於Pod資源的生命周期,具有持久性。在Pod刪除時,數據不會丟失。

hostPath字段說明:

[root@k8s-master storage]# kubectl explain pod.spec.volumes.hostPath
path    <string> -required-    #指定工作節點上的目錄路徑
type    <string>    #指定存儲卷類型

type類型如下:
DirectoryOrCreate    指定的路徑不存在時自動創建其權限為0755的空目錄,屬主和屬組為kubelet
Directory            必須存在的目錄路徑
FileOrCreate         指定的路徑不存在時自動創建其權限為0644的空文件,屬主和屬組為kubelet
File                 必須存在的文件路徑
Socket               必須存在的Socket文件路徑
CharDevice           必須存在的字符設備文件路徑
BlockDevice          必須存在的塊設備文件路徑

hostPath示例:

1)編輯資源清單文件

[root@k8s-master storage]# vim vol-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-hostpath
  namespace: default
spec:
  containers:
  - name: myapp
    image: nginx:1.15
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    hostPath:
      path: /data/pod/volume1
      type: DirectoryOrCreate

2)創建並查看狀態

[root@k8s-master storage]# kubectl apply -f vol-hostpath.yaml 
pod/vol-hostpath-pod created
[root@k8s-master storage]# kubectl get pods -o wide 
NAME               READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
vol-hostpath-pod   1/1     Running   0          7s    10.244.1.83   k8s-node1   <none>           <none>

3)通過上面查看pod被調度到節點1上面,查看節點1的目錄並創建測試文件

[root@k8s-node1 ~]# ll /data/pod/volume1/
總用量 0
[root@k8s-node1 ~]# echo "<h1>kubernetes hostPath test</h1>" >> /data/pod/volume1/index.html

4)訪問測試,及刪除測試

[root@k8s-master storage]# curl 10.244.1.83
<h1>kubernetes hostPath test</h1>

#刪除pod資源再次查看節點1上面的文件
[root@k8s-master storage]# kubectl delete -f vol-hostpath.yaml 
pod "vol-hostpath-pod" deleted
[root@k8s-node1 ~]# ll /data/pod/volume1/
總用量 4
-rw-r--r-- 1 root root 34 10月  9 16:09 index.html

nfs 存儲卷

nfs存儲卷用於將事先存在的NFS服務器上導出的存儲空間掛載到Pod中供容器使用。與emptyDir不同的是,當pod資源刪除時emptyDir也會被刪除,而NFSPod對象刪除時僅是被卸載而非刪除。這就意味NFS能夠允許我們提前對數據進行處理,而且這些數據可以在Pod之間相互傳遞,並且NFS可以同時被多個Pod掛載並進行讀寫。

nfs字段說明:

[root@k8s-master ~]# kubectl explain pod.spec.volumes.nfs
server    <string> -required-    #NFS服務器的IP地址或主機名,必選字段
path    <string> -required-    #NFS服務器導出(共享)的文件系統路徑,必選字段
readOnly    <boolean>          #是否以只讀方式掛載,默認為false

nfs示例:

1)首先准備一個nfs服務器

[root@storage ~]# yum -y install nfs-utils    #安裝軟件
[root@storage ~]# mkdir -p /data/k8s/v1    #創建共享目錄
[root@storage ~]# vim /etc/exports    #編輯配置文件配置共享目錄
/data/k8s/v1  192.168.1.0/24(rw,no_root_squash)
[root@storage ~]# systemctl start rpcbind    #啟動rpcbind服務(nfs依賴服務)
[root@storage ~]# systemctl start nfs    #啟動nfs

[root@k8s-node1 ~]# showmount -e 192.168.1.34    #k8s節點測試能否正常訪問到nfs服務器
Export list for 192.168.1.34:
/data/k8s/v1 192.168.1.0/24

2)編輯資源清單文件

[root@k8s-master storage]# vim vol-nfs.yaml

3)創建並查看狀態

[root@k8s-master storage]# kubectl apply -f vol-nfs.yaml 
pod/vol-nfs-pod created
[root@k8s-master storage]# kubectl get pods 
NAME          READY   STATUS    RESTARTS   AGE
vol-nfs-pod   1/1     Running   0          45s
[root@k8s-master storage]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
vol-nfs-pod   1/1     Running   0          51s   10.244.2.80   k8s-node2   <none>           <none>

4)測試驗證

[root@k8s-master storage]# kubectl exec -it vol-nfs-pod redis-cli
127.0.0.1:6379> set mykey "hello test"
OK
127.0.0.1:6379> get mykey
"hello test
127.0.0.1:6379> bgsave 
Background saving started
127.0.0.1:6379> exit

#為了測試其數據持久化效果,下面刪除Pod資源vol-nfs-pod,並於再次重新創建后檢測數據是否依然能夠訪問
[root@k8s-master storage]# kubectl delete -f vol-nfs.yaml 
pod "vol-nfs-pod" deleted
[root@k8s-master storage]# kubectl apply -f vol-nfs.yaml 
pod/vol-nfs-pod created
[root@k8s-master storage]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
vol-nfs-pod   1/1     Running   0          47s   10.244.1.84   k8s-node1   <none>           <none>
[root@k8s-master storage]# kubectl exec -it vol-nfs-pod redis-cli
127.0.0.1:6379> get mykey
"hello test"
127.0.0.1:6379>

通過上面測試可以看出,此前創建的mykey及其數據在Pod資源重建后依然存在,且不論pod資源調度到哪個節點。這表明在刪除Pod資源時,其關聯的外部存儲卷並不會被一同刪除。如果需要刪除此類的數據,需要用戶通過存儲系統的管理接口手動進行。

PVC與PV

介紹

前面提到Kubernetes提供那么多存儲接口,但是首先Kubernetes的各個Node節點能管理這些存儲,但是各種存儲參數也需要專業的存儲工程師才能了解,由此我們的Kubernetes管理變的更加復雜。由此kubernetes提出了PVPVC的概念,這樣開發人員和使用者就不需要關注后端存儲是什么,使用什么參數等問題。如下圖:

PV:

PersistentVolumePV)是集群中已由管理員配置的一段網絡存儲。集群中的資源就像一個節點是一個集群資源。PV是諸如卷之類的卷插件,但是具有獨立於使用PV的任何單個Pod的生命周期。該API對象捕獲存儲的實現細節,即NFSISCSI或雲提供商特定的存儲系統。

PVC:

PersistentVolumeClaimPVC)是用戶存儲的請求。它類似於PodPod消耗節點資源,PVC消耗存儲資源。Pod可以請求特定級別的資源(CPU和內存)。權限要求可以請求特定的大小和訪問模式。

雖然PersistentVolumeClaims允許用戶使用抽象存儲資源,但是常見的是,用戶需要具有不同屬性(如性能)的PersistentVolumes,用於不同的問題。集群管理員需要能夠提供多種不同於PersistentVolumesPersistentVolumes,而不僅僅是大小和訪問模式,而不會使用戶了解這些卷的實現細節。對於這些需求,存在StorageClass資源。

StorageClass為管理員提供了一種描述他們提供的存儲的“類”的方法。不同的類可能映射到服務質量級別,或備份策略,或者由集群管理員確定的任意策略。Kubernetes本身對於什么類別代表是不言而喻的。這個概念有時在其它存儲系統中稱為“配置文件”

生命周期

PV是集群中的資源。PVC是對這些資源的請求,也是對資源的索賠檢查。PVPVC之間的相互作用遵循這個生命周期:

Provisioning—>Binding—>Using—>Releasing—>Recycling

供應准備Provisioning

PV有兩種提供方式:靜態或者動態

  • Static:集群管理員創建多個PV。它們攜帶可供集群用戶使用的真實存儲的詳細信息。它們存在於Kubernetes API中,可用於消費。

  • Dynamic:當管理員創建的靜態PV都不匹配用戶的PersistentVolumesClaim時,集群可能會嘗試為PVC動態配置卷。此配置基於StorageClasses:PVC必須請求一個類,並且管理員必須已經創建並配置該類才能進行動態配置。要求該類的聲明有效地位自己禁用動態配置。

綁定Binding

用戶創建PVC並指定需要的資源和訪問模式。在找到可用PV之前,PVC會保持未綁定狀態。

使用Using

用戶可在Pod中像volume一樣使用PVC

釋放Releasing

用戶刪除PVC來回收存儲資源,PV將變成“released”狀態。由於還保留着之前的數據,這些數據要根據不同的策略來處理,否則這些存儲資源無法被其它PVC使用

回收Recycling

PV可以設置三種回收策略:保留(Retain)、回收(Recycle)和刪除(Delete)。

創建PV

字段說明:

PersistentVolume Spec主要支持以下幾個通用字段,用於定義PV的容量、訪問模式、和回收策略

[root@k8s-master ~]# kubectl explain pv.spec
capacity    <map[string]string>    #當前PV的容量;目前,capacity僅支持空間設定,將來應該還可以指定IOPS和throughput。

accessModes    <[]string>    #訪問模式;盡管在PV層看起來並無差異,但存儲設備支持及啟用的功能特性卻可能不盡相同。例如NFS存儲支持多客戶端同時掛載及讀寫操作,但也可能是在共享時僅啟用了只讀操作,其他存儲系統也存在類似的可配置特性。因此,PV底層的設備或許存在其特有的訪問模式,用戶使用時必須在其特性范圍內設定其功能。參考:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
    - ReadWribeOnce:僅可被單個節點讀寫掛載;命令行中簡寫為RWO。
    - ReadOnlyMany:可被多個節點同時只讀掛載;命令行中簡寫為ROX。
    - ReadWriteMany:可被多個節點同時讀寫掛載;命令行中簡寫為RWX。
    
persistentVolumeReclaimPolicy    <string>    #PV空間被釋放時的處理機制;可用類型僅為Retain(默認)、Recycle或Delete,具體說明如下。
    - Retain:保持不動,由管理員隨后手動回收。
    - Recycle:空間回收,即刪除存儲卷目錄下的所有文件(包括子目錄和隱藏文件),目前僅NFS和hostPath支持此操作。
    - Delete:刪除存儲卷,僅部分雲端存儲系統支持,如AWS EBS、GCE PD、Azure Disk和Cinder

volumeMode    <string>    #卷模型,用於指定此卷可被用作文件系統還是裸格式的塊設備;默認為Filesystem。

storageClassName    <string>    #當前PV所屬的StorageClass的名稱;默認為空值,即不屬於任何StorageClass。

mountOptions    <[]string>    #掛載選項組成的列表,如ro、soft和hard等。

創建PVC

字段說明:

PersistentVolumeClaim是存儲卷類型的資源,它通過申請占用某個PersistentVolume而創建,它與PV是一對一的關系,用戶無須關系其底層實現細節。申請時,用戶只需要指定目標空間的大小、訪問模式、PV標簽選擇器和StorageClass等相關信息即可。PVCSpec字段的可嵌套字段具體如下:

[root@k8s-master ~]# kubectl explain pvc.spec
accessModes    <[]string>    #當前PVC的訪問模式,其可用模式與PV相同

resources    <Object>    #當前PVC存儲卷需要占用的資源量最小值;目前,PVC的資源限定僅指其空間大小

selector    <Object>    #綁定時對PV應用的標簽選擇器(matchLabels)或匹配條件表達式(matchEx-pressions),用於挑選要綁定的PV;如果同時指定了兩種挑選機制,則必須同時滿足兩種選擇機制的PV才能被選出

storageClassName    <string>    #所依賴的存儲卷的名稱

volumeMode    <string>    #卷模型,用於指定此卷可被用作於文件系統還是裸格式的塊設備;默認為“Filesystem”

volumeName    <string>    #用於直接指定要綁定的PV的卷名

在Pod中使用PVC

Pod資源中調用PVC資源,只需要在定義volumes時使用persistentVolumeClaims字段嵌套指定兩個字段即可。具體如下:

[root@k8s-master ~]# kubectl explain pod.spec.volumes.persistentVolumeClaim
claimName    <string> -required-    #要調用的PVC存儲卷的名稱,PVC卷要與Pod在同一名稱空間中
readOnly    <boolean>    #是否將存儲卷掛載為只讀模式,默認為false。

示例使用PVC和PV

說明:下面示例中,准備了一台NFS Server創建了幾個共享目錄提供給Kubernetes作為PV使用。在創建PV的同時指定了不同的大小和不同的訪問權限,然后在創建PVC時候指定了大小為6Gi,故滿足條件的PV只有pv003~pv005,這里通過標簽選擇器選擇了pv003。Pod中的容器使用了MySQL,並將MySQL的數據目錄掛載到PV上。示例圖如下:

1)准備NFS服務

(1)創建存儲卷對應的目錄
[root@storage ~]# mkdir /data/volumes/v{1..5} -p

(2)修改nfs的配置文件
[root@storage ~]# vim /etc/exports
/data/volumes/v1  192.168.1.0/24(rw,no_root_squash)
/data/volumes/v2  192.168.1.0/24(rw,no_root_squash)
/data/volumes/v3  192.168.1.0/24(rw,no_root_squash)
/data/volumes/v4  192.168.1.0/24(rw,no_root_squash)
/data/volumes/v5  192.168.1.0/24(rw,no_root_squash)

(3)查看nfs的配置
[root@storage ~]# exportfs -arv
exporting 192.168.1.0/24:/data/volumes/v5
exporting 192.168.1.0/24:/data/volumes/v4
exporting 192.168.1.0/24:/data/volumes/v3
exporting 192.168.1.0/24:/data/volumes/v2
exporting 192.168.1.0/24:/data/volumes/v1

(4)使配置生效
[root@storage ~]# showmount -e
Export list for storage:
/data/volumes/v5 192.168.1.0/24
/data/volumes/v4 192.168.1.0/24
/data/volumes/v3 192.168.1.0/24
/data/volumes/v2 192.168.1.0/24
/data/volumes/v1 192.168.1.0/24

2)創建PV;這里創建5PV,存儲大小各不相等,是否可讀也不相同

(1)編寫資源清單文件
[root@k8s-master storage]# vim pv-nfs-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: 192.168.1.34
    readOnly: false 
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  capacity:
    storage: 2Gi
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: 192.168.1.34
    readOnly: false 
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 5Gi
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: 192.168.1.34
    readOnly: false 
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  capacity:
    storage: 10Gi
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: 192.168.1.34
    readOnly: false 
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  capacity:
    storage: 15Gi
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: 192.168.1.34
    readOnly: false 
  accessModes: ["ReadWriteOnce","ReadWriteMany"]
  capacity:
    storage: 20Gi
  persistentVolumeReclaimPolicy: Retain
  
(2)創建PV
[root@k8s-master storage]# kubectl apply -f pv-nfs-demo.yaml 
persistentvolume/pv-nfs-001 created
persistentvolume/pv-nfs-002 created
persistentvolume/pv-nfs-003 created
persistentvolume/pv-nfs-004 created
persistentvolume/pv-nfs-005 created

(3)查看PV
[root@k8s-master storage]# kubectl get pv
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs-001   2Gi        RWO,RWX        Retain           Available                                   2s
pv-nfs-002   5Gi        RWO            Retain           Available                                   2s
pv-nfs-003   10Gi       RWO,RWX        Retain           Available                                   2s
pv-nfs-004   15Gi       RWO,RWX        Retain           Available                                   2s
pv-nfs-005   20Gi       RWO,RWX        Retain           Available                                   2s

3)創建PVC,綁定PV

(1)編寫資源清單文件
[root@k8s-master storage]# vim vol-nfs-pvc.yaml
#創建PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 6Gi    #指定PVC大小為6Gi
  selector:    #這里通過標簽選擇器指定了所使用的pv卷為key為name,value為pv003的pv資源
    matchLabels:
      name: pv003
---
#創建Pod
apiVersion: v1
kind: Pod
metadata:
  name: pvc-mysql
  labels:
    app: mysql
spec:
  containers:
  - name: pvc-mysql-pod
    image: mysql:latest
    imagePullPolicy: IfNotPresent
    ports:
    - name: mysqlport
      containerPort: 3306
    volumeMounts: 
    - name: mysqldata
      mountPath: /var/lib/mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "mysql"
  volumes:
  - name: mysqldata
    persistentVolumeClaim:  #通過該字段定義使用pvc
      claimName: nfs-pvc    #指定pvc的名稱
      readOnly: false       #關閉只讀

(2)創建PVC和Pod
[root@k8s-master storage]# kubectl apply -f vol-nfs-pvc.yaml 
persistentvolumeclaim/nfs-pvc created
pod/pvc-mysql created

4)查詢驗證pvpvc

[root@k8s-master storage]# kubectl get pvc    #查看pvc,可以看到該pvc使用的是pv-nfs-003資源
NAME      STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc   Bound    pv-nfs-003   10Gi       RWO,RWX                       12s

[root@k8s-master storage]# kubectl get pv    #查看pv,可以看出pv-nfs-003資源的狀態從Availabel變成了Bound
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM             STORAGECLASS   REASON   AGE
pv-nfs-001   2Gi        RWO,RWX        Retain           Available                                             64m
pv-nfs-002   5Gi        RWO            Retain           Available                                             64m
pv-nfs-003   10Gi       RWO,RWX        Retain           Bound       default/nfs-pvc                           64m
pv-nfs-004   15Gi       RWO,RWX        Retain           Available                                             64m
pv-nfs-005   20Gi       RWO,RWX        Retain           Available                                             64m

[root@k8s-master storage]# kubectl get pods -o wide 
NAME                    READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
pvc-mysql               1/1     Running   0          31s   10.244.2.84   k8s-node2   <none>           <none>

[root@storage ~]# ls /data/volumes/v3/    #查看nfs服務器的pv3對應的共享目錄,里面生成了mysql的數據。
auto.cnf       ca-key.pem       ib_buffer_pool  ibtmp1        performance_schema  server-key.pem
binlog.000001  ca.pem           ibdata1         #innodb_temp  private_key.pem     sys
binlog.000002  client-cert.pem  ib_logfile0     mysql         public_key.pem      undo_001
binlog.index   client-key.pem   ib_logfile1     mysql.ibd     server-cert.pem     undo_002

5)測試驗證

#(1)進入到pod連接容器mysql並創建一個數據庫
[root@k8s-master ~]# kubectl exec -it pvc-mysql -- mysql -u root -pmysql
......
mysql> 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> create database volumes;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| volumes            |
+--------------------+
5 rows in set (0.00 sec)

mysql> exit
Bye


#(2)刪除pvc和pod和pv
[root@k8s-master storage]# kubectl delete -f vol-nfs-pvc.yaml    #刪除pvc
persistentvolumeclaim "nfs-pvc" deleted
pod "pvc-mysql" deleted
[root@k8s-master storage]# kubectl delete -f pv-nfs-demo.yaml    #刪除pv(如果有pv在被使用的狀態,需要先刪除pvc方可刪除pv)
persistentvolume "pv-nfs-001" deleted
persistentvolume "pv-nfs-002" deleted
persistentvolume "pv-nfs-003" deleted
persistentvolume "pv-nfs-004" deleted
persistentvolume "pv-nfs-005" deleted
[root@storage ~]# ls /data/volumes/v3/    #上面刪除了pv和pvc,可以看出存儲服務器上面的數據還是存在
auto.cnf       ca-key.pem       ib_buffer_pool  ibtmp1        performance_schema  server-key.pem  volumes
binlog.000001  ca.pem           ibdata1         #innodb_temp  private_key.pem     sys
binlog.000002  client-cert.pem  ib_logfile0     mysql         public_key.pem      undo_001
binlog.index   client-key.pem   ib_logfile1     mysql.ibd     server-cert.pem     undo_002

#(3)重新創建pv和pvc和pod驗證數據
[root@k8s-master storage]# kubectl apply -f pv-nfs-demo.yaml  
persistentvolume/pv-nfs-001 created
persistentvolume/pv-nfs-002 created
persistentvolume/pv-nfs-003 created
persistentvolume/pv-nfs-004 created
persistentvolume/pv-nfs-005 created
[root@k8s-master storage]# kubectl apply -f vol-nfs-pvc.yaml 
persistentvolumeclaim/nfs-pvc created
pod/pvc-mysql created
[root@k8s-master ~]# kubectl exec -it pvc-mysql -- mysql -u root -pmysql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| volumes            |
+--------------------+
5 rows in set (0.00 sec)


###
測試說明:
如果刪除pvc不刪除pv,重新創建同樣的pvc,那么pvc狀態會處於Pending狀態,因為pv的當前狀態為Released。這也和上面定義的回收策略息息相關。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM