kubernetes Value:將磁碟掛載到容器,PV,PVC
6.1.介紹卷
6.1.1.卷的型別
emptyDir-用於儲存臨時資料的簡單空目錄
hostPath-用於將目錄從工作節點的檔案系統掛載到pod
nfs-掛載到pod中的NFS共享卷。
還有其他的如gitRepo、gcepersistenDisk
6.2.通過卷在容器間共享資料
6.2.1.使用emptyDir卷
卷的生命週期與pod的生命週期項關聯,所以當刪除pod時,卷的內容就會丟失。
使用empty示例程式碼如下:
apiVersion: v1 kind: Pod metadata: name: fortune spec: containers: - image: luksa/fortune name: html-gener volumeMounts: - name: html mountPath: /usr/share/nginx readOnly: true - image: nginx/aplin name: web-service volumeMounts: - name: html mountPath: /usr/share readOnly: true volumes: - name: html //一個名為html的單獨emptyDir卷,掛載在上面的兩個容器中 emptyDir: {}
6.3.訪問工作節點檔案系統上的檔案
6.3.1.hostPath卷
hostPath是永續性儲存,emptyDir卷的內容隨著pod的刪除而刪除。
使用hostPath會發現當刪除一個pod,並且下一個pod使用了指向主機上相同路徑的hostPath卷,則新pod將會發現上一個pod留下的資料,但前提是必須將其排程到與第一個pod相同的節點上。
所以當你使用hostPath時請務必考慮清楚,當重新起一個pod時候,必須要保證pod的節點與之前相同。
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: # directory location on host path: /data # this field is optional type: Directory
6.4.使用持久化儲存
怎樣保證pod重新啟動後排程到任意一個節點都有相同的資料可用,這就需要做到持久化儲存。
因此必須要將資料儲存在某種型別的網路儲存(NAS)中。
各種支援的方式不盡相同,例如 GlusterFS 需要建立 Endpoint,Ceph/NFS 之流就沒這麼麻煩了。
6.4.1.使用NFS儲存
以NFS為例,yml程式碼如下:
6.4.2.configmap和secert
secret和configmap可以理解為特殊的儲存卷,但是它們不是給Pod提供儲存功能的,而是提供了從叢集外部向叢集內部的應用注入配置資訊的功能。ConfigMap扮演了K8S叢集中配置中心的角色。ConfigMap定義了Pod的配置資訊,可以以儲存卷的形式掛載至Pod中的應用程式配置檔案目錄,從configmap中讀取配置資訊;也可以基於環境變數的形式,從ConfigMap中獲取變數注入到Pod容器中使用。但是ConfigMap是明文儲存的,如果用來儲存資料庫賬號密碼這樣敏感資訊,就非常不安全。一般這樣的敏感資訊配置是通過secret
secret
的功能和ConfigMap一樣,不過secret是通過Base64的編碼機制儲存配置資訊。
從ConfigMap中獲取配置資訊的方法有兩種:
- 一種是利用環境變數將配置資訊注入Pod容器中的方式,這種方式只在Pod建立的時候生效,這就意味著在ConfigMap中的修改配置資訊後,更新的配置不能被已經建立Pod容器所應用。
- 另一種是將ConfigMap做為儲存卷掛載至Pod容器內,這樣在修改ConfigMap配置資訊後,Pod容器中的配置也會隨之更新,不過這個過程會有稍微的延遲。
ConfigMap當作儲存卷掛載至Pod中的用法:
apiVersion: v1 kind: Pod metadata: name: pod-configmap-vol-2 labels: name: pod-configmap-vol-2 spec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: my-cm-www mountPath: /etc/nginx/conf.d/ # 將名為my-www的configmap掛載至Pod容器的這個目錄下。 volumes: - name: my-cm-www configMap: # 儲存卷型別選configMap
secert的方法類似,只是secert對資料進行了加密
6.5.從底層儲存技術解耦pod
6.5.1.介紹持久卷和持久卷宣告
當叢集使用者需要在其pod中使用持久化儲存時,他們首先建立持久化宣告(PVC)清單,指定所需要的最低容量要求,和訪問模式,然後使用者將持久卷宣告清單提交給kubernetes API伺服器,kubernetes將找到可以匹配的持久卷並將其繫結到持久卷宣告。
持久卷宣告可以當做pod中的一個捲來使用,其他使用者不能使用相同的持久卷,除非先通過刪除持久卷宣告繫結來釋放。
6.5.2.建立持久卷
下面建立一個 PV mypv1
,配置檔案pv1.yml
如下:
apiVersion: v1 kind: PersistentVolume metadata: name: yh_pv1 spec: capacity: storage: 1Gi //capacity 指定 PV 的容量為 1G accessModes: //accessModes 指定訪問模式為 ReadWriteOnce - ReadWriteOnce persistentVolumeReclaimpolicy: Recycle //persistentVolumeReclaimPolicy 指定當 PV 的回收策略為 Recycle storageClassName: nfs //storageClassName 指定 PV 的 class 為 nfs。相當於為 PV 設定了一個分類,PVC 可以指定 class 申請相應 class 的 PV。 nfs: path: /nfs/data //指定 PV 在 NFS 伺服器上對應的目錄 server: 10.10.0.11
1.accessModes
指定訪問模式為 ReadWriteOnce
,支援的訪問模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到單個節點。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多個節點。
ReadWriteMany – PV 能以 read-write 模式 mount 到多個節點。
2.persistentVolumeReclaimPolicy
指定當 PV 的回收策略為 Recycle
,支援的策略有:
Retain – 需要管理員手工回收。
Recycle – 清除 PV 中的資料,效果相當於執行 rm -rf /thevolume/*
。
Delete – 刪除 Storage Provider 上的對應儲存資源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
建立 pv
:
# kubectl apply -f pv1.yml persistentvolume/yh-pv1 created
檢視pv:
# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE yh-pv1 1Gi RWO Recycle Available nfs 17m
STATUS
為 Available
,表示 yh-pv1就緒,可以被 PVC 申請。
6.5.3.通過持久卷宣告來獲取持久卷
接下來建立 PVC mypvc1
,配置檔案 pvc1.yml
如下:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: yh-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs
PVC 就很簡單了,只需要指定 PV 的容量,訪問模式和 class。
執行命令建立 mypvc1
:
# kubectl apply -f pvc1.yml persistentvolumeclaim/yh-pvc created
檢視pvc
# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE yh-pvc Bound yh-pv1 1Gi RWO nfs 64s
從 kubectl get pvc
和 kubectl get pv
的輸出可以看到 yh-pvc1
已經 Bound 到yh- pv1
,申請成功。
# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE yh-pv1 1Gi RWO Recycle Bound default/yh-pvc nfs 47m
6.5.4.在pod中使用持久卷宣告
上面已經建立好了pv和pvc,pod中直接使用這個pvc即可
與使用普通 Volume 的格式類似,在 volumes
中通過 persistentVolumeClaim
指定使用 mypvc1
申請的 Volume。
通過命令建立mypod1
:
可見,在 Pod 中建立的檔案 /mydata/hello
確實已經儲存到了 NFS 伺服器目錄 /nfsdata
中。
如果不再需要使用 PV,可用刪除 PVC 回收 PV。
6.5.5.回收持久卷
當 PV 不再需要時,可通過刪除 PVC 回收。
未刪除pvc之前 pv的狀態是Bound
刪除pvc之後pv的狀態變為Available,,此時解除繫結後則可以被新的 PVC 申請。
/nfsdata檔案中的檔案被刪除了
因為 PV 的回收策略設定為 Recycle
,所以資料會被清除,但這可能不是我們想要的結果。如果我們希望保留資料,可以將策略設定為 Retain
。
通過 kubectl apply
更新 PV:
回收策略已經變為 Retain
,通過下面步驟驗證其效果:
① 重新建立 mypvc1
。
② 在 mypv1
中建立檔案 hello
。
③ mypv1
狀態變為 Released
。
④ PV 中的資料被完整保留。
雖然 mypv1
中的資料得到了保留,但其 PV 狀態會一直處於 Released
,不能被其他 PVC 申請。為了重新使用儲存資源,可以刪除並重新建立 mypv1
。刪除操作只是刪除了 PV 物件,儲存空間中的資料並不會被刪除。
新建的 mypv1
狀態為 Available
,已經可以被 PVC 申請。
PV 還支援 Delete
的回收策略,會刪除 PV 在 Storage Provider 上對應儲存空間。NFS 的 PV 不支援 Delete
,支援 Delete
的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
6.6.持久卷的動態配置
6.6.1.通過StorageClass資源定義可用儲存型別
前面的例子中,我們提前建立了 PV,然後通過 PVC 申請 PV 並在 Pod 中使用,這種方式叫做靜態供給(Static Provision)。
與之對應的是動態供給(Dynamical Provision),即如果沒有滿足 PVC 條件的 PV,會動態建立 PV。相比靜態供給,動態供給有明顯的優勢:不需要提前建立 PV,減少了管理員的工作量,效率高。
動態供給是通過 StorageClass 實現的,StorageClass 定義瞭如何建立 PV,下面是兩個例子。
StorageClass standard
:
StorageClass slow
:
這兩個 StorageClass 都會動態建立 AWS EBS,不同在於 standard
建立的是 gp2
型別的 EBS,而 slow
建立的是 io1
型別的 EBS。不同型別的 EBS 支援的引數可參考 AWS 官方文件。
StorageClass 支援 Delete
和 Retain
兩種 reclaimPolicy
,預設是 Delete
。
與之前一樣,PVC 在申請 PV 時,只需要指定 StorageClass 和容量以及訪問模式,比如:
除了 AWS EBS,Kubernetes 支援其他多種動態供給 PV 的 Provisioner,完整列表請參考 https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner
6.6.2.PV&&PVC在應用在mysql的持久化儲存
下面演示如何為 MySQL 資料庫提供持久化儲存,步驟為:
-
建立 PV 和 PVC。
-
部署 MySQL。
-
向 MySQL 新增資料。
-
模擬節點宕機故障,Kubernetes 將 MySQL 自動遷移到其他節點。
-
驗證資料一致性。
首先建立 PV 和 PVC,配置如下:
mysql-pv.yml
mysql-pvc.yml
建立 mysql-pv
和 mysql-pvc
:
接下來部署 MySQL,配置檔案如下:
PVC mysql-pvc
Bound 的 PV mysql-pv
將被 mount 到 MySQL 的資料目錄 var/lib/mysql
。
MySQL 被部署到 k8s-node2
,下面通過客戶端訪問 Service mysql
:
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
更新資料庫:
① 切換到資料庫 mysql。
② 建立資料庫表 my_id。
③ 插入一條資料。
④ 確認資料已經寫入。
關閉 k8s-node2
,模擬節點宕機故障。
驗證資料的一致性:
由於node2節點已經宕機,node1節點接管了這個任務。
通過kubectl run 命令 進入node1的這個pod裡,檢視資料是否依舊存在
MySQL 服務恢復,資料也完好無