Kubernetes In Action 持久化存儲 & Volume

Background

K8s的卷可以理解爲是pod的一個組成部分,不是獨立的的資源,pod的所有容器都可以使用卷,但是必須先掛載在每個需要訪問它的容器中。

換句話說,不同的container的某個路徑只要掛載到同一個捲上,這幾個container就可以實現對磁盤空間的共享

可用的Volume的類型

1.本地存儲類型:emptydir/hostpath

兩者區別在於後者的數據其實是會存儲在宿主機的一個特定路徑上,pod刪除之後,目錄仍然會存在,數據也不會丟失。

2.網絡存儲: 實現是給K8s本身解耦,通過抽象接口把不同存儲的driver實現從K8s代碼倉庫中剝離
3.Projected Volumes:把配置信息如secret/configmap用卷的形式掛載在容器中,讓容器中的程序可以通過POSIX接口來訪問配置數據
4.PV 和PVC

  • emptyDir
    用於存儲臨時數據的簡單空目錄,主要用於同一個Pod的運行容器之間共享文件,也可以用於單個容器用於把數據臨時寫入磁盤中。
    下面的配置文件,創建了兩個都掛載在名爲html的Volume的pod
apiVersion: v1
kind: Pod
metadata:
  name: fortune
spec:
  containers:
  - image: luksa/fortune
    name: html-generator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs
  - image: nginx:alpine
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: html
    emptyDir: {}

當然你可以指定EMPTYDIR的介質,用磁盤還是內存都可

volumes:
- name: html
  emptyDir:
  	medium: Memory

訪問工作節點文件系統上的文件

  • hostPath

把目錄從工作節點的文件系統掛載到pod中

屬於持久性存儲卷,pod刪除後卷不會被刪除

Pod通常使用hostPath來訪問節點上的日誌文件,kubeconfig或者CA證書

但是如果Pod被調度到別的節點上後,就不能訪問原來掛載在工作節點上的數據了

持久化存儲

首先爲什麼要引入PV這個概念?

1.要保證Pod調度到別的節點上後,仍然能訪問之前節點的數據,也就是說數據要可以提供給集羣中任何節點訪問.例如宿主機宕機,需要把Pod遷移到別的節點上,Statefulset管理的pod,實現了帶卷遷移的語義,這時候通過Pod Volumes是做不到的
2.pod的重建銷燬,例如用deployment管理的pod,在做鏡像升級的時候,會產生新的pod並且刪除舊的pod,那麼新舊pod之間如何複用數據?
3.同一個pod內的多個容器如果要共享數據,可以用Pod Volumes來解決,當多個pod要共享數據的時候,Pod Volumes就很難表達這種語義
4.對卷做功能擴展

換句話說,Volumes難以實現複用共享功能

因此我們引入Persistent Volumes概念,可以把存儲和計算分離開來,通過不同的組件來管理存儲資源和計算資源,然後解耦pod和Volume之間生命週期的關聯,這樣把pod刪除之後,使用的PV不會被銷燬,還可以被新的pod複用。

因爲我這裏用的是minikube,不支持GCE硬盤來做持久化存儲,因此這裏用hostPath做持久化存儲,把容器內/tmp/mongodb的數據持久化存儲在宿主節點的/data/db上

apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  volumes:
  - name: mongodb-data
    hostPath:
      path: /tmp/mongodb
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP

除了使用硬盤存儲,hostPath之外,還可以使用nfs

持久卷聲明PVC

如果要創建支持NFS協議的卷,開發人員必須知道NFS節點所在的實際服務器,這違背了K8s的基本理念,基本理念旨在嚮應用程序以及開發人員隱藏真實的基礎設施

爲什麼要引入PVC?

  • 職責分離,PVC中只用聲明自己需要的存儲size,access mode(節點獨佔還是共享,只讀還是讀寫訪問),開發者不需要關心存儲需求,PV和對應後端存儲信息交給cluster admin統一運維和管控
  • PVC簡化了User對存儲的需求,PV纔是存儲的實際信息的承載體,通過kube-controller-manager的PersistentVolumeController把PVC與合適的PV綁定在一起,從而滿足User對存儲的實際需求。

因此引入了PVC和PV這個概念

  • 集羣管理員設置底層存儲
  • 通過K8s API傳遞PV聲明創建持久卷
  • 用戶創建持久卷聲明
  • K8s找到一個足夠容量的PV並且將其置於訪問模式,並且將PVC綁定到PV
  • 用戶創建一個pod並通過卷配置引用PVC

首先創建一個PV

persistentVolumeReclaimPolicy:也有三種策略,這個策略是當與之關聯的PVC被刪除以後,這個PV中的數據如何被處理

Retain 當刪除與之綁定的PVC時候,這個PV被標記爲released(PVC與PV解綁但還沒有執行回收策略)且之前的數據依然保存在該PV上,但是該PV不可用,需要手動來處理這些數據並刪除該PV。

Delete 當刪除與之綁定的PVC時候,刪除底層存儲

accessModes:支持三種類型

ReadWriteMany 多路讀寫,卷能被集羣多個節點掛載並讀寫

ReadWriteOnce 單路讀寫,卷只能被單一集羣節點掛載讀寫

ReadOnlyMany 多路只讀,卷能被多個集羣節點掛載且只能讀
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongodb-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /tmp/mongodb

然後通過創建持久卷聲明來獲取持久卷

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc
spec:
  resources:
    requests:
      storage: 1Gi
  accessModes:
  - ReadWriteOnce
  storageClassName: ""

注意PV不屬於任何命名空間,屬於控制平面層級的資源,而PVC和pod一樣,都要屬於某個命名空間

然後在Pod中使用持久卷聲明

全稱是Persistent Volume Claim,也就是持久化存儲聲明。開發人員使用這個來描述該容器需要一個什麼存儲。

apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongodb-data
    persistentVolumeClaim:
      claimName: mongodb-pvc

小結一下,引入PV和PVC的目的是爲了解耦Pod與底層的存儲技術,研發人員不需要關心底層究竟使用哪種技術作爲存儲後端,這部分是由集羣管理員來做的.

研發人員只需要聲明你所需要存儲空間的大小即可,不需要了解底層存儲細節。

PV對象怎麼產生?

  • 靜態分配PV對象

集羣管理員事先規劃這個集羣的用戶會怎樣使用存儲,即預分配一些存儲,也就是預先創建一些PV

然後開發者聲明PVC的時候,會把PVC和相應PV做綁定

之後Pod需要使用存儲的時候,就可以通過PVC找到相應的PV

  • 動態分配PV對象

Cluster-admin 不需要預先分配PV,先寫一個模板文件(Storage Class),用來表示創建某一類型存儲如塊存儲,文件存儲所需的一些參數。

那麼用戶在聲明PVC的時候,需要指定使用的StorageClass模板

K8s會結合PVC和SC,生成用戶所需要的PV,把PV和PVC綁定。

然後pod就可以使用PV了。

換句話說,通過StorageClass配置生成存儲所需要的存儲模板,再結合用戶的需求動態創建PV對象,做到按需分配。

持久卷的動態卷配置

PV是由運維人員創建的,而PVC是由開發人員創建的,那麼大規模集羣中可能會有很多PV,如果這些PV都需要手動管理,將會十分繁瑣,因此就有了動態供給概念,核心就是StorageClass,作用是創建PV模板

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: k8s.io/minikube-hostpath
parameters:
  type: pd-ssd

那最終效果就是,用戶提交PVC,裏面指定存儲類型,如果符合定義的StorageClass,則會自動創建PV並且進行綁定.

如下,在創建PVC的時候,可以指定StorageClass的名稱,那麼在創建pvc後,由provisioner來指定真實的存儲,創建一個持久卷,並將其綁定到PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc
spec:
  storageClassName: fast
  resources:
    requests:
      storage: 100Mi
  accessModes:
    - ReadWriteOnce

架構設計

在這裏插入圖片描述
csi全稱container storage interface

是K8s社區對存儲插件實現的官方推薦方式

根據上圖,PV provision/attach過程:

  • (1)用戶提交PVCyaml,在集羣(api-server)中生成一個PVC對象
  • (2)PVC對象會被csi-provisioner controller 監控到
  • (3)csi-provisioner 結合PVC對象和PVC對象中聲明的storageClass,通過gRPC調用csi-controller-server,
  • (4)然後到雲存儲服務端創建真正的存儲,並最終創建出PV對象
  • (5)由集羣的PV controller把PVC和PV對象bound,然後就可以使用PV了

(1)用戶提交pod之後
(2)會被調度器調度選中一個合適的node
(3)在該node上面的kubelet在創建pod過程
(4)首先會通過csi-node-server將之前創建的PV掛載到pod可以使用的路徑
(6)kubelet的docker daemon創建container

總結:

創建存儲

  • 用戶提交完 PVC,由 csi-provisioner 創建存儲,並生成 PV 對象,之後 PV controller 將 PVC 及生成的 PV 對象做 bound,bound 之後,create 階段就完成了

存儲掛載到節點上

  • 用戶在提交 pod yaml 的時候,首先會被調度選中某一個 合適的node,等 pod 的運行 node 被選出來之後,會被 AD Controller watch 到 pod 選中的 node,它會去查找 pod 中使用了哪些 PV。然後它會生成一個內部的對象叫 VolumeAttachment 對象,從而去觸發 csi-attacher去調用csi-controller-server 去做真正的 attache 操作,attach操作調到雲存儲廠商OpenAPI。這個 attach 操作就是將存儲 attach到 pod 將會運行的 node 上面。第二個階段 —— attach階段完成

將對應的PV進一步掛載到 pod 可以使用的路徑

發生在kubelet 創建 pod的過程中,它在創建 pod 的過程中,首先要去做一個 mount,這裏的 mount 操作是爲了將已經attach到這個 node 上面那塊盤,進一步 mount 到 pod 可以使用的一個具體路徑,之後 kubelet 纔開始創建並啓動容器。這就是 PV 加 PVC 創建存儲以及使用存儲的第三個階段 —— mount 階段。

ref

https://gitbook.cn/gitchat/column/5d68b823de93ed72d6eca1bc/topic/5d8aff4f49b2b1063b559481

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章