<未完成> Kubernetes - Volumes

前言

本篇為 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
kind: Pod
metadata:
name: test-ebs
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4

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
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: {}

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
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

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
--region us-central1
--replica-zones us-central1-a,us-central1-b

範例 PersistentVolume 設定檔:

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

hostPath

  • hostPath volume 從 host node 的 filesystem 中, 掛載檔案或資料夾到 Pod
  • 除了 path property 之外, hostPath volume 還可以使用 optional field type
  • type 沒設或為空時, 預設不在掛載 hostPath volume 之前做任何檢查
  • typeDirectoryOrCreate 時, 如果該路徑是空的, 一個權限為 755, group 跟 owner 跟 kubelet 相同的空資料夾將會被建立
  • typeDirectory 時, path 中一定要存在一個 directory
  • typeFileOrCreate 時, 如果該路徑是空的, 一個權限為 644, group 跟 owner 跟 kubelet 相同的空檔案將會被建立
  • typeFile 時, path 中一定要存在一個 file
  • typeSocket 時, path 中一定要存在一個 UNIX socket
  • typeCharDevice 時, path 中一定要存在一個 character device
  • typeBlockDevice 時, path 中一定要存在一個 Block device
  • 一樣設定的 Pods 可能會也不一樣的行為, 因為 node 不同, 而不同 node 可能有不同的檔案
  • 建立於 host 的檔案或資料夾只有 root 可以寫。 可以使用 privileged Container 來存取 root 身份, 或在 host 修改檔案權限

範例 Pod

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
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory

注意: FileOrCreate mode 不會建立檔案的上層資料夾。 如果掛載檔案的上層資料夾不存在, Pod 會無法開始。 要確保沒問題, 可以分開掛載資料夾以及檔案, 如下:


Pod FileOrCreate 範例

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


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-node
  • PersistentVolume 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 可以寫, 要怎麼解決這個問題呢?
解釋以下的 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 時, 預設效果是?

typeBlockDevice 時, path 中一定要存在一個 Block device

Kubernetes 中, type field 為 CharDevice 時, 預設效果是?

typeCharDevice 時, path 中一定要存在一個 character device

Kubernetes 中, type field 為 Socket 時, 預設效果是?

typeSocket 時, path 中一定要存在一個 UNIX socket

Kubernetes 中, type field 為 File 時, 預設效果是?

typeFile 時, path 中一定要存在一個 file

Kubernetes 中, type field 為 FileOrCreate 時, 預設效果是?

typeFileOrCreate 時, 如果該路徑是空的, 一個權限為 644, group 跟 owner 跟 kubelet 相同的空檔案將會被建立

Kubernetes 中, type field 為 Directory 時, 預設效果是?

typeDirectory 時, 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

PHP - Data Structure and Algorithm Laravel - Digging Deeper - Events (官方文件原子化翻譯筆記)

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×