- 一、概述
- 1、StorageClass 物件定義
- 2、StorageClass YAML 示例
- 二、StorageClass 欄位
- 1、provisioner(儲存製備器)
- 1.1、內建製備器
- 1.2、第三方製備器
- 2、reclaimPolicy(回收策略)
- 3、allowVolumeExpansion(允許卷擴充套件)
- 4、mountOptions(掛載選項)
- 5、volumeBindingMode(卷繫結模式)
- 5.1、Immediate
- 5.2、WaitForFirstConsumer
- 6、allowedTopologies(允許的拓撲結構)
- 6.1、示例
- 7、parameters(儲存引數)
- 7.1、示例
- 7.2、儲存引數(AWSElasticBlockStore)
- 8、設定預設的 StorageClass(storageclass.kubernetes.io/is-default-class)
- 8.1、示例
- 8.2、修改已有的 StorageClass
- 8.2.1、將存在的 SC 設定為預設
- 8.2.2、將存在的 SC 設定為非預設
- 1、provisioner(儲存製備器)
- 三、例項 -- 使用 NFS 型別的 StorageClass 動態建立 PV
- 1、配置 NFS 服務端
- 1.1、master 節點安裝 nfs-utils 包
- 1.2、master 節點建立共享目錄
- 1.3、編輯/etc/exports檔案
- 1.4、應用新的匯出設定
- 1.5、重啟並設定 NFS 開機自啟
- 1.6、檢查 NFS 共享
- 2、配置 NFS 客戶端
- 2.1、安裝 nfs-utils 包
- 2.2、建立目錄掛載 NFS 共享
- 2.2.1、解除安裝錯誤的掛載點
- 2.3、重啟並設定 NFS 開機自啟
- 2.4、系統啟動自動掛載 NFS 共享(非必要)
- 2.5、檢視掛載狀態
- 3、建立儲存類
- 4、建立 RBAC 許可權
- 5、建立 provisioner
- 6、建立 PVC
- 7、觀察 PV 是否動態建立
- 8、建立使用同一 PVC 的多個 Pod
- 9、向共享儲存寫入資料
- 10、從另一個 Pod 讀取資料
- 11、檢視 nfs 服務端與客戶端的共享目錄
- 11.1、PV 目錄建立的流程
- 11.2、PV 目錄的結構
- 12、修改 NFS 伺服器共享目錄內容檢視容器內部變化
- 1、配置 NFS 服務端
- 四、例項 -- 動態建立 PVC 和 PV
- 1、建立 Headless Service
- 2、建立 StatefulSet
- 3、觀察 Pod狀態
- 4、觀察到 PVC 與 PV 已經動態建立並相互繫結了
- 5、每一個 Pod 都會透過繫結 PVC 獲取一塊獨立的 PV
一、概述
叢集級別資源,StorageClass 是 Kubernetes 中的一種資源物件,它定義了建立 Persistent Volume (PV) 的策略和方法。StorageClass 主要用於實現 PV 的動態供應,這意味著當使用者建立了一個 Persistent Volume Claim (PVC) 時,Kubernetes 會根據所指定的 StorageClass 自動建立一個符合要求的 PV 並將其繫結到 PVC 上
StorageClass
作為對儲存資源的抽象定義,對使用者設定的 PVC
申請遮蔽後端儲存的細節,一方面減少了使用者對於儲存資源細節的關注,另一方面減輕了管理員手工管理 PV
的工作,由系統自動完成 PV
的建立和繫結,實現動態的資源供應。基於 StorageClass
的動態資源供應模式將逐步成為雲平臺的標準儲存管理模式。
1、StorageClass 物件定義
StorageClass 資源物件的定義主要包括:名稱、後端儲存的提供者 (provisioner)、後端儲存的相關引數配置(parameters)和回收策略(reclaimPolicy)、卷繫結模式(volumeBindingMode)
StorageClass 的名稱很重要,將在建立 PVC 時引用,管理員應該準確命名具有不同儲存特性的 StorageClass。
StorageClass 一旦被建立,則無法修改,如需更改,則只能刪除原 StorageClass 資源物件並重新建立。
2、StorageClass YAML 示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
# 儲存類的名稱,使用者在 PVC 中引用
name: example-storage-class
storageclass.kubernetes.io/is-default-class: "true" # 設定為預設的 StorageClass
# 動態製備器的名稱,需要與已安裝的製備器匹配
provisioner: kubernetes.io/aws-ebs # 例子中使用的是 AWS EBS 製備器
# reclaimPolicy 定義了當 PVC 被刪除時,PV 應該如何處理
reclaimPolicy: Delete # 可選值為 Retain 或 Delete
# 允許卷擴充套件
allowVolumeExpansion: true # 可選值為 true 或 false
# 定義了卷繫結到 Pod 的模式
volumeBindingMode: Immediate # 可選值為 Immediate 或 WaitForFirstConsumer
# 定義了儲存系統需要的引數,這些引數會傳遞給製備器
parameters:
# 儲存型別,根據製備器和儲存系統的要求設定
type: gp2 # AWS EBS 的例子,對於其他系統可能有不同的值
# 儲存 IOPS 效能,某些儲存系統可能需要這個引數
iopsPerGB: "10" # 例子,具體值根據需求和製備器支援設定
# 儲存的最小 IOPS 值,某些儲存系統可能需要這個引數
minimumIOPS: "1000" # 例子,具體值根據需求和製備器支援設定
# 儲存的最大 IOPS 值,某些儲存系統可能需要這個引數
maximumIOPS: "20000" # 例子,具體值根據需求和製備器支援設定
# 儲存的加密選項,某些儲存系統可能支援加密
encrypted: "true" # 例子,具體值根據需求和製備器支援設定
# 儲存的區域,對於跨區域儲存系統可能需要這個引數
availabilityZone: "us-east-1a" # 例子,具體值根據製備器和儲存系統的要求設定
# 儲存的效能等級,某些儲存系統可能提供不同的效能等級
performance: "high" # 例子,具體值根據製備器和儲存系統的要求設定
# 定義了掛載選項,這些選項會在 PV 被掛載到節點時使用
mountOptions:
- debug # 例子,具體值根據需求設定,可能包括 "debug", "defaults", "ro" 等
# - other-option # 可以新增額外的掛載選項
# 允許的拓撲約束,定義了儲存可以被哪些節點訪問
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/region
values:
- us-east-1
- key: topology.kubernetes.io/zone
values:
- us-east-1a
二、StorageClass 欄位
1、provisioner(儲存製備器)
provisioner 指定了用於動態建立 PersistentVolume (PV) 的製備器(Provisioner)。製備器是一個外掛,它負責在後端儲存系統中根據 PersistentVolumeClaim (PVC) 的請求來建立儲存資源,不同的儲存外掛支援不同的儲存後端和服務提供商。當 PVC 被建立並且與之關聯的 StorageClass 指定了一個製備器時,Kubernetes 會呼叫這個製備器來自動建立相應的 PV。
卷外掛 | 內建製備器 | 配置示例 |
---|---|---|
AWSElasticBlockStore | √ | AWS EBS |
AzureFile | √ | Azure檔案(已棄用) |
AzureDisk | √ | Azure Disk |
CephFS | - | - |
Cinder | √ | Open Stack Cinder |
FC | - | - |
FlexVolume | - | - |
GCEPersistentDisk | √ | gcePD |
Glusterfs | √ | GlusterFS |
iSCSI | - | - |
Local | - | Local |
NFS | - | NFS |
PortworxVolume | √ | portworx-volume |
RBD | √ | ceph-rbd |
VsphereVolume | √ | Vsphere |
1.1、內建製備器
Kubernetes 內建支援的 Provisioner 的命名都以 "kubernetes.io/" 開頭
- kubernetes.io/aws-ebs:用於在 AWS 上建立 Elastic Block Store (EBS) 卷。
- kubernetes.io/azure-disk:用於在 Azure 上建立磁碟。
- kubernetes.io/gce-pd:用於在 Google Cloud Platform (GCP) 上建立持久磁碟。
- kubernetes.io/cinder:用於在 OpenStack 上建立 Cinder 卷。
1.2、第三方製備器
為了符合 StorageClass 的用法,自定義 Provisioner 需要符合儲存卷的開發規範,外部儲存供應商的作者對程式碼、提供方式、執行方式、儲存外掛(包括Flex)等具有完全的自由控制權。
程式碼倉庫 kubernetes-sigs/sig-storage-lib-external-provisioner 包含一個用於為外部製備器編寫功能實現的類庫。你可以訪問程式碼倉庫 kubernetes-sigs/sig-storage-lib-external-provisioner 瞭解外部驅動列表。
例如,對NFS型別,Kubernetes沒有提供內部的Provisioner,但可以使用外部的Provisioner。也有許多第三方儲存提供商自行提供外部的Provisioner。
2、reclaimPolicy(回收策略)
透過動態資源供應模式建立的PV將繼承在StorageClass資源物件上設定的回收策略,配置欄位名稱為“reclaimPolicy“,可以設定的選項包括Delete(刪除)和 Retain(保留)。
- 如果StorageClass沒有指定reclaimPolicy,則預設值為Delete。
- 對於管理員手工建立的仍被StorageClass管理的PV,將使用建立PV時設定的資源回收策略。
3、allowVolumeExpansion(允許卷擴充套件)
PV 可以被配置為允許擴容,當 StorageClass 資源物件的 allowVolumeExpansion欄位被設定為true時,將允許使用者透過編輯PVC的儲存空間自動完成PV的擴容。
下表描述了支援儲存擴容的Volume型別和要求的Kubernetes最低版本:
支援儲存擴容的 Volume 型別 | Kubernetes 最低版本 |
---|---|
gcePersistentDisk | 1.11 |
awsElasticBlock Store | 1.11 |
Cinder | 1.11 |
glusterfs | 1.11 |
RBD | 1.11 |
Azure File | 1.11 |
Azure Disk | 1.11 |
Portworx | 1.13 |
FlexVolume | 1.14(Alpha) |
CSI | 1.16(Beta) |
此功能僅可用於擴容卷,不能用於縮小卷。
4、mountOptions(掛載選項)
透過StorageClass資源物件的mountOptions欄位,系統將為動態建立的PV設定掛載選項。
並不是所有 PV型別都支援掛載選項,如果 PV不支援但 StorageClass 設定了該欄位,則 PV將會建立失敗。另外,系統不會對掛載選項進行驗證,如果設定了錯誤的選項,則容器在掛載儲存時將直接失敗。
5、volumeBindingMode(卷繫結模式)
StorageClass 資源物件的 volumeBindingMode 欄位設定用於控制何時將 PVC 與動態建立的 PV 繫結。
目前支援的繫結模式包括: Immediate 和 WaitForFirstConsumer。
5.1、Immediate
儲存繫結模式的預設值為 Immediate,表示當一個PersistentVolumeClaim (PVC)建立出來時,就動態建立PV並進行PVC與PV的繫結操作。
需要注意的是,對於拓撲受限 (Topology-limited) 或無法從全部Node訪問的後端儲存,將在不瞭解Pod排程需求的情況下完成PV的繫結操作,這可能會導致某些Pod無法完成排程。
5.2、WaitForFirstConsumer
WaitForFirstConsumer繫結模式表示PVC與PV的繫結操作延遲到第一個使用 PVC的Pod建立出來時再進行。
系統將根據Pod的排程需求,在Pod所在的Node上建立PV,這些排程需求可以透過以下條件(不限於)進行設定:
-
Pod對資源的需求
-
Node Selector
-
Pod親和性和反親和性設定
-
Taint和Toleration設定
目前支援 WaitForFirstConsumer 繫結模式的儲存捲包括:
- AWSElasticBlockStore
- AzureDisk
- GCEPersistentDisk.
另外,有些儲存外掛透過預先建立好的PV繫結支援WaitForFirstConsumer模式,比如:
- AWSElasticBlockStore
- AzureDisk
- GCEPersistentDisk
- Local
6、allowedTopologies(允許的拓撲結構)
在使用WaitForFirstConsumer模式的環境中,如果仍然希望基於特定拓撲資訊(Topology)進行PV繫結操作,則在StorageClass的定義中還可以透過 allowedTopologies欄位進行設定。
6.1、示例
下面的例子透過 matchLabelExpressions 設定目標 Node 的標籤選擇條件 (zone=us-central1-a或 us-central1-b) PV 將在滿足這些條件的 Node 上允許建立
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/example
parameters:
type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/zone
values:
- us-central-1a
- us-central-1b
7、parameters(儲存引數)
後端儲存資源提供者的引數設定,不同的 Provisioner 可能提供不同的引數設定。某些引數可以不顯示設定,Provisioner 將使用其預設值。
目前 StorageClass 資源物件支援設定的儲存引數最多為 512個,全部 key 和 value 所佔的空間不能超過 256KiB。
7.1、示例
下面舉常見儲存提供商(Provisioner)提供的 StorageClass 儲存引數示例(以AWSElasticBlockStore儲存卷為例子):
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
csi.storage.k8s.io/fstype: xfs
type: io1
iopsPerGB: "50"
encrypted: "true"
allowedTopologies:
- matchLabelExpressions:
- key: topology.ebs.csi.aws.com/zone
values:
- us-east-2c
7.2、儲存引數(AWSElasticBlockStore)
AWS EBS 儲存引數
-
type (必需)
- 定義 EBS 卷的儲存型別(預設值gp3)。例如:
- gp2:通用目的 SSD
- io1:提供高 IOPS 的 SSD
- io2:適用於需要大量 IOPS 的應用程式的新一代 SSD
- st1:透過 HDD 儲存最佳化的卷
- sc1:透過冷 HDD 儲存最佳化的卷
- 定義 EBS 卷的儲存型別(預設值gp3)。例如:
-
iopsPerGB (可選,僅當 type 為 io1 或 io2 時有效)
- 定義每個 GiB 提供的 IOPS 數量。
- 例如,如果 type 為 io1 並且 iopsPerGB 設定為 10,則 100 GiB 的卷將提供 1000 IOPS。
-
iops (可選,僅當 type 為 io1 時有效)
- 直接定義卷的 IOPS 總數。例如,iops: "1000" 表示卷將提供 1000 IOPS。
-
throughput (可選,僅當 type 為 st1 時有效)
- 定義卷的吞吐量,以 MiB/s 為單位。例如,throughput: "500" 表示卷的吞吐量為 500 MiB/s。
-
encrypted (可選)
- 布林值,指示是否應該加密 EBS 卷。例如,encrypted: "true"。
-
kmsKeyId (可選)
- 指定用於加密 EBS 卷的 KMS 金鑰 ID。例如,kmsKeyId: "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"。
-
fsType (可選)
- 定義檔案系統型別。例如,fsType: "ext4"。
-
volumeSize (可選)
- 定義請求的卷大小(以 GiB 為單位)。例如,volumeSize: "100" 表示請求 100 GiB 的卷。
-
availabilityZone (可選)
- 定義 EBS 卷應該建立在哪個可用區。例如,availabilityZone: "us-west-2a"。
-
multiAttachEnabled (可選)
- 布林值,指示是否啟用多附加。例如,multiAttachEnabled: "true" 允許卷同時附加到多個例項。
-
snapshotId (可選)
- 定義用於建立 EBS 卷的快照 ID。例如,snapshotId: "snap-0123456789abcdef0"。
-
tags (可選)
-
定義一組鍵值對,用於標記 EBS 卷。例如:
-
tags: - key: "project" value: "myproject" - key: "owner" value: "myteam"
-
8、設定預設的 StorageClass(storageclass.kubernetes.io/is-default-class)
在建立 SC 的 YAML 檔案時,需要在 metadata 部分新增一個註解,以標記該 SC 為預設。
8.1、示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: low-latency
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: csi-driver.example-vendor.example
reclaimPolicy: Retain # 預設值是 Delete
allowVolumeExpansion: true
mountOptions:
- discard # 這可能會在塊儲存層啟用 UNMAP/TRIM
volumeBindingMode: WaitForFirstConsumer
parameters:
guaranteedReadWriteLatency: "true" # 這是服務提供商特定的
8.2、修改已有的 StorageClass
8.2.1、將存在的 SC 設定為預設
kubectl patch storageclass <sc-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
8.2.2、將存在的 SC 設定為非預設
kubectl patch storageclass <sc-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
如果你在叢集中的多個 StorageClass 上將 storageclass.kubernetes.io/is-default-class 註解設定為 true,然後建立一個未設定 storageClassName 的 PersistentVolumeClaim (PVC), Kubernetes 將使用最近建立的預設 StorageClass。
三、例項 -- 使用 NFS 型別的 StorageClass 動態建立 PV
角色 | 主機名 | ip地址 |
---|---|---|
nfs 服務端 + master 節點 | k8s-master1 | 192.168.112.10 |
nfs 客戶端 + node 節點 | k8s-node1 | 192.168.112.20 |
nfs 客戶端 + node 節點 | k8s-node2 | 192.168.112.30 |
1、配置 NFS 服務端
1.1、master 節點安裝 nfs-utils 包
yum install -y nfs-utils
1.2、master 節點建立共享目錄
mkdir -pv /data/nfs
1.3、編輯/etc/exports檔案
echo "/data/nfs 192.168.112.0/24(rw,sync,no_root_squash)" > /etc/exports
1.4、應用新的匯出設定
exportfs -arv
1.5、重啟並設定 NFS 開機自啟
systemctl restart nfs && systemctl enable nfs
1.6、檢查 NFS 共享
showmount -e localhost
2、配置 NFS 客戶端
所有 node 節點
2.1、安裝 nfs-utils 包
yum install -y nfs-utils
2.2、建立目錄掛載 NFS 共享
mkdir -pv /mnt/nfs
mount -t nfs 192.168.112.10:/data/nfs /mnt/nfs
2.2.1、解除安裝錯誤的掛載點
如果在執行 mount -t nfs
命令時出現了錯誤,比如使用了錯誤的引數或者路徑,你可以透過解除安裝當前的掛載點然後再重新掛載來修正錯誤。
-
確認當前的掛載狀態
-
使用
mount
命令檢視當前的所有掛載情況,找到錯誤掛載的條目。 -
mount
-
-
解除安裝錯誤的掛載點
-
# 知道錯誤的掛載點 sudo umount /mnt/nfs
-
# 知道 nfs 服務端 IP 地址和共享目錄路徑 sudo umount 192.168.112.10:/data/nfs
-
-
解除安裝時遇到裝置/檔案正在使用中
-
umount -f /mnt/nfs
-
強制解除安裝可能會導致資料丟失,因此只有在確定沒有資料寫入的情況下才這樣做。
-
2.3、重啟並設定 NFS 開機自啟
systemctl restart nfs && systemctl enable nfs
2.4、系統啟動自動掛載 NFS 共享(非必要)
echo '192.168.112.10:/data/nfs /mnt/nfs nfs defaults 0 0' >> /etc/fstab
2.5、檢視掛載狀態
mount | grep 192.168.112.10
3、建立儲存類
cat >> nfs-storage.yaml << EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
namespace: default
labels:
environment: test
provisioner: fuseim.pri/ifs
reclaimPolicy: Retain
volumeBindingMode: Immediate
EOF
kubectl apply -f nfs-storage.yaml
4、建立 RBAC 許可權
cat >> rbac.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f rbac.yaml
5、建立 provisioner
部署 NFS Client Provisioner,這是一個 Kubernetes 外部儲存外掛,用於動態建立 NFS PV。
cat >> nfs-provisioner.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs # 這裡必須要填寫storageclass中的PROVISIONER名稱資訊一致
- name: NFS_SERVER
value: 192.168.112.10 # 指定NFS伺服器的IP地址
- name: NFS_PATH
value: /data/nfs # 指定NFS伺服器中的共享掛載目錄
volumes:
- name: nfs-client-root # 定義持久化卷的名稱,必須要上面volumeMounts掛載的名稱一致
nfs:
server: 192.168.112.10 # 指定NFS所在的IP地址
path: /data/nfs # 指定NFS伺服器中的共享掛載目錄
EOF
kubectl apply -f nfs-provisioner.yaml
6、建立 PVC
cat >> nfs-pvc.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
namespace: default
labels:
environment: test
app: nginx
spec:
storageClassName: nfs-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Mi
EOF
kubectl apply -f nfs-pvc.yaml
7、觀察 PV 是否動態建立
kubectl get pvc,pv,sc
發現使用 NFS Client Provisioner 可以動態建立 pv 並與 PVC 繫結處於 Bound 狀態
8、建立使用同一 PVC 的多個 Pod
cat >> nfs-pod1.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: nfs-pod1
spec:
containers:
- name: container1
image: nginx:1.16.0
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
volumes:
- name: shared-data
persistentVolumeClaim:
claimName: nginx-pvc
EOF
cat >> nfs-pod2.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: nfs-pod2
spec:
containers:
- name: container2
image: nginx:1.16.0
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
volumes:
- name: shared-data
persistentVolumeClaim:
claimName: nginx-pvc
EOF
kubectl apply -f nfs-pod1.yaml -f nfs-pod2.yaml
9、向共享儲存寫入資料
kubectl exec -it nfs-pod1 -- /bin/bash
echo "hello from nfs-pod1" > /usr/share/nginx/html/index.html
exit
10、從另一個 Pod 讀取資料
kubectl exec -it nfs-pod2 -- /bin/bash
cat /usr/share/nginx/html/index.html
exit
11、檢視 nfs 服務端與客戶端的共享目錄
tree /data/nfs
tree /mnt/nfs
這個新出現的目錄(PV 目錄) default-nginx-pvc-pvc-c8a8b825-1577-4f76-ba1f-a1302941b333 用於對映 PersistentVolume (PV) 到 NFS 伺服器上的具體路徑
11.1、PV 目錄建立的流程
- 建立 PVC:
- 當你建立 PVC 時,Kubernetes 會根據 StorageClass 自動建立 PV。
- Provisioner 建立 PV:
- Provisioner 會在 NFS 伺服器上的共享目錄下建立一個新目錄,目錄名稱包含了 PVC 的名稱和 UUID。
- 掛載到 Pod:
- 建立的 PV 會被掛載到 Pod 中指定的路徑。
11.2、PV 目錄的結構
/<共享目錄>/<名稱空間>-<PVC名稱>-<PV名稱>
- 共享目錄:
- 這是你在 NFS 伺服器上建立並共享出去的目錄,比如 nfs 服務端的 /data/nfs 以及 nfs 客戶端的 /mnt/nfs
- 名稱空間:
- 這是 Kubernetes 中的一個邏輯分組,用於隔離不同的應用程式和服務。PVC 所屬的名稱空間名稱。
- PVC 名稱:
- 這是在 Kubernetes 中建立的 PersistentVolumeClaim 的名稱。
- PV 名稱:
- 這是根據 PVC 動態建立出來的 PersistentVolume 的名稱,通常是一個帶有 UUID 的字串。
kubectl get pvc nginx-pvc -o custom-columns='PVC-NAMESPACE:.metadata.namespace,PVC-NAME:.metadata.name'
kubectl get pv pvc-c8a8b825-1577-4f76-ba1f-a1302941b333 -o custom-columns='PV-NAME:.metadata.name'
12、修改 NFS 伺服器共享目錄內容檢視容器內部變化
可以發現也是同步更新的
cd /data/nfs/default-nginx-pvc-pvc-c8a8b825-1577-4f76-ba1f-a1302941b333
echo "hello from nfs-server" > index.html
kubectl get pods -o wide
curl 10.244.1.3
curl 10.244.2.8
四、例項 -- 動態建立 PVC 和 PV
1、建立 Headless Service
cat >> nginx-headless.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: nginx-headless
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
EOF
kubectl apply -f nginx-headless.yaml
kubectl get svc -l app=nginx -o wide
2、建立 StatefulSet
cat >> sts.yaml << EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 5
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.0
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates: # 透過模板化方式繫結
- metadata:
name: www # 指定pvc的名字
annotations:
volume.beta.kubernetes.io/storage-class: "nfs-storage" # 只指定了storageClass
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Mi
EOF
kubectl apply -f sts.yaml
3、觀察 Pod狀態
由於是 statefulset 控制器所以 pod 是按順序建立的
kubectl get pods -l app=nginx -w
4、觀察到 PVC 與 PV 已經動態建立並相互繫結了
kubectl get pvc -l 'app=nginx,environment!=test'
kubectl get pv | grep -v "default/nginx-pvc"
5、每一個 Pod 都會透過繫結 PVC 獲取一塊獨立的 PV
kubectl get pod web-0 -o custom-columns='PVC-NAME:.spec.volumes[*].persistentVolumeClaim.claimName'
kubectl get pod web-1 -o custom-columns='PVC-NAME:.spec.volumes[*].persistentVolumeClaim.claimName'
kubectl get pod web-2 -o custom-columns='PVC-NAME:.spec.volumes[*].persistentVolumeClaim.claimName'
kubectl get pod web-3 -o custom-columns='PVC-NAME:.spec.volumes[*].persistentVolumeClaim.claimName'
kubectl get pod web-4 -o custom-columns='PVC-NAME:.spec.volumes[*].persistentVolumeClaim.claimName'