卷
容器中的檔案在磁碟上是臨時存放的,這給在容器中執行較重要的應用帶來一些問題。 當容器崩潰或停止時會出現一個問題。此時容器狀態未儲存, 因此在容器生命週期內建立或修改的所有檔案都將丟失。 在崩潰期間,kubelet 會以乾淨的狀態重新啟動容器。 當多個容器在一個 Pod 中執行並且需要共享檔案時,會出現另一個問題。 跨所有容器設定和訪問共享檔案系統具有一定的挑戰性。
Kubernetes 卷(Volume) 這一抽象概念能夠解決這兩個問題。
emptyDir
對於定義了 emptyDir
卷的 Pod,在 Pod 被指派到某節點時此卷會被建立。 就像其名稱所表示的那樣,emptyDir
卷最初是空的。儘管 Pod 中的容器掛載 emptyDir
卷的路徑可能相同也可能不同,但這些容器都可以讀寫 emptyDir
卷中相同的檔案。 當 Pod 因為某些原因被從節點上刪除時,emptyDir
卷中的資料也會被永久刪除。
emptyDir 配置
[root@master NFS-storageclass]# cat po-2.yaml apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: registry.k8s.io/test-webserver name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: sizeLimit: 500Mi [root@master NFS-storageclass]# kubectl apply -f po-2.yaml pod/test-pd created [root@master NFS-storageclass]# kubectl get po test-pd NAME READY STATUS RESTARTS AGE test-pd 1/1 Running 0 2m2s
hostPath
hostPath
卷能將主機節點檔案系統上的檔案或目錄掛載到你的 Pod 中。 雖然這不是大多數 Pod 需要的,但是它為一些應用提供了強大的逃生艙。
hostPath
的一些用法有:
- 執行一個需要訪問節點級系統元件的容器 (例如一個將系統日誌傳輸到集中位置的容器,使用只讀掛載
/var/log
來訪問這些日誌) - 讓儲存在主機系統上的配置檔案可以被靜態 Pod 以只讀方式訪問;與普通 Pod 不同,靜態 Pod 無法訪問 ConfigMap
[root@master svc]# cat ../host/po.yaml apiVersion: v1 kind: Pod metadata: name: host spec: volumes: - name: test-host hostPath: path: /data containers: - name: web image: nginx imagePullPolicy: IfNotPresent volumeMounts: - name: test-host mountPath: /test - name: cx image: tomcat:10 imagePullPolicy: IfNotPresent volumeMounts: - name: test-host mountPath: /chenxi [root@master host]# kubectl exec -it host -c cx -- /bin/sh # ls / bin __cacert_entrypoint.sh dev home lib64 mnt proc run srv tmp var boot chenxi etc lib media opt root sbin sys usr # cd chenxi /bin/sh: 2: cd: can't cd to chenxi # ^[[A^[[B /bin/sh: 3: : not found # /bin/bash root@host:/usr/local/tomcat# cd /chenxi/ root@host:/chenxi# echo "chenxi" > tomcat.txt root@host:/chenxi# ls tomcat.txt [root@master ~]# kubectl exec -it host -c web -- /bin/bash root@host:/# ls /test/ tomcat.txt root@host:/# echo "nginx" >/test/nginx.txt [root@master svc]# kubectl get po host -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES host 2/2 Running 0 6m52s 172.16.84.140 node-1 <none> <none> [root@node-1 ~]# ls /data/ nginx.txt tomcat.txt
nfs
nfs
卷能將 NFS (網路檔案系統) 掛載到你的 Pod 中。 不像 emptyDir
那樣會在刪除 Pod 的同時也會被刪除,nfs
卷的內容在刪除 Pod 時會被儲存,卷只是被解除安裝。 這意味著 nfs
卷可以被預先填充資料,並且這些資料可以在 Pod 之間共享。
[root@master ~]# cat /etc/exports /data/kubernetes/pv1 192.168.10.0/24(rw,sync,no_root_squash,no_all_squash) /data/kubernetes/pv2 192.168.10.0/24(rw,sync,no_root_squash,no_all_squash) /data/kubernetes/pv3 192.168.10.0/24(rw,sync,no_root_squash,no_all_squash) /data/kubernetes/pv4 192.168.10.0/24(rw,sync,no_root_squash,no_all_squash) /data/kubernetes/pv5 192.168.10.0/24(rw,sync,no_root_squash,no_all_squash) /data/kubernetes/pv6 192.168.10.0/24(rw,sync,no_root_squash,no_all_squash) [root@master NFS-storageclass]# cat po.yaml apiVersion: v1 kind: Pod metadata: name: nfs-1 spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - name: web containerPort: 80 volumeMounts: - name: nfs-volumes mountPath: /nginx volumes: - name: nfs-volumes nfs: server: 192.168.10.29 path: /data/kubernetes/pv2 [root@master NFS-storageclass]# kubectl apply -f po.yaml pod/nfs-1 created [root@master NFS-storageclass]# kubectl describe pod nfs-1 Name: nfs-1 Namespace: default Priority: 0 Service Account: default Node: node-1/192.168.10.30 Start Time: Fri, 18 Oct 2024 10:02:04 +0800 Labels: <none> Annotations: cni.projectcalico.org/containerID: ce2101862c7aaafc907faf6652859a564c3d63770892e2f91acf357fb245ef00 cni.projectcalico.org/podIP: 172.16.84.139/32 cni.projectcalico.org/podIPs: 172.16.84.139/32 Status: Running IP: 172.16.84.139 IPs: IP: 172.16.84.139 Containers: nginx: Container ID: containerd://036aed08ecdce0b3aee06a5369673ae54123362fa4c43ab00b52ef0be7efb009 Image: nginx Image ID: docker.io/library/nginx@sha256:d2eb56950b84efe34f966a2b92efb1a1a2ea53e7e93b94cdf45a27cf3cd47fc0 Port: 80/TCP Host Port: 0/TCP State: Running Started: Fri, 18 Oct 2024 10:02:05 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /nginx from nfs-volumes (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-b8h9m (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: nfs-volumes: Type: NFS (an NFS mount that lasts the lifetime of a pod) Server: 192.168.10.29 Path: /data/kubernetes/pv2 ReadOnly: false kube-api-access-b8h9m: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 27s default-scheduler Successfully assigned default/nfs-1 to node-1 Normal Pulled 27s kubelet Container image "nginx" already present on machine Normal Created 26s kubelet Created container nginx Normal Started 26s kubelet Started container nginx [root@master NFS-storageclass]# kubectl exec -it nfs-1 -- /bin/bash root@nfs-1:/# ls nginx/ root@nfs-1:/# cd /nginx/ root@nfs-1:/nginx# echo "nginx" > nginx.txt root@nfs-1:/nginx# ls nginx.txt [root@master ~]# ls /data/kubernetes/pv2/ nginx.txt [root@master ~]# cat /data/kubernetes/pv2/ cat: /data/kubernetes/pv2/: 是一個目錄 [root@master ~]# cat /data/kubernetes/pv2/nginx.txt nginx
Persistent Volumes
本文描述 Kubernetes 中的持久卷(Persistent Volumes)
PersistentVolume 子系統為使用者和管理員提供了一組 API, 將儲存如何製備的細節從其如何被使用中抽象出來。 為了實現這點,我們引入了兩個新的 API 資源:PersistentVolume 和 PersistentVolumeClaim。
持久卷(PersistentVolume,PV) 是叢集中的一塊儲存,可以由管理員事先製備, 或者使用儲存類(Storage Class)來動態製備。 持久卷是叢集資源,就像節點也是叢集資源一樣。PV 持久卷和普通的 Volume 一樣, 也是使用卷外掛來實現的,只是它們擁有獨立於任何使用 PV 的 Pod 的生命週期。 此 API 物件中記述了儲存的實現細節,無論其背後是 NFS、iSCSI 還是特定於雲平臺的儲存系統。
持久卷申領(PersistentVolumeClaim,PVC) 表達的是使用者對儲存的請求。概念上與 Pod 類似。 Pod 會耗用節點資源,而 PVC 申領會耗用 PV 資源。Pod 可以請求特定數量的資源(CPU 和記憶體)。同樣 PVC 申領也可以請求特定的大小和訪問模式 (例如,可以掛載為 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 或 ReadWriteOncePod, 請參閱訪問模式)。
儘管 PersistentVolumeClaim 允許使用者消耗抽象的儲存資源, 常見的情況是針對不同的問題使用者需要的是具有不同屬性(如,效能)的 PersistentVolume 卷。 叢集管理員需要能夠提供不同性質的 PersistentVolume, 並且這些 PV 卷之間的差別不僅限於卷大小和訪問模式,同時又不能將卷是如何實現的這些細節暴露給使用者。 為了滿足這類需求,就有了儲存類(StorageClass) 資源。
卷和申領的生命週期
PV 卷是叢集中的資源。PVC 申領是對這些資源的請求,也被用來執行對資源的申領檢查。 PV 卷和 PVC 申領之間的互動遵循如下生命週期:
製備
PV 卷的製備有兩種方式:靜態製備或動態製備。
靜態製備
叢集管理員建立若干 PV 卷。這些卷物件帶有真實儲存的細節資訊, 並且對叢集使用者可用(可見)。PV 卷物件存在於 Kubernetes API 中,可供使用者消費(使用)。
動態製備
如果管理員所建立的所有靜態 PV 卷都無法與使用者的 PersistentVolumeClaim 匹配, 叢集可以嘗試為該 PVC 申領動態製備一個儲存卷。 這一製備操作是基於 StorageClass 來實現的:PVC 申領必須請求某個 儲存類, 同時叢集管理員必須已經建立並配置了該類,這樣動態製備卷的動作才會發生。 如果 PVC 申領指定儲存類為 ""
,則相當於為自身禁止使用動態製備的卷。
為了基於儲存類完成動態的儲存製備,叢集管理員需要在 API 伺服器上啟用 DefaultStorageClass
准入控制器。 舉例而言,可以透過保證 DefaultStorageClass
出現在 API 伺服器元件的 --enable-admission-plugins
標誌值中實現這點;該標誌的值可以是逗號分隔的有序列表。 關於 API 伺服器標誌的更多資訊,可以參考 kube-apiserver 文件。
繫結
使用者建立一個帶有特定儲存容量和特定訪問模式需求的 PersistentVolumeClaim 物件; 在動態製備場景下,這個 PVC 物件可能已經建立完畢。 控制平面中的控制迴路監測新的 PVC 物件,尋找與之匹配的 PV 卷(如果可能的話), 並將二者繫結到一起。 如果為了新的 PVC 申領動態製備了 PV 卷,則控制迴路總是將該 PV 卷繫結到這一 PVC 申領。 否則,使用者總是能夠獲得他們所請求的資源,只是所獲得的 PV 卷可能會超出所請求的配置。 一旦繫結關係建立,則 PersistentVolumeClaim 繫結就是排他性的, 無論該 PVC 申領是如何與 PV 卷建立的繫結關係。 PVC 申領與 PV 卷之間的繫結是一種一對一的對映,實現上使用 ClaimRef 來記述 PV 卷與 PVC 申領間的雙向繫結關係。
如果找不到匹配的 PV 卷,PVC 申領會無限期地處於未繫結狀態。 當與之匹配的 PV 卷可用時,PVC 申領會被繫結。 例如,即使某叢集上製備了很多 50 Gi 大小的 PV 卷,也無法與請求 100 Gi 大小的儲存的 PVC 匹配。當新的 100 Gi PV 卷被加入到叢集時, 該 PVC 才有可能被繫結。
使用
Pod 將 PVC 申領當做儲存捲來使用。叢集會檢視 PVC 申領,找到所繫結的卷, 併為 Pod 掛載該卷。對於支援多種訪問模式的卷, 使用者要在 Pod 中以卷的形式使用申領時指定期望的訪問模式。
一旦使用者有了申領物件並且該申領已經被繫結, 則所繫結的 PV 卷在使用者仍然需要它期間一直屬於該使用者。 使用者透過在 Pod 的 volumes
塊中包含 persistentVolumeClaim
節區來排程 Pod,訪問所申領的 PV 卷。 相關細節可參閱使用申領作為卷。
保護使用中的儲存物件
保護使用中的儲存物件(Storage Object in Use Protection) 這一功能特性的目的是確保仍被 Pod 使用的 PersistentVolumeClaim(PVC) 物件及其所繫結的 PersistentVolume(PV)物件在系統中不會被刪除,因為這樣做可能會引起資料丟失。
PV
[root@master pv]# cat pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: nfs-cx spec: capacity: storage: 1Gi accessModes: ["ReadWriteOnce"] nfs: server: 192.168.10.29 path: /data/kubernetes/pv3 --- apiVersion: v1 kind: PersistentVolume metadata: name: nfs-cx-2 spec: capacity: storage: 2Gi accessModes: ["ReadWriteMany"] nfs: server: 192.168.10.29 path: /data/kubernetes/pv4 [root@master pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE nfs-cx 1Gi RWO Retain Available 8m20s nfs-cx-2 2Gi RWX Retain Available 8m20s [root@master pv]# cat pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cx-pvc spec: accessModes: ["ReadWriteMany"] resources: requests: storage: 2Gi [root@master pv]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE cx-pvc Bound nfs-cx-2 2Gi RWX 9m43s [root@master pv]# cat po.yaml apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: myfrontend image: nginx volumeMounts: - mountPath: "/var/www/html" name: mypd volumes: - name: mypd persistentVolumeClaim: claimName: cx-pvc [root@master pv]# kubectl describe po mypod Name: mypod Namespace: default Priority: 0 Service Account: default Node: node-2/192.168.10.31 Start Time: Sat, 19 Oct 2024 09:28:22 +0800 Labels: <none> Annotations: cni.projectcalico.org/containerID: 59ba3be077ca2c966a44cbd16404fcf88075394125a16d4e4c32cba4a7a281e3 cni.projectcalico.org/podIP: 172.16.247.40/32 cni.projectcalico.org/podIPs: 172.16.247.40/32 Status: Running IP: 172.16.247.40 IPs: IP: 172.16.247.40 Containers: myfrontend: Container ID: containerd://3817af539efa8fd11e1f082cfb57d315ecfb48db14ed951c9e124c0901ba58df Image: nginx Image ID: docker.io/library/nginx@sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb Port: <none> Host Port: <none> State: Running Started: Sat, 19 Oct 2024 09:28:53 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vv7kt (ro) /var/www/html from mypd (rw) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: mypd: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: cx-pvc ReadOnly: false kube-api-access-vv7kt: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 5m24s default-scheduler Successfully assigned default/mypod to node-2 Normal Pulling 5m22s kubelet Pulling image "nginx" Normal Pulled 4m53s kubelet Successfully pulled image "nginx" in 28.407s (28.408s including waiting) Normal Created 4m53s kubelet Created container myfrontend Normal Started 4m53s kubelet Started container myfrontend
儲存類: https://www.cnblogs.com/rdchenxi/p/17113820.html