Kubernetes存儲

本文轉(zhuǎn)載自 https://www.cnblogs.com/DaweiJ/articles/8618317.html

首先我們會學(xué)習(xí) Volume,以及 Kubernetes 如何通過 Volume 為集群中的容器提供存儲;

然后我們會實踐幾種常用的 Volume 類型并理解它們各自的應(yīng)用場景;

最后,我們會討論 Kubernetes 如何通過 Persistent Volume 和 Persistent Volume Claim 分離集群管理員與集群用戶的職責(zé),并實踐 Volume 的靜態(tài)供給。

Volume

本節(jié)我們討論 Kubernetes 的存儲模型 Volume,學(xué)習(xí)如何將各種持久化存儲映射到容器。

我們經(jīng)常會說:容器和 Pod 是短暫的。
其含義是它們的生命周期可能很短,會被頻繁地銷毀和創(chuàng)建。容器銷毀時,保存在容器內(nèi)部文件系統(tǒng)中的數(shù)據(jù)都會被清除。

為了持久化保存容器的數(shù)據(jù),可以使用 Kubernetes Volume。

Volume 的生命周期獨立于容器,Pod 中的容器可能被銷毀和重建,但 Volume 會被保留。

本質(zhì)上,Kubernetes Volume 是一個目錄,這一點與 Docker Volume 類似。當(dāng) Volume 被 mount 到 Pod,Pod 中的所有容器都可以訪問這個 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ù)的時候不需要關(guān)心數(shù)據(jù)到底是存放在本地節(jié)點的文件系統(tǒng)中呢還是云硬盤上。對它來說,所有類型的 Volume 都只是一個目錄。

我們將從最簡單的 emptyDir 開始學(xué)習(xí) Kubernetes Volume。

emptyDir

emptyDir 是最基礎(chǔ)的 Volume 類型。正如其名字所示,一個 emptyDir Volume 是 Host 上的一個空目錄。

emptyDir Volume 對于容器來說是持久的,對于 Pod 則不是。當(dāng) Pod 從節(jié)點刪除時,Volume 的內(nèi)容也會被刪除。但如果只是容器被銷毀而 Pod 還在,則 Volume 不受影響。

也就是說:emptyDir Volume 的生命周期與 Pod 一致。

Pod 中的所有容器都可以共享 Volume,它們可以指定各自的 mount 路徑。下面通過例子來實踐 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: {}
producer-consumer.png

這里我們模擬了一個 producer-consumer 場景。

Pod 有兩個容器 producerconsumer,它們共享一個 Volume。

producer 負(fù)責(zé)往 Volume 中寫數(shù)據(jù),consumer則是從 Volume 讀取數(shù)據(jù)。

① 文件最底部 volumes 定義了一個 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ù),驗證了兩個容器共享 emptyDir Volume。

因為 emptyDir 是 Docker Host 文件系統(tǒng)里的目錄,其效果相當(dāng)于執(zhí)行了 docker run -v /producer_dirdocker run -v /consumer_dir。通過 docker inspect 查看容器的詳細(xì)配置信息,我們發(fā)現(xiàn)兩個容器都 mount 了同一個目錄:

producer-mount.PNG
consumer-mount.PNG

這里/var/lib/kubelet/pods/59a1fa91-8054-11e9-8f26-000c29114255/volumes/kubernetes.io~empty-dir/shared-volume 就是 emptyDir 在 Host 上的真正路徑。

emptyDir 是 Host 上創(chuàng)建的臨時目錄,其優(yōu)點是能夠方便地為 Pod 中的容器提供共享存儲,不需要額外的配置。

但它不具備持久性,如果 Pod 不存在了,emptyDir 也就沒有了。

根據(jù)這個特性,emptyDir 特別適合 Pod 中的容器需要臨時共享存儲空間的場景,比如前面的生產(chǎn)者消費者用例。

下一節(jié)我們學(xué)習(xí) hostPath Volume。

hostPath Volume

hostPath Volume 的作用是將 Docker Host 文件系統(tǒng)中已經(jīng)存在的目錄 mount 給 Pod 的容器。

大部分應(yīng)用都不會使用 hostPath Volume,因為這實際上增加了 Pod 與節(jié)點的耦合,限制了 Pod 的使用。

不過那些需要訪問 Kubernetes 或 Docker 內(nèi)部數(shù)據(jù)(配置文件和二進制庫)的應(yīng)用則需要使用 hostPath。

如果 Pod 被銷毀了,hostPath 對應(yīng)的目錄也還會被保留,從這點看,hostPath 的持久性比 emptyDir 強。不過一旦 Host 崩潰,hostPath 也就沒法訪問了。

PersistentVolume & PersistentVolumeClaim

Volume 提供了非常好的數(shù)據(jù)持久化方案,不過在可管理性上還有不足。

拿前面 AWS EBS 的例子來說,要使用 Volume,Pod 必須事先知道如下信息:

  1. 當(dāng)前 Volume 來自 AWS EBS。
  2. EBS Volume 已經(jīng)提前創(chuàng)建,并且知道確切的 volume-id。

Pod 通常是由應(yīng)用的開發(fā)人員維護,而 Volume 則通常是由存儲系統(tǒng)的管理員維護。開發(fā)人員要獲得上面的信息:

  1. 要么詢問管理員。
  2. 要么自己就是管理員。

這樣就帶來一個管理上的問題:應(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)建和維護。與 Volume 一樣,PV 具有持久性,生命周期獨立于 Pod。

PersistentVolumeClaim (PVC) 是對 PV 的申請 (Claim)。PVC 通常由普通用戶創(chuàng)建和維護。需要為 Pod 分配存儲資源時,用戶可以創(chuàng)建一個 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)建一個 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
mypv1.PNG

capacity 指定 PV 的容量為 1G。

accessModes 指定訪問模式為 ReadWriteOnce,支持的訪問模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到單個節(jié)點。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多個節(jié)點。
ReadWriteMany – PV 能以 read-write 模式 mount 到多個節(jié)點。

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è)置了一個分類,PVC 可以指定 class 申請相應(yīng) class 的 PV。

⑤ 指定 PV 在服務(wù)器上對應(yīng)的目錄。

創(chuàng)建 mypv1

create-mypv1.PNG

STATUSAvailable,表示 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

create-mypvc1.PNG

kubectl get pvckubectl 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

create-mypod1.PNG

驗證 PV 是否可用:


validate-mypv1.PNG

可見,在 Pod 中創(chuàng)建的文件 /mydata/hello 確實已經(jīng)保存到了 服務(wù)器10.193.9.55/data/pv1 中。

如果不再需要使用 PV,可用刪除 PVC 回收 PV,下節(jié)我們詳細(xì)討論。

回收PV

在使用本地存儲時,需要刪除pod以及對應(yīng)的pvc,這時候pv狀態(tài)為failed


delete pod and pvc.PNG

這個時候pv狀態(tài)為failed,無法提供服務(wù),需要刪除重建,但是數(shù)據(jù)還會保留

delete pv.PNG

重新創(chuàng)建pv, pvc, pod會發(fā)現(xiàn)數(shù)據(jù)依然存在

recreate pv.PNG
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 在K8S運行的服務(wù),從簡單到復(fù)雜可以分成三類:無狀態(tài)服務(wù)、普通有狀態(tài)服務(wù)和有狀態(tài)集群服務(wù)。下面分別來看K8S...
    梅_梅閱讀 1,131評論 0 2
  • 一、Docker中的Volume和Kubernetes中的Volume Docker中的Volume 在Docke...
    奧個特曼閱讀 976評論 0 0
  • 目錄 存儲卷是屬于Pod,不屬于容器。但是可以在容器中去掛載存儲卷來使用。 K8S上可用的存儲卷類型: empty...
    CaiGuangyin閱讀 2,885評論 2 4
  • D65,2018年5月8日 星期二 晴 中午放學(xué)后還是我去接的兒子,見到兒子后的第一句話還是昨天的話題...
    a行者無疆123閱讀 304評論 0 1
  • 也許,只有醫(yī)院才能讓人不在胡思亂想。一大早掛號處已熙熙攘攘。走在路上誰也不會覺得身邊人需要看醫(yī)生,而走進醫(yī)院你會發(fā)...
    小胖蟲子閱讀 167評論 0 0

友情鏈接更多精彩內(nèi)容