(九)Kubernetes 存儲卷

Kubernetes存儲卷概述

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

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

Kubernetes支持的存儲卷類型

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

  • 非持久性存儲nginx

  • emptyDirgit

  • hostPathgithub

  • 網絡鏈接性存儲web

  • SAN:iscsiredis

  • NFS:nfs、cfssql

  • 分佈式存儲docker

  • 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

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。這也和上面定義的回收策略息息相關。
相關文章
相關標籤/搜索