Kubernetes中,兩種常見型別的Volume深度實踐
一.背景
儲存資源在所有計算資源中扮演著十分重要的角色,大部分業務場景下都有可能使用到各類儲存資源。在Kubernetes中,系統通過Volume對叢集中的容器動態或靜態提供儲存資源。通常情況下,我們可以認為容器或者Pod的生命週期時短暫的,當容器被銷燬時,容器內部的資料也同時被清除。為了持久化儲存容器的資料,Kubernetes引入了Volume,類似於Docker的Volume(Docker also has a concept of volumes, though it is somewhat looser and less managed. In Docker, a volume is simply a directory on disk or in another Container. Lifetimes are not managed and until very recently there were only local-disk-backed volumes. Docker now provides volume drivers, but the functionality is very limited for now)。這個Volume被某個Pod掛載之後,這個Pod裡面的所有容器都能使用這個Volume。Kubernetes目前支援的volume型別可以參考文末官方資料。
二.兩種Volume使用舉例
2.1 emptyDir
emptyDir: emptyDir是最基礎的Volume型別。每個emptyDir Volume是主機上的一個空目錄,可以被Pod中所有的容器共享。它對於容器來說是持久的,對於Pod則不是。刪除容器並不會對它造成影響,只有刪除整個Pod時,它才會被刪除,它的生命週期與所掛載的Pod一致。簡而言之,emptyDir型別的Volume在Pod分配到Node上時被建立,Kubernetes會在Node主機上自動分配一個目錄,因此無需指定Node主機上對應的目錄檔案。 這個目錄的初始內容為空,當Pod從Node上移除時,emptyDir中的資料會被永久刪除。emptyDir主要用於一些無需永久保留的資料,例如臨時目錄,多容器共享目錄等。我們通過實際案例來理解一下,Pod gysl的yaml如下:
apiVersion: v1 kind: Pod metadata: name: gysl spec: containers: - image: busybox name: gysl-01 volumeMounts: - mountPath: /gysl-01 name: gysl-volume args: - /bin/sh - -c - echo "This is a test file.">/gysl-01/test.gysl;sleep 20000 - image: busybox name: gysl-02 volumeMounts: - mountPath: /gysl-02 name: gysl-volume args: - /bin/sh - -c - cat /gysl-02/test.gysl;sleep 20000 volumes: - name: gysl-volume emptyDir: {}
建立Pod gysl,並檢視相關資訊:
[[email protected] k8s-volumes]# kubectl apply -f emptyDir.yaml
pod/gysl created
[[email protected] k8s-volumes]# kubectl get pod
NAME READY STATUS RESTARTS AGE
gysl 2/2 Running 0 10m
[[email protected] k8s-volumes]# kubectl logs gysl gysl-02
This is a test file.
該例中,我們建立了一個名為gysl的Pod,這個pod裡面包含gysl-01和gysl-02兩個容器,這兩個容器同時掛載了名為gysl-volume的emptyDir,gysl-01的掛載點為/gysl-01,gysl-02的掛載點為gysl-02,容器gysl-01建立了一個test.gysl的檔案,內容為:“This is a test file.”在容器gysl-02中,成功顯示了gysl-01建立的檔案的內容。
2.2 hostPath
hostPath: hostPath的主要作用是將主機的檔案或目錄掛載給Pod的容器使用,使得容器能以較為良好的效能來儲存資料。接下來我們以Pod gysl-hostpath為例來理解一下hostPath的相關概念,YAML檔案如下:
apiVersion: v1
kind: Pod
metadata:
name: gysl-hostpath
spec:
nodeSelector:
role: test
containers:
- image: ubuntu:18.04
name: gysl-hostpath-container
volumeMounts:
- mountPath: /etc/gysl-test-01
name: gysl-02
- mountPath: /etc/gysl-test-02
name: gysl-01
- mountPath: /gysl-test-dir
name: gysl-dir
args:
- /bin/bash
- -c
- cat /etc/gysl-test-01 /etc/gysl-test-02;ls -l /gysl-test-dir;sleep 3600
volumes:
- hostPath:
path: /root/gysl-01
name: gysl-01
- hostPath:
path: /root/gysl-02
name: gysl-02
- hostPath:
path: /root/gysl-dir
name: gysl-dir
在Node k8s-n1的/root目錄下建立如下檔案和目錄:
[[email protected] ~]# ll
總用量 8
-rw-r--r-- 1 root root 16 11月 21 20:31 gysl-01
-rw-r--r-- 1 root root 16 11月 21 20:31 gysl-02
drwxr-xr-x 2 root root 51 11月 21 20:32 gysl-dir
兩個檔案的內容如下:
[[email protected] ~]# cat gysl-01
This is gysl-01
[[email protected] ~]# cat gysl-02
This is gysl-02
目錄gysl-dir的內容如下:
[[email protected] ~]# ll gysl-dir/
總用量 12
-rw-r--r-- 1 root root 16 11月 21 20:32 gysl-01
-rw-r--r-- 1 root root 16 11月 21 20:32 gysl-02
-rw-r--r-- 1 root root 16 11月 21 20:32 gysl-03
給Node k8s-n1指定一個標籤,apply 該Pod:
[[email protected] k8s-Volumes]# kubectl label node k8s-n1 role=test
node/k8s-n1 labeled
[[email protected] k8s-Volumes]# kubectl apply -f hostPath.yaml
pod/gysl-hostpath created
[[email protected] k8s-Volumes]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
gysl-hostpath 1/1 Running 0 17s 10.244.1.177 k8s-n1 <none>
[[email protected] k8s-Volumes]# kubectl logs gysl-hostpath
This is gysl-02
This is gysl-01
total 12
-rw-r--r-- 1 root root 16 Nov 21 12:32 gysl-01
-rw-r--r-- 1 root root 16 Nov 21 12:32 gysl-02
-rw-r--r-- 1 root root 16 Nov 21 12:32 gysl-03
這個例子中,我把名為gysl-02的hostPath檔案掛載到了容器的檔案/etc/gysl-test-01上,把名為gysl-01的hostPath檔案掛載到了容器的檔案/etc/gysl-test-02上,把名為gysl-dir的hostPath目錄掛載到了/gysl-test-dir下。通過logs命令,我們不難發現,目標已經達成。
這種掛載方式比emptyDir更為持久,除非所在Node發生故障。不過,除了掛載一些配置檔案/二進位制檔案之外,一般不採用該類掛載方式,因為這樣的掛載操作增加了Pod檔案與Node主機檔案的耦合,不利於統一管理。
三.總結
3.1 在volume的配置過程中,涉及到具體掛載路徑的需要按照一定的規則來配置。例如:檔案或目錄需要寫絕對路徑。不按照規則來配置,會出現以下報錯:
Warning Failed 8s (x3 over 20s) kubelet, k8s-n1 Error: Error response from daemon: create ~/gysl: "~/gysl-dir" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path
3.2 emptyDir和hostPath都是比較常見的兩種型別的volume,在使用時需要根據具體情況進行配置。其他型別的volume可參考以上兩種型別及官方文件進行配置,相關官方文件會在文末給出。
四.相關資料
5.1 Volumes基本概念
5.3 文章涉及到的YAML檔案