iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 14
1
DevOps

k8s 不自賞系列 第 14

Day 14 - 別再遺失資料了:Volume (1)

Day 14 - 別再遺失資料了:Volume (1)

本日共賞

  • Volume
  • Volume 種類

希望你知道

Volume

今天想聊聊 k8s 中的 Volume。還記得我們在 Day 10 - 建構組件 曾經提到過 Pod 有臨時性的特性 (ephemeral),意思就是,當 Pod 被刪除的同時,所有屬於 Pod 的資料便會一並被刪除。而當 Pod 被刪除時,k8s 會嘗試重新建立 Pod 這時候新建的 Pod 的內容並 不會包含被刪除 Pod 的內容

  • 如果直接部署 Pod 物件,當刪除 Pod 物件時 k8s 並不會建立新的 Pod,而是建立 Deployment 物件後,刪除該物件對應的 Pod,k8s 才會重新建立 Pod。
  • 不會包含被刪除 Pod 的內容 指的是 Pod 運行後產生的內容,並非映像檔內容,映像檔原始內容還是會一致。

因此,為了克服這個問題,k8s 提供了 Volume 物件來儲存需要保存的資料。簡單來看可以當作是一個目錄且包含在 Pod 內獨立存活在容器外。

還記得 Pod 內的容器是共用 Volume 嗎?

Volume 種類

Volume 種類其實還蠻多的,詳細內容可參考 官網說明,底下列舉幾個常用的種類

1. emptyDir

emptyDir 依舊是屬於臨時性的目錄,當 Pod 被刪除的同時該目錄也會被刪除。而在 Pod 被建立的同時,k8s 會自動地分配一個目錄,即無須指定 Node 上的目錄。另外要注意的一點是,如果容器崩潰 (crash),該目錄還是會留著。只有 Pod 被刪除才會一併刪除。

emptyDir 可以應用在

  • 暫存空間
  • 多個容器的共享空間

底下為 emptyDir 的一個例子

# volume-empty.yaml

---
apiVersion: v1
kind: Pod
metadata:
  name: volume-empty-nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /tmp/conf  <=== 將 empty-volume 掛載到 /tmp/conf 下
      name: empty-volume
  volumes:
  - name: empty-volume
    emptyDir: {}            <=== 指定為 emptyDir 

試試部署到 k8s 並觀察狀態

$ kubectl apply -f volume-empty.yaml
pod "volume-empty-nginx" created

$ kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
volume-empty-nginx   1/1       Running   0          16m

接著透過指令連到 volume-empty-nginx Pod 並查看 /tmp/conf

$ kubectl exec -it volume-empty-nginx bash
root@volume-empty-nginx:/# ls -al /tmp
total 12
drwxrwxrwt 1 root root 4096 Dec  4 07:22 .
drwxr-xr-x 1 root root 4096 Dec  4 07:22 ..
drwxrwxrwx 2 root root 4096 Dec  4 07:22 conf

kubectl exec 請參考 Get a Shell to a Running Container

你會發現 /tmp/conf 已經掛載成功

可以試試看把 yaml 中的 Volume 宣告移除後再部署到 k8s 看看有什麼變化

記得先移除 Pod,忘記怎麼移除可以參考 Day 8 - 與 k8s 溝通: kubectl 之 8. 刪除資源

2. hostPath

使用 hostPath 可以指定一個 Node 的目錄掛載到 Pod 中使用,即便 Pod 被刪除,該目錄的內容也都會存在。hostPath 形態的 Volume 可以從 Node 掛載一個檔案或者目錄到 Pod。

底下是一個 hostPath Volume 的例子

# volume-hostpath.yaml

---
apiVersion: v1
kind: Pod
metadata:
  name: volume-hostpath-nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /tmp/conf     <=== 一樣掛載到 /tmp/conf,不同的 Pod 不怕
      name: hostpath-volume
  volumes:
  - name: hostpath-volume
    hostPath:
      path: /tmp/hostpathdata  <=== 指定 Node 目錄,可更換成其他目錄

接著部署到 k8s 中,在 Pod 正常運行後連到該 Pod

$ kubectl apply -f volume-hostpath.yaml
pod "volume-hostpath-nginx" created

$ kubectl exec -it volume-hostpath-nginx bash
root@volume-hostpath-nginx:/#

接著在 /tmp/conf 建立一個 mypath 檔案後,鍵入 exit 離開:

root@volume-hostpath-nginx:/# echo "My Host Path" >> /tmp/conf/mypath

root@volume-hostpath-nginx:/# exit

接著把 volume-hostpath-nginx 移除

$ kubectl delete pods volume-hostpath-nginx
pod "volume-hostpath-nginx" deleted

接著,我們到 Node 查看剛剛建立的檔案是否還存在,由於我們使用 minikube,因此 Node 指的就是 minikube 運行的虛擬機。可以利用下列指令連到 minikube

在 k8s 叢集中 Node 可能會有很多台,只是目前我們使用 minikube 做示範故只有一台 Node

$ minikube ssh
                         _             _            
            _         _ ( )           ( )           
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __  
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)

$ cat /tmp/hostpathdata/mypath 
My Host Path

mypath 還存在在 /tmp/hostpathdata 目錄底下,證明的確不會因為 Pod 刪除而被刪除。

雖然 hostPath 是保存資料的方法,不過一般不建議這樣使用,因為概念上來看,Pod 與 Node 是沒有依存關係。如果使用這種方式,則 Pod 的運行可能會需要 Node 上的某個檔案。但是,如果是需要直接存取函式庫 (理論上每台 Node 都應該要有) 這時候就可以使用 hostPath

由於 Pod 是會被部署到任意 Node 中,因此透過 hostPath 產生的檔案,很有可能不存在在所有的 Node 中,你應該可以預見會有什麼事情發生了吧!

3. gcePersistentDisk

k8s 可以直接支援 Google Compute Engine (GCE) 上的磁碟,用的就是 gcePersistentDisk 這類型的 Volume。在後面的文章我們再來說明如何使用。

4. awsElasticBlockStore

類似 gcePersistentDisk,k8s 同樣支援 Amazon Web Service (AWS) 中的 EBS Volume 使用的就是 awsElasticBlockStore

5. azureDisk

azureDisk 指的是 Microsoft AzureData Disk,同樣的,k8s 可與 Azure 串接。

6. secret

Secret,k8s 中另一個重要的物件且可以用 Volume 的形式掛載到 Pod 內使用。

關於 Secret 我們會在之後的文章再更詳細的說明。

明天我們再接著欣賞 Persisten Volumes 與 Persistent Volume Claims

本文與部署檔案同步發表於 https://jlptf.github.io/ironman2018-day14/


上一篇
Day 13 - 別耍自閉開放你的應用吧:Ingress
下一篇
Day 15 - 別再遺失資料了:Volume (2)
系列文
k8s 不自賞32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言