本文轉(zhuǎn)載自 https://www.cnblogs.com/DaweiJ/articles/8618317.html
首先我們會學(xué)習(xí) Volume默色,以及 Kubernetes 如何通過 Volume 為集群中的容器提供存儲锌钮;
然后我們會實(shí)踐幾種常用的 Volume 類型并理解它們各自的應(yīng)用場景;
最后贫奠,我們會討論 Kubernetes 如何通過 Persistent Volume 和 Persistent Volume Claim 分離集群管理員與集群用戶的職責(zé),并實(shí)踐 Volume 的靜態(tài)供給逾冬。
Volume
本節(jié)我們討論 Kubernetes 的存儲模型 Volume包吝,學(xué)習(xí)如何將各種持久化存儲映射到容器。
我們經(jīng)常會說:容器和 Pod 是短暫的腹纳。
其含義是它們的生命周期可能很短痢掠,會被頻繁地銷毀和創(chuàng)建。容器銷毀時(shí)嘲恍,保存在容器內(nèi)部文件系統(tǒng)中的數(shù)據(jù)都會被清除足画。
為了持久化保存容器的數(shù)據(jù),可以使用 Kubernetes Volume佃牛。
Volume 的生命周期獨(dú)立于容器淹辞,Pod 中的容器可能被銷毀和重建,但 Volume 會被保留俘侠。
本質(zhì)上象缀,Kubernetes Volume 是一個(gè)目錄,這一點(diǎn)與 Docker Volume 類似爷速。當(dāng) Volume 被 mount 到 Pod央星,Pod 中的所有容器都可以訪問這個(gè) Volume。
Kubernetes Volume 也支持多種 backend 類型惫东,包括 emptyDir莉给、hostPath、GCE Persistent Disk廉沮、AWS Elastic Block Store禁谦、NFS、Ceph 等废封,完整列表可參考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes
Volume 提供了對各種 backend 的抽象州泊,容器在使用 Volume 讀寫數(shù)據(jù)的時(shí)候不需要關(guān)心數(shù)據(jù)到底是存放在本地節(jié)點(diǎn)的文件系統(tǒng)中呢還是云硬盤上。對它來說漂洋,所有類型的 Volume 都只是一個(gè)目錄遥皂。
我們將從最簡單的 emptyDir 開始學(xué)習(xí) Kubernetes Volume力喷。
emptyDir
emptyDir 是最基礎(chǔ)的 Volume 類型。正如其名字所示演训,一個(gè) emptyDir Volume 是 Host 上的一個(gè)空目錄弟孟。
emptyDir Volume 對于容器來說是持久的,對于 Pod 則不是样悟。當(dāng) Pod 從節(jié)點(diǎn)刪除時(shí)拂募,Volume 的內(nèi)容也會被刪除。但如果只是容器被銷毀而 Pod 還在窟她,則 Volume 不受影響陈症。
也就是說:emptyDir Volume 的生命周期與 Pod 一致。
Pod 中的所有容器都可以共享 Volume震糖,它們可以指定各自的 mount 路徑录肯。下面通過例子來實(shí)踐 emptyDir,配置文件如下:
apiVersion: v1
kind: Pod
metadata:
name: producer-consumer
spec:
containers:
- name: producer
image: 10.193.9.54:5000/library/busybox
volumeMounts:
- mountPath: /producer_dir
name: shared-volume
args:
- /bin/sh
- -c
- echo "hello world" > /producer_dir/hello ; sleep 30000
- name: consumer
image: 10.193.9.54:5000/library/busybox
volumeMounts:
- mountPath: /consumer_dir
name: shared-volume
args:
- /bin/sh
- -c
- cat /consumer_dir/hello ; sleep 30000
volumes:
- name: shared-volume
emptyDir: {}
這里我們模擬了一個(gè) producer-consumer 場景吊说。
Pod 有兩個(gè)容器 producer
和 consumer
论咏,它們共享一個(gè) Volume。
producer
負(fù)責(zé)往 Volume 中寫數(shù)據(jù)颁井,consumer
則是從 Volume 讀取數(shù)據(jù)厅贪。
① 文件最底部 volumes
定義了一個(gè) emptyDir
類型的 Volume shared-volume
。
② producer
容器將 shared-volume
mount 到 /producer_dir
目錄雅宾。
③ producer
通過 echo
將數(shù)據(jù)寫到文件 hello
里卦溢。
④ consumer
容器將 shared-volume
mount 到 /consumer_dir
目錄。
⑤ consumer
通過 cat
從文件 hello
讀數(shù)據(jù)秀又。
執(zhí)行命令創(chuàng)建pod并查看pod日志
[root@master clay]# kubectl get pod
NAME READY STATUS RESTARTS AGE
producer-consumer 2/2 Running 0 8s
[root@master clay]# kubectl logs producer-consumer consumer
hello world
kubectl logs
顯示容器 consumer
成功讀到了 producer
寫入的數(shù)據(jù)单寂,驗(yàn)證了兩個(gè)容器共享 emptyDir Volume。
因?yàn)?emptyDir 是 Docker Host 文件系統(tǒng)里的目錄吐辙,其效果相當(dāng)于執(zhí)行了 docker run -v /producer_dir
和 docker run -v /consumer_dir
宣决。通過 docker inspect
查看容器的詳細(xì)配置信息,我們發(fā)現(xiàn)兩個(gè)容器都 mount 了同一個(gè)目錄:
這里/var/lib/kubelet/pods/59a1fa91-8054-11e9-8f26-000c29114255/volumes/kubernetes.io~empty-dir/shared-volume
就是 emptyDir 在 Host 上的真正路徑昏苏。
emptyDir 是 Host 上創(chuàng)建的臨時(shí)目錄尊沸,其優(yōu)點(diǎn)是能夠方便地為 Pod 中的容器提供共享存儲,不需要額外的配置贤惯。
但它不具備持久性洼专,如果 Pod 不存在了,emptyDir 也就沒有了孵构。
根據(jù)這個(gè)特性屁商,emptyDir 特別適合 Pod 中的容器需要臨時(shí)共享存儲空間的場景,比如前面的生產(chǎn)者消費(fèi)者用例颈墅。
下一節(jié)我們學(xué)習(xí) hostPath Volume蜡镶。
hostPath Volume
hostPath Volume 的作用是將 Docker Host 文件系統(tǒng)中已經(jīng)存在的目錄 mount 給 Pod 的容器雾袱。
大部分應(yīng)用都不會使用 hostPath Volume,因?yàn)檫@實(shí)際上增加了 Pod 與節(jié)點(diǎn)的耦合官还,限制了 Pod 的使用芹橡。
不過那些需要訪問 Kubernetes 或 Docker 內(nèi)部數(shù)據(jù)(配置文件和二進(jìn)制庫)的應(yīng)用則需要使用 hostPath。
如果 Pod 被銷毀了望伦,hostPath 對應(yīng)的目錄也還會被保留林说,從這點(diǎn)看,hostPath 的持久性比 emptyDir 強(qiáng)屯伞。不過一旦 Host 崩潰腿箩,hostPath 也就沒法訪問了。
PersistentVolume & PersistentVolumeClaim
Volume 提供了非常好的數(shù)據(jù)持久化方案愕掏,不過在可管理性上還有不足度秘。
拿前面 AWS EBS 的例子來說顶伞,要使用 Volume饵撑,Pod 必須事先知道如下信息:
- 當(dāng)前 Volume 來自 AWS EBS。
- EBS Volume 已經(jīng)提前創(chuàng)建唆貌,并且知道確切的 volume-id滑潘。
Pod 通常是由應(yīng)用的開發(fā)人員維護(hù),而 Volume 則通常是由存儲系統(tǒng)的管理員維護(hù)锨咙。開發(fā)人員要獲得上面的信息:
- 要么詢問管理員语卤。
- 要么自己就是管理員。
這樣就帶來一個(gè)管理上的問題:應(yīng)用開發(fā)人員和系統(tǒng)管理員的職責(zé)耦合在一起了酪刀。如果系統(tǒng)規(guī)模較小或者對于開發(fā)環(huán)境這樣的情況還可以接受粹舵。但當(dāng)集群規(guī)模變大,特別是對于生成環(huán)境骂倘,考慮到效率和安全性眼滤,這就成了必須要解決的問題。
Kubernetes 給出的解決方案是 PersistentVolume 和 PersistentVolumeClaim历涝。
PersistentVolume (PV) 是外部存儲系統(tǒng)中的一塊存儲空間诅需,由管理員創(chuàng)建和維護(hù)。與 Volume 一樣荧库,PV 具有持久性堰塌,生命周期獨(dú)立于 Pod。
PersistentVolumeClaim (PVC) 是對 PV 的申請 (Claim)分衫。PVC 通常由普通用戶創(chuàng)建和維護(hù)场刑。需要為 Pod 分配存儲資源時(shí),用戶可以創(chuàng)建一個(gè) PVC蚪战,指明存儲資源的容量大小和訪問模式(比如只讀)等信息摇邦,Kubernetes 會查找并提供滿足條件的 PV恤煞。
有了 PersistentVolumeClaim,用戶只需要告訴 Kubernetes 需要什么樣的存儲資源施籍,而不必關(guān)心真正的空間從哪里分配居扒,如何訪問等底層細(xì)節(jié)信息。這些 Storage Provider 的底層信息交給管理員來處理丑慎,只有管理員才應(yīng)該關(guān)心創(chuàng)建 PersistentVolume 的細(xì)節(jié)信息喜喂。
Kubernetes 支持多種類型的 PersistentVolume,比如 AWS EBS竿裂、Ceph玉吁、NFS 等,完整列表請參考 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes
PV
下面創(chuàng)建一個(gè) PV mypv1
腻异,配置文件 my-pv1.yml
如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv1
labels:
type: local
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: manual
hostPath:
path: /data/pv1
① capacity
指定 PV 的容量為 1G进副。
② accessModes
指定訪問模式為 ReadWriteOnce
,支持的訪問模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到單個(gè)節(jié)點(diǎn)悔常。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多個(gè)節(jié)點(diǎn)影斑。
ReadWriteMany – PV 能以 read-write 模式 mount 到多個(gè)節(jié)點(diǎn)。
③ persistentVolumeReclaimPolicy
指定當(dāng) PV 的回收策略為 Recycle
机打,支持的策略有:
Retain – 需要管理員手工回收矫户。
Recycle – 清除 PV 中的數(shù)據(jù),效果相當(dāng)于執(zhí)行 rm -rf /thevolume/*
残邀。
Delete – 刪除 Storage Provider 上的對應(yīng)存儲資源皆辽,例如 AWS EBS、GCE PD芥挣、Azure Disk驱闷、OpenStack Cinder Volume 等。
④ storageClassName
指定 PV 的 class 為 manual
空免。相當(dāng)于為 PV 設(shè)置了一個(gè)分類空另,PVC 可以指定 class 申請相應(yīng) class 的 PV。
⑤ 指定 PV 在服務(wù)器上對應(yīng)的目錄鼓蜒。
創(chuàng)建 mypv1
:
STATUS
為 Available
痹换,表示 mypv1
就緒,可以被 PVC 申請都弹。
接下來創(chuàng)建 PVC mypvc1
娇豫,配置文件 my-pvc1.yml
如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: manual
PVC 就很簡單了,只需要指定 PV 的容量畅厢,訪問模式和 class冯痢。
創(chuàng)建 mypvc1
:
從 kubectl get pvc
和 kubectl get pv
的輸出可以看到 mypvc1
已經(jīng) Bound 到 mypv1
,申請成功。
接下來就可以在 Pod 中使用存儲了浦楣,Pod 配置文件 pod1.yml
如下:
apiVersion: v1
kind: Pod
metadata:
name: mypod1
spec:
containers:
- name: mypod1
image: 10.193.9.54:5000/library/busybox
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- mountPath: "/mydata"
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: mypvc1
與使用普通 Volume 的格式類似袖肥,在 volumes
中通過 persistentVolumeClaim
指定使用 mypvc1
申請的 Volume。
創(chuàng)建 mypod1
:
驗(yàn)證 PV 是否可用:
可見振劳,在 Pod 中創(chuàng)建的文件 /mydata/hello
確實(shí)已經(jīng)保存到了 服務(wù)器10.193.9.55
的 /data/pv1
中椎组。
如果不再需要使用 PV,可用刪除 PVC 回收 PV历恐,下節(jié)我們詳細(xì)討論寸癌。
回收PV
在使用本地存儲時(shí),需要刪除pod以及對應(yīng)的pvc弱贼,這時(shí)候pv狀態(tài)為failed
這個(gè)時(shí)候pv狀態(tài)為failed
蒸苇,無法提供服務(wù),需要刪除重建吮旅,但是數(shù)據(jù)還會保留
重新創(chuàng)建pv, pvc, pod會發(fā)現(xiàn)數(shù)據(jù)依然存在