這篇主要說明什麼時間點會需要使用local persistent volume並搭配local storageclass的文章紀錄
假如對kubernetes針對資料保存的機制 (Persistent Volume, Persistent Volume Mount, 以及StorageClass) 尚未接觸的讀者們,可以先參考我之前的筆記
Kubernetes - Storage 學習紀錄
先談談 StorageClass volumeBindingMode的兩種模式 WaitForFirstConsumer
& Immediate
我想大部分的人都是在學習k8的階段,了解到怎麼建立一個persistent volume,然後掛上本地的目錄並提供給PersistentVolumeClaim (PVC) 使用。
除了掛載給PVC之外,K8s admin也可以預先開好數個persistent volume,然後提供給配置provisioner
為 WaitForFirstConsumer
的StorageClass使用
1 | apiVersion: storage.k8s.io/v1 |
然後就是這裡,直接給他套用上去
但 volumeBindingMode: WaitForFirstConsumer
是什麼用法???
WaitForFirstConsumer的consumer,指的是Pod!
直到有Pod被安排到特定的K8s node上,確定好位置後,StorageClass才會將PV分配給Pod所綁定的PVC囉
那另外一種Mode為 Immediate
也是Default的行為,就是不用等到Pod被Scheduler調度完成,即把PVC與PV給綁定。
為何要使用StorageClass WaitForFirstConsumer啊???
直接先開門見山回答問題,如果你有Pod有存取特定節點上的特殊目錄的需求,那就得使用WaitForFirstConsumer啊???
因為當你的Pod必須要先跑在指定的Worker Node的位置,也就是等Pod被調度完成後,StorageClass才能夠分配Persistent Volume給Pod。
見了山,再見林,配個使用情境快速了解:
當你有一座Elasticsearch集群時,你看了他們的官方說明,被建議使用Local PersistentVolumes來達到讀寫都是在本地端達成,而不須經過頻寬傳輸 (例如使用Network Storage (NFS))而多產生傳輸延遲
於是乎,額外產了幾台worker node專門給Elasticsearch使用,這時StorageClass的volumeBindingMode就得使用 WaitForFirstConsumer
,先讓Pod跑在Elasticsearch專屬的位置,然後才分配PV給他,Elastic官方也是建議使用這種行為。
因為當使用了Local PV,其使用的空間為Worker node上面的filesystem.所以必須得等到Pod順順利利的放到指定的Worker node上面,才能夠把PV給Pod這樣。
這邊補充一下,PV也可以限制被哪些Node上的Pod存取,可透過nodeAffinity達成
使用local persistent volume潛在問題與解方
當只有使用Local Persistent Volumes與Local StorageClass
必須要事先將Local Persistent Volumes建立起來,並且註冊給StorageClass
但當Pod被刪除,PVC也跟著被移除後,那對應的Persistent Volume會如何??
答案是:Persistent Volume只會認得之前被移除的PVC!!!除非要對他做一些更改否則
透過以下範例來說明:
創建 volumeBindingMode: WaitForFirstConsumer
的StorageClass local-storage
1 | kind: StorageClass |
1 | $ kubectl create -f sc.yaml |
創建PV,並指定給StorageClass local-storage
1 | apiVersion: v1 |
1 | $ kubectl create -f pv.yaml |
創建PVC,向StorageClass要求PV分配
1 | kind: PersistentVolumeClaim |
這時可以看到,PVC pending中,尚未被分配,因為的StorageClass設置WaitForFirstConsumer
,故要等待Pod被kube-scheduler分配到worker nodes上,SC才會將PV與PVC做綁定
1 | $ kubectl get pvc |
開一個pod掛載
1 | kind: Pod |
記得使用local persistent volume時,Pod所在的worker node,mount的掛載目錄要確保存在,否則Pod會卡在ContainerCreating,並冒出
MountVolume.NewMounter initialization failed for volume "local-pv-1" : path "/mnt/disks/local-pv-1" does not exist
Event log
1 | $ kubectl get pods |
1 | $ kubectl get pods -owide |
這時查看PVC狀態,已經Bound成功
1 | $ kubectl get pvc |
PV也已經被StorageClass local-storage
分配給PVC
1 | $ kubectl get pv |
砍掉Pod與PVC,那PV會變成怎樣????
先觀察一下PVC內容,會有個uid
資訊
1 | apiVersion: v1 |
然後我們再把PVC給砍了,並查看一下PV的狀態為Release
1 | $ kubectl delete -f pvc.yaml |
那我們想要再重新綁定PV給重新創建的PVC,會發生什麼事呢??
會發現怎沒辦法重新綁定,Pod呈現Pending狀態
1 | $ kubectl create -f pvc.yaml |
查看Pod的Event log會看到 1 node(s) didn't find available persistent volumes to bind
,原因是因為原本的Persistent Volume因為是使用local volume mount的手動創建的機制,他所綁定的PVC還停留在上一個刪除pvc name,可以透過uid辨識出是上一個刪除的pvc…
請用 kubectl edit pv
查看,才能看到pv綁定的pvc uid資訊在 claimRef
之下
1 | $ kubectl edit pv |
這時需要清除PV的claimRef內容,才能夠讓Pod的PVC重新綁定到PV
1 | kubectl patch pv local-pv-1 -p '{"spec":{"claimRef": null}}' |
以上的動作都可以至 KillerKoda提供免費的playground操作囉
其實可以看到若使用local persistent volume會產生不少operation的活,這時K8 admin就會很想哭,所以就可以透過 Local Persistence Volume Static Provisioner 來自動化產生PV所需的mount目錄,以及管理PV與PVC綁定的關係和PV的生命週期
小結
- 什麼情況使用
WaitForFirstConsumer
A: Pod跑在指定的Node上,且存取指定Node上特定的目錄空間 (由local PV掛載而存取到)
- Local PV為何沒辦法重新綁定給重新產生的PVC
A: 請將PV的ClaimRef所聲明的PVC對象資訊給清除掉
- 要如何改善使用Local Persistent Volume??
A: 可以考慮使用 Local Persistence Volume Static Provisioner
Reference
StorageClass volumeBindingMode
https://kubernetes.io/docs/concepts/storage/storage-classes/#local
Local Persistence Volume Static Provisioner
https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner
文章版權聲明:請勿抄襲,本部落格採用創用CC, 姓名標示-非商業性-相同方式分享授權
欲轉載請標註出處與作者-Kubeguts 庫柏格,thanks!