本章節將深入探討兩種常見的卷類型:emptyDir 和 hostPath。這兩者雖然概念簡單,但各自針對臨時緩存與持久化儲存提供了不同的解決方案,滿足了不同的應用場景需求。透過理解這兩種卷的特性與使用方法,將能更有效地設計、部署及管理 Kubernetes 應用。
emptyDir 是 Kubernetes 中的一種 Volume 類型。當一個 Pod 被指派到節點上運行時,emptyDir Volume 會被創建,並在 Pod 的整個生命周期內存在。一旦該 Pod 被刪除,emptyDir 中的數據也會隨之消失。
emptyDir 提供了一個簡單的解決方案。以下是一個使用 emptyDir 的 Kubernetes 組態檔範例:
apiVersion: v1
kind: Pod
metadata:
name: emptydir-demo
spec:
containers:
- name: container1
image: busybox
command: [ "sh", "-c", "echo Hello from container1 > /data/message && sleep 3600" ]
volumeMounts:
- mountPath: /data
name: shared-data
- name: container2
image: busybox
command: [ "sh", "-c", "cat /data/message && sleep 3600" ]
volumeMounts:
- mountPath: /data
name: shared-data
volumes:
- name: shared-data
emptyDir: {}
apiVersion: v1:指定使用的 Kubernetes API 版本為 v1。kind: Pod:指定這個資源的類型是 Pod。metadata:
name: emptydir-demo:Pod 的名稱是 emptydir-demo。spec:
containers:定義 Pod 內的容器。
name: container1:第一個容器的名稱是 container1。
image: busybox:使用 busybox 這個 Docker 鏡像來啟動容器。
command:容器啟動時執行的命令。這裡的命令是將訊息寫入 /data/message,然後進入休眠。
volumeMounts:將名為 shared-data 的卷掛載到容器內的 /data 路徑。
name: container2:第二個容器的名稱是 container2。
image: busybox:使用 busybox 這個 Docker 鏡像來啟動容器。
command:容器啟動時執行的命令。這裡的命令是讀取 /data/message 的內容,然後進入休眠。
volumeMounts:將名為 shared-data 的卷掛載到容器內的 /data 路徑。
volumes:定義 Pod 使用的卷。
name: shared-data:卷的名稱是 shared-data。emptyDir: {}:使用 emptyDir 作為卷的類型,這是一個臨時目錄,可以在兩個容器之間共享數據。在這個範例中,我們定義了一個名為 emptydir-demo 的 Pod,該 Pod 包含兩個容器 container1 和 container2。這兩個容器都掛載了一個名為 shared-data 的 emptyDir Volume 到 /data 路徑。
container1 會在 /data/message 中寫入一個訊息。container2 則會從 /data/message 中讀取該訊息。這個設計允許這兩個容器共享數據,而 emptyDir 提供了一個簡單的機制來實現這一點。這個 emptyDir Volume 是臨時的,當 Pod 被刪除時,所有數據都會消失。
組態檔案: emptyDir.yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: nginx
volumeMounts:
- name: emptydir-volume
mountPath: /usr/share/nginx/html
volumes:
- name: emptydir-volume
emptyDir: {} # 使用普通的 emptyDir
spec.containers[].volumeMounts:容器的卷掛載配置。
name: emptydir-volume:這個容器掛載的卷名稱是 emptydir-volume。mountPath: /usr/share/nginx/html:容器內的掛載點為 /usr/share/nginx/html。spec.volumes:定義這個 Pod 使用的卷。
name: emptydir-volume:卷的名稱是 emptydir-volume。emptyDir: {}:使用普通的 emptyDir 作為卷的類型,表示一個臨時空目錄,當 Pod 被刪除時,這個目錄的數據將會消失。部署 Pod
kubectl apply -f emptyDir.yaml
kubectl exec -it example-pod -- /bin/sh
echo "Hello, emptyDir!" > /usr/share/nginx/html/testfile.txt
kubectl delete pod example-pod
kubectl apply -f emptyDir.yaml
kubectl exec -it example-pod -- /bin/sh
cat /usr/share/nginx/html/testfile.txt
---
cat: /usr/share/nginx/html/testfile.txt: No such file or directory
文件不存在,這表明 emptyDir 卷是臨時的,隨著 Pod 的刪除,數據也被刪除了。
在 Kubernetes 中,emptyDir 可以配置為使用節點的內存 (memory) 來存儲數據,這樣可以提高 I/O 性能。
組態檔案: emptydir-memory.yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: nginx
volumeMounts:
- name: emptydir-memory
mountPath: /usr/share/nginx/html
volumes:
- name: emptydir-memory
emptyDir:
medium: Memory # 指定使用內存
kubectl apply -f emptydir-memory.yaml
kubectl exec -it example-pod -- /bin/sh
進入容器後,可以通過以下幾個方法檢查 emptyDir 是否使用了記憶體:
emptyDir 掛載點的文件系統類型df -h /usr/share/nginx/html
---
Filesystem Size Used Avail Use% Mounted on
tmpfs 32G 0 32G 0% /usr/share/nginx/html
如果掛載點顯示類型為 tmpfs,那麼它使用的是內存。
kubectl top pod
---
NAME CPU(cores) MEMORY(bytes)
example-pod 0m 12Mi
dd if=/dev/zero of=/usr/share/nginx/html/testfile bs=1M count=100
kubectl top pod
---
NAME CPU(cores) MEMORY(bytes)
example-pod 2m 113Mi
內存使用量顯著增加,說明 emptyDir 正在使用內存。
hostPath 是 Kubernetes 中的一種 Volume 類型,允許你將 Kubernetes 節點上的檔案或目錄掛載到 Pod 中的容器內。當你使用 hostPath 時,你可以指定節點上的一個具體路徑,Pod 啟動後,該路徑會被掛載到容器內的指定路徑中。
hostPath 的主要用途是允許容器直接訪問 Kubernetes 節點上的文件系統資源。這在一些情況下非常有用,例如:
hostPath 來存取和分析節點上的日誌檔案。hostPath 來確保數據在 Pod 重啟後仍然存在。hostPath 可能使容器獲得過高的權限,增加安全風險。應在必要情況下使用,並考慮其他更安全的存儲選項。hostPath 所掛載的目錄或文件僅存在於 Kubernetes 集群中的某個特定節點上,而不是在整個集群中的所有節點上共享。因此,如果 Pod 因某種原因(例如節點故障、負載均衡)被重新調度到另一個節點,原來的 hostPath 路徑將不再可用,因為這個路徑不存在於新節點上。以下是一個使用 hostPath 的 Kubernetes 組態檔範例:
apiVersion: v1
kind: Pod
metadata:
name: hostpath-demo
spec:
containers:
- name: container1
image: busybox
command: [ "sh", "-c", "ls /mnt/hostpath && sleep 3600" ]
volumeMounts:
- mountPath: /mnt/hostpath
name: my-hostpath
volumes:
- name: my-hostpath
hostPath:
path: /data
type: Directory
apiVersion: v1:指定使用的 Kubernetes API 版本為 v1。kind: Pod:指定這個資源的類型是 Pod。metadata:
name: hostpath-demo:Pod 的名稱是 hostpath-demo。spec:
containers:定義 Pod 內的容器。
name: container1:容器的名稱是 container1。image: busybox:使用 busybox 這個 Docker 鏡像來啟動容器。command:容器啟動時執行的命令,這裡是列出 /mnt/hostpath 目錄的內容,然後進入休眠。volumeMounts:將名為 my-hostpath 的卷掛載到容器內的 /mnt/hostpath 路徑。volumes:定義 Pod 使用的卷。
name: my-hostpath:卷的名稱是 my-hostpath。hostPath:指定卷的來源為主機路徑。
path: /data:主機上的路徑為 /data。type: Directory:指定該路徑的類型為目錄 (Directory)。在這個範例中,我們定義了一個名為 hostpath-demo 的 Pod,該 Pod 包含一個容器 container1。我們使用 hostPath Volume 將節點上的 /data 目錄掛載到容器內的 /mnt/hostpath 路徑中。
path:指定主機上的目錄或檔案路徑。這個範例中為 /data。type:指定 hostPath 的類型,如 Directory(目錄)、File(檔案)等。這個範例中使用 Directory。這個設計允許容器存取和使用節點上的本地資源,這在需要直接操作主機文件系統的情況下特別有用。
組態檔案: hostPath.yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
nodeName: wslkind-worker2 # 調度 Pod 到特定的節點
containers:
- name: example-container
image: nginx
volumeMounts:
- name: hostpath-volume
mountPath: /usr/share/nginx/html # 容器內的掛載點
volumes:
- name: hostpath-volume
hostPath:
path: /data # 節點上的路徑
type: DirectoryOrCreate # 如果目錄不存在,則自動創建
kubectl apply -f hostPath.yaml
kubectl exec -it example-pod -- /bin/sh
echo "Hello, hostPath!" > /usr/share/nginx/html/testfile.txt
kubectl delete pod example-pod
kubectl apply -f hostPath.yaml
kubectl exec -it example-pod -- /bin/sh
cat /usr/share/nginx/html/testfile.txt
---
Hell: not found!
文件存在,這表明 hostPath 卷是持久儲存,儘管刪除了掛載的 Pod,數據依然存留。
emptyDir 和 hostPath 各有其獨特的特性和適用場景。在選擇使用哪種卷時,應根據應用的需求、數據持久化要求以及安全性考量來做出決策。
emptyDir 主要用於臨時緩存、數據處理中間存儲和多容器數據共享,它提供了一個簡單的機制來共享臨時數據。
hostPath 允許容器直接存取節點上的文件系統資源,這在一些需要存取特定系統文件或日誌文件、數據共享以及持久性數據存儲的場景下非常有用。然而,hostPath 也可能帶來安全風險,需要謹慎使用。