Kubernetes 初戰(二) 儲存空間 Volume

Kubernetes 初戰(二) 儲存空間 Volume

2021, May 16    

在一般的觀念裡,container 相當合適作為 stateless application 之用(例如:api service),但由於 stateful service 的需求也是存在的(例如:各種資料庫、檔案存放伺服器…等等),因此 Kubernetes 就額外增加了一些相關的機制,讓 pod 也開始能夠承載 stateful application,本篇就簡單接紹 K8s 裡的 Volume 機制,看看是如何將資料保存下來

Volume

為了保存 container 的狀態而誕生的機制就是 Volume,在 Docker 中其實也有這個機制可以看看之前的文章 利用 Docker volume 儲存 container 的資料 簡單來說 K8s 的 Volume 主要是為了解決:

  1. 資料在 container 中無法存續,重啟 container 後將會遺失
  2. pod 內的多個 container 有共享檔案的需求

K8s 支援幾種不同的 Volume Type 下面會各自介紹,詳細也可見官方文件:

emptyDir

簡單的 Volume 掛載可以直接在 Pod 中設定,下面是 EmptyDir 的設定:

apiVersion: v1
kind: Pod
metadata:
  name: empty-dir-nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /tmp/conf
      name: empty-dir
  volumes:
  - name: empty-dir
    emptyDir: {}

emptyDir 顧名思義一開始會是一個空的目錄用來暫存或是共享資料,雖說是一種 Volume 但是在 Pod 被移除的時候資料依舊會被一並刪除,主要用途是當 Pod 崩潰被 Deploy 這類的 controller 重啟時會保留,可以看見 emptyDir 只有指定 mountPath 而沒有設定機器(Node)上的存放位置,就是因為沒有這個需求

emptyDir 主要會應用在:

  • 暫存資料
  • 多 container 的共用資料

  • 這邊要注意的是 volumeMounts 裡的 name 要跟 volumesname 對應上,volumes 裡是定義這個 volume 的 spec 然後在 volumeMounts 裡進行掛載

hostPath

第二個來看到的 Volume 種類是 hostPath,以下是 yaml 的設定方式:

apiVersion: v1
kind: Pod
metadata:
  name: host-path-nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /tmp/conf
      name: host-path
  volumes:
  - name: host-path
    hostPath:
      path: /tmp/host_path
      type: DirectoryOrCreate

hostPath 是一個很直覺的 Volume 種類,就是將 container 內的指定路徑跟實體機(Node)上的指定路徑綁定在一起,Docker 的 Volume 也比較像這個模式,而 hostPath 設定裡還有一個 type 可以做一些路徑的檢查如下表:

type 描述
(空) 不做任何檢查
DirectoryOrCreate 路徑必須為目錄若不存在則建立
Directory 路徑必須為已存在目錄
FileOrCreate 路徑必須為檔案若不存在則建立
File 路徑必須為已存在檔案
Socket 路徑必須為已存在的 UNIX socket
CharDevice 路徑必須為已存在 character device
BlockDevice 路徑必須為已存在的 block device

實際上後三個 type 筆者也不確定是用在什麼情境,詳情可以看官方文件原文

emptyDir 的差異上來說,可以事先在 hostPath 裡放入資料再進行掛載,且 Pod 重啟資料也不會遺失,符合 stateful 的 service 使用情境

但通常來說不會直接用 hostPath 來設定 Volume,會再透過 Persistent Volumes (PV) 以及 Persistent Volume Claims (PVC) 來進行 Volume 的管理,大多用在測試階段才會先用 hostPath 來使用

  • 如果說需要在一個 Volume 下掛載多個路徑也可以透過 subPath 的方式,如下所設定:
apiVersion: v1
kind: Pod
metadata:
  name: host-path-nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /tmp/conf
      name: host-path
      subPath: sub1
    - mountPath: /tmp/conf
      name: host-path
      subPath: sub2
  volumes:
  - name: host-path
    hostPath:
      path: /tmp/host_path
      type: DirectoryOrCreate

照這樣設定可以在同一個 hostPath 之下掛載兩個目錄,而不會把資料都混在一起

其他

其他的 Volume Type 則主要是用於雲端上的儲存空間,可以透過 K8s 直接將 Volume 掛載到雲端上,如下面的三種:

  1. gcePersistentDisk
  2. awsElasticBlockStore
  3. azureDisk

分別在各個平台上都有各自的 Volume Type,K8s 這方面的支援也真的是很到位,不過目前筆者還沒有用到雲端儲存空間的經驗這邊就不細談了


結語

此篇簡單講解 k8s 的 Volume 在 Pod 上的設定還有種類,下次預計會介紹下 Persistent Volumes (PV)Persistent Volume Claims (PVC),更完整得補完 K8s 在資料保存方面的機制