前言
本篇為 Kubernetes 筆記, 內容主要參照官方文件, 考量到時間成本不會逐字翻譯, 但會將重要的資訊翻譯出來
容器中, 紀錄在硬碟上的檔案是暫時的, 對於運行在容器內的複雜應用來說, 這產生了一些問題。
首先, 當容器掛了, kubelet 會重啟它, 但檔案會丟失, 因為容器會以一個乾淨的狀態重啓。
再來, Pod 內的容器常常會需要共享一些檔案。 Kubernetes Volume
抽象可以解決這兩個問題。
建議對 Pod 熟悉。
Background
Kubernetes Volume 的生命週期與所屬的 Pod 一樣長, 所以說, volume 不受 Pod 內容器的重啓影響。
本質上來說, volume 只是個可被 Pod 內容器存取的資料夾。 而這個資料夾是怎麼來的, 什麼方式產生的, 有什麼樣的內容, 這些都取決於使用什麼樣的 volume 類型
Pod 的 .spec.volume
欄位指定了要使用什麼 volume, 而 .spec.container[*].volumMounts
欄位指定了要掛載這些 volume 到容器裡的位置
Volumes 無法掛載到其他 volumes 或硬連結到其他的 volumes, Pod 內的每一個容器都必須要獨立的指令要將 volume 掛載到哪個位置
Types of Volumes
awsElasticBlockStore
awsElasticBlockStore
volume 掛載一個 Amazon Web Services (AWS) EBS Volume 到你的 Pod。 跟 emptyDir
不同, 當 Pod 被移除時, EBS volume 的內容不會被移除, 而是會被保留, 僅僅是不掛載而已。 這表示 EBS volume 可以被預先載入資料, 然後這個資料可以在 Pods 之間傳遞
注意: 使用 EBS 之前, 需先使用 aws ec2 create-volume
來建立 EBS volume
當使用 awsElasticBolckStore
volume 時有幾個限制:
- Pods 所運行的 Nodes 必須要是 AWS EC2 instances
- 這些 instances 必須要跟 EBS volume 同 region 以及 zone
- EBS 只支援掛載一個 volume 的 EC2 instance
建立一個 EBS volume
在 Pod 使用 EBS volume 之前, 你需要先建立它
aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2 |
AWS EBS 範例設定檔
apiVersion: v1 |
emptyDir
emptyDir
volume 當 Pod 被指派給 Node 時建立emptyDir
的存活時間跟該 Pod 在該 Node 的時間一樣長emptyDir
一開始是空的- 所有在該 Pod 內的容器都可以 讀 以及 寫 該
emptyDir
中的同一個檔案 emptyDir
可以被掛載到每個容器中的不同路徑- 當 Pod 從 Node 移除,
emptyDir
中的資料會永久刪除 - 一個容器掛掉並不會將 Pod 從 Node 移除, 所以容器掛掉這件事不會影響到
emptyDir
中的資料 - 預設上,
emptyDir
會儲存在支援該 Node 的媒體, 可能是 disk, 或 SSD, 或網路儲存 emptyDir
也可透過emptyDir.medium
欄位設定成Memory
, 掛載到 tmpfs (RAM 支援的檔案系統)- 每當 node 重啟, tmpfs 會被清除
- tmpfs 上的使用量會算在該容器的 memory limits
範例 Pod
apiVersion: v1 |
gcePersistentDisk
gcePersistentDisk
volume 掛載一個 Gogole Compute Engine (GCE) Persistent Disk 到你的 Pod。 跟 emptyDir
不同, 當 Pod 被移除時, PD 的內容不會被移除, 而是會被保留, 僅僅是不掛載而已。 這表示 PD 可以被預先載入資料, 然後這個資料可以在 Pods 之間傳遞
注意: 使用 PD 之前, 需先使用 gcloud
或 GCE API 或 UI 來建立 PD
當使用 gcePersistentDisk
volume 時有幾個限制:
- Pods 運行所在的 Nodes 必須要是 GCE VMs
- PD 跟 VMs 需位於同一個 GCE project 以及 zone
PD 的一個特色是, 當被多方存取時, 只可使用 read-only 掛載。 這代表說, 你可以預載入資料, 然後讓多個 Pod 使用它。 不幸的是, PD 當掛載為 read-write 模式時, 並不支援多方存取。
若在一個由 ReplicationController 控制的 Pod 上使用 PD 將會失敗, 除非這個 PD 是 read-only, 或是 replica 為 0 或 1
建立 PD
在 Pod 使用 GCE PD 之前, 要先建立
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk |
範例 Pod
apiVersion: v1 |
Regional Persistent Disks
Regional Persistent Disk 功能讓 Persistent Disks 可以在不同的 zone, 相同的 region 內可用。 要使用這個功能, volume 必須要以 PersistentVolume 的方式提供, 直接從 Pod 來參照 volume 的方式並不被支援
手動提供 Regional PD PersistentVolume
使用 StorageClass for GCE PD 是可能的。 建立 PersistentVolume 之前, 先要建立 PD
gcloud beta compute disks create --size=500GB my-data-disk |
範例 PersistentVolume 設定檔:
apiVersion: v1 |
hostPath
hostPath
volume 從 host node 的 filesystem 中, 掛載檔案或資料夾到 Pod- 除了
path
property 之外,hostPath
volume 還可以使用 optional fieldtype
type
沒設或為空時, 預設不在掛載 hostPath volume 之前做任何檢查type
為DirectoryOrCreate
時, 如果該路徑是空的, 一個權限為 755, group 跟 owner 跟 kubelet 相同的空資料夾將會被建立type
為Directory
時, path 中一定要存在一個 directorytype
為FileOrCreate
時, 如果該路徑是空的, 一個權限為 644, group 跟 owner 跟 kubelet 相同的空檔案將會被建立type
為File
時, path 中一定要存在一個 filetype
為Socket
時, path 中一定要存在一個 UNIX sockettype
為CharDevice
時, path 中一定要存在一個 character devicetype
為BlockDevice
時, path 中一定要存在一個 Block device- 一樣設定的 Pods 可能會也不一樣的行為, 因為 node 不同, 而不同 node 可能有不同的檔案
- 建立於 host 的檔案或資料夾只有 root 可以寫。 可以使用 privileged Container 來存取 root 身份, 或在 host 修改檔案權限
範例 Pod
apiVersion: v1 |
注意: FileOrCreate
mode 不會建立檔案的上層資料夾。 如果掛載檔案的上層資料夾不存在, Pod 會無法開始。 要確保沒問題, 可以分開掛載資料夾以及檔案, 如下:
Pod FileOrCreate 範例
apiVersion: v1 |
local
local
volume 代表一個本地儲存裝置, 像是硬碟, 分區, 或資料夾local
volume 只能以 PersistentVolume 的方式被使用local
volume 跟hostPath
volume 的不同之處, 在於local
volume 不需要手動的指定 Pod 到特定的 node 上如果 node 掛了,
local
volume 也無法被存取, 且使用該local
volume 的 Pod 也無法運行以下為使用
local
volume 以及nodeAffinity
的 PersistentVolume 範例:apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-nodePersistentVolume
nodeAffinity
當使用 local volume 時為必要的。 它啟動 Kubernetes scheduler 正確的分配有使用 local volume 的 Pod 到正確的 Node 上PersistentVolume
volumeMode
也可以設成 “Block”
Questions and Answer
Kubernetes persistentVolume 中, nodeAffinity field 的作用是?
限制該 persistentVolume 只可從哪個 node 上被存取, 所以有定義使用該 persistentVolume 的 Pod 會被分配到該 node
Kubernetes 中, 當使用 local volume
時, 哪一個 field 是必要的?
nodeAffinity
解釋以下 Kubernetes example
- Example
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node - Answer
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
# volume 的系統格式
volumeMode: Filesystem
# 這個 volume 可以被掛載到一個 node 上, read and write
accessModes:
- ReadWriteOnce
# 當這個 persistentVolume 被 claim 釋放時, 刪除該 persistentVolume
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
# 使用 local volume
local:
path: /mnt/disks/ssd1
# 限制該 persistentVolume 只可從哪個 node 存取, 也就是說, 有定義存取該 persistentVolume 的 Pod 都會被分配到該 node
nodeAffinity:
required:
nodeSelectorTerms:
# 目標 node, key kubernetes.io/hostname, 其 value 須為 example-node
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node
Kubernetes 中, local
volume 需要手動的指定 Pod 要分配到的 Node 嗎?
不需要
Kubernetes 中, local
volume 只能以什麼形式被使用?
Persistent Volume
Kubernetes 中, local
volume 代表本地儲存裝置, 比如說?
硬碟, 分區, 資料夾
Kubernetes 中, 當使用 hostPath 時, host 下的檔案只有 root 可以寫, 要怎麼解決這個問題呢?
- 使用 privileged container
- 修改 host 下檔案權限
解釋以下的 Kubernetes example
- Example:
apiVersion: v1
kind: Pod
metadata:
name: test-webserver
spec:
containers:
- name: test-webserver
image: k8s.gcr.io/test-webserver:latest
volumeMounts:
- mountPath: /var/local/aaa
name: mydir
- mountPath: /var/local/aaa/1.txt
name: myfile
volumes:
- name: mydir
hostPath:
# Ensure the file directory is created.
path: /var/local/aaa
type: DirectoryOrCreate
- name: myfile
hostPath:
path: /var/local/aaa/1.txt
type: FileOrCreate - Answer:
apiVersion: v1
kind: Pod
metadata:
name: test-webserver
spec:
containers:
- name: test-webserver
image: k8s.gcr.io/test-webserver:latest
volumeMounts:
- mountPath: /var/local/aaa
name: mydir
- mountPath: /var/local/aaa/1.txt
name: myfile
volumes:
# 要確保資料夾跟檔案都有掛載, 所以分開掛載兩個
- name: mydir
hostPath:
# Ensure the file directory is created.
path: /var/local/aaa
type: DirectoryOrCreate
- name: myfile
hostPath:
path: /var/local/aaa/1.txt
type: FileOrCreate
Kubernetes 中, type field 為 BlockDevice 時, 預設效果是?
type
為 BlockDevice
時, path 中一定要存在一個 Block device
Kubernetes 中, type field 為 CharDevice 時, 預設效果是?
type
為 CharDevice
時, path 中一定要存在一個 character device
Kubernetes 中, type field 為 Socket 時, 預設效果是?
type
為 Socket
時, path 中一定要存在一個 UNIX socket
Kubernetes 中, type field 為 File 時, 預設效果是?
type
為 File
時, path 中一定要存在一個 file
Kubernetes 中, type field 為 FileOrCreate 時, 預設效果是?
type
為 FileOrCreate
時, 如果該路徑是空的, 一個權限為 644, group 跟 owner 跟 kubelet 相同的空檔案將會被建立
Kubernetes 中, type field 為 Directory 時, 預設效果是?
type
為 Directory
時, path 中一定要存在一個 directory
Kubernetes 中, type field 為 DirectoryOrCreate 時, 預設效果是?
如果該路徑是空的, 一個權限為 755, group 跟 owner 跟 kubelet 相同的空資料夾將會被建立
Kubernetes 中, type field 為空或沒設時, 預設效果是?
預設不會在掛載 hostPath volume 之前針對 path 做任何檢查
Kubernetes 中, hostPath volume 除了 path field 之外, 還能使用哪一個 optional field?
type field
Kubernetes 中, hostPath volume 的作用是?
從 host node 的 filesystem 中, 掛載檔案或資料夾到 Pod
解釋以下 Kubernetes example
- Example:
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-volume
labels:
failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
spec:
capacity:
storage: 400Gi
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4 - Answer:
apiVersion: v1
# 定義 PersistentVolume
kind: PersistentVolume
metadata:
name: test-volume
labels:
failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
spec:
capacity:
# 容量定義為 400Gi
storage: 400Gi
# 定義存取模式
accessModes:
- ReadWriteOnce
# 使用 gcePersistentDisk
gcePersistentDisk:
# 輸入 pdName
pdName: my-data-disk
# file system 類型
fsType: ext4
Kubernetes volume 中, 若要使用 Regional Persistent Disk, volume 要以什麼形式提供?
PersistentVolume
解釋以下 Kubernetes example
- Example:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
# This GCE PD must already exist.
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4 - Answer:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
# This GCE PD must already exist.
# 使用 GCP Persistent Disk
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
Kubernetes volume 中, 當使用 GCE Persistent Disk 時, read-write 模式支援多方存取嗎?
不支援
Kubernetes volume 中, 當使用 GCE Persistent Disk 時, read-only 模式支援多方存取嗎?
支援
Kubernetes volume 中, 當使用 GCE Persistent Disk 時, Persistent Disk 與 VMs 需位於怎麼樣的條件?
- 同一個 GCE project
- 同一個 zone
Kubernetes volume 中, 當使用 GCE Persistent Disk 時, Pods 所運行的 Node 必須要是 GCE VMs, 是或不是?
是
Kubernetes volume 中, Persistent Disk 可以預先載入, 被多個 Pod 使用嗎?
可以
Kubernetes volume 中, 當我使用 Persistent Disk 為 volume 時, 當 Pod 被移除時, PD 的資料會被移除嗎?
不會
Kubernetes 中, emptyDir
的存活時間為多久?
emptyDir
的存活時間跟該 Pod 在該 Node 的時間一樣長
Kubernetes 中, emptyDir volume 剛建立時裡頭有什麼東西?
emptyDir
一開始是空的
Kubernetes 中, 同個 Pod 內的不同容器可否讀寫同一個 emptyDir volume 的檔案?
可
Kubernetes 中, emptyDir 可否被掛載到不同容器中不同路徑?
可
Kubernetes 中, 當 Pod 從 Node 被移除, emptyDir 中的資料還會存在嗎?
不會, 會被永久刪除
Kubernetes 中, 如果一個 Pod 中有一個容器 crashes, 那會影響到 emptyDir volume 中的資料嗎?
不會
Kubernetes 中, 預設上, emptyDir 會被儲存在什麼地方?
該 Node 所在的 medium
Kubernetes 中, emptyDir 可以被掛載到 tmpfs 嗎?
可以
Kubernetes 中, 若要掛載 emptyDir 到 tmpfs, 需使用哪一個欄位??
emptyDir.medium
Kubernetes 中, 當 Node reboot, tmpfs 中的資料會如何?
會被清除
Kubernetes 中, tmpfs 是?
RAM based filesystem
Kubernetes 中, tmpfs 的用量會算在 memory limits 嗎?
會哦
Kubernetes 中, emptyDir volume 是在什麼時候被建立的?
當 Pod 被分配給一個 Node 時
解釋以下 Kubernetes example
- Example
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {} - Answer
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
# 定義一個 emptyDir 類型的 volume
emptyDir: {}
Kubernetes 中, volume 可以硬連結到另一個 volume 嗎?
不行
Kubernetes 中, volume 可以掛載到另外一個 volume 裡嗎?
不行
Kubernetes 中, 一般來說, volume 的周命週期與什麼相同?
Pod
留言