Kubernetes 3種存儲傻傻分不清楚!
Kubernetes支持幾十種類型的后端存儲卷,其中有幾種存儲卷總是給人一種分不清楚它們之間有什么區別的感覺,尤其是local與hostPath這兩種存儲卷類型,看上去都像是node本地存儲方案嘛。當然,還另有一種volume類型是emptyDir,也有相近之處。
在Docker容器時代,我們就對Volume很熟悉了,一般來說我們是通過創建Volume數據卷,然后掛載到指定容器的指定路徑下,以實現容器數據的持久化存儲或者是多容器間的數據共享,當然這里說的都是單機版的容器解決方案。
進入到容器集群時代后,我們看到Kubernetes按時間順序先后提供了emptyDir、hostPath和local的本地磁盤存儲卷解決方案。
emptyDir、hostPath都是Kubernetes很早就實現和支持了的技術,local volume方式則是從k8s v1.7才剛剛發布的alpha版本,目前在k8s v1.10中發布了local volume的beta版本,部分功能在早期版本中并不支持。
在展開之前,我們先討論一個問題,就是既然都已經實現容器云平臺了,我們為什么還要關注這幾款本地存儲卷的貨呢?
粗略歸納了下,有以下幾個原因:
- 特殊使用場景需求,如需要個臨時存儲空間,運行cAdvisor需要能訪問到node節點/sys/fs/cgroup的數據,做本機單節點的k8s環境功能測試等等。
- 容器集群只是做小規模部署,滿足開發測試、集成測試需求。
- 作為分布式存儲服務的一種補充手段,比如我在一臺node主機上插了塊SSD,準備給某個容器吃小灶。
- 目前主流的兩個容器集群存儲解決方案是ceph和glusterfs,二者都是典型的網絡分布式存儲,所有的數據讀、寫都是對磁盤IO和網絡IO的考驗,所以部署存儲集群時至少要使用萬兆的光纖網卡和光纖交換機。如果你都沒有這些硬貨的話,強上分布式存儲方案的結果就是收獲一個以”慢動作”見長的容器集群啦。
- 分布式存儲集群服務的規劃、部署和長期的監控、擴容與運行維護是專業性很強的工作,需要有專職的技術人員做長期的技術建設投入。
我們并不是說分布式存儲服務不好,很多公司在云平臺建設的實踐中,往往是需要結合使用幾種通用的與專用的存儲解決方案,才能最終滿足大部分的使用需求。
所以,如果這里有一款場景適合你的話,不妨了解一下這幾款本地存儲卷的功能特點、使用技巧與異同。
1、emptyDir
emptyDir類型的Volume在Pod分配到Node上時被創建,Kubernetes會在Node上自動分配一個目錄,因此無需指定宿主機Node上對應的目錄文件。 這個目錄的初始內容為空,當Pod從Node上移除時,emptyDir中的數據會被***刪除。
注:容器的crashing事件并不會導致emptyDir中的數據被刪除。
***實踐
根據官方給出的***使用實踐的建議,emptyDir可以在以下幾種場景下使用:
- apiVersion: v1
- kind: Pod
- metadata:
- name: test-pod
- spec:
- containers:
- - image: busybox
- name: test-emptydir
- command: [ "sleep", "3600" ]
- volumeMounts:
- - mountPath: /data
- name: data-volume
- volumes:
- - name: data-volume
- emptyDir: {}
查看下創建出來的pod,這里只截取了與volume有關的部分,其他無關內容直接省略:
- # kubectl describe pod test-pod
- Name: test-pod
- Namespace: default
- Node: kube-node2/172.16.10.102
- ......
- Environment: <none>
- Mounts:
- /data from data-volume (rw)
- ......
- Volumes:
- data-volume:
- Type: EmptyDir (a temporary directory that shares a pod's lifetime)
- Medium:
- ......
可以進入到容器中查看下實際的卷掛載結果:
- # kubectl exec -it test-pod -c test-emptydir /bin/sh
2、hostPath
hostPath類型則是映射node文件系統中的文件或者目錄到pod里。在使用hostPath類型的存儲卷時,也可以設置type字段,支持的類型有文件、目錄、File、Socket、CharDevice和BlockDevice。
下面是來自官網對hostPath的使用場景和注意事項的介紹。
使用場景:
- 當運行的容器需要訪問Docker內部結構時,如使用hostPath映射/var/lib/docker到容器;
- 當在容器中運行cAdvisor時,可以使用hostPath映射/dev/cgroups到容器中;
- 注意事項:
- 配置相同的pod(如通過podTemplate創建),可能在不同的Node上表現不同,因為不同節點上映射的文件內容不同
- 當Kubernetes增加了資源敏感的調度程序,hostPath使用的資源不會被計算在內
- 宿主機下創建的目錄只有root有寫權限。你需要讓你的程序運行在privileged container上,或者修改宿主機上的文件權限。
hostPath volume 實驗
下面我們在測試k8s環境中創建一個hostPath volume使用示例。
- apiVersion: v1
- kind: Pod
- metadata:
- name: test-pod2
- spec:
- containers:
- - image: busybox
- name: test-hostpath
- command: [ "sleep", "3600" ]
- volumeMounts:
- - mountPath: /test-data
- name: test-volume
- volumes:
- - name: test-volume
- hostPath:
- # directory location on host
- path: /data
- # this field is optional
- type: Directory
查看下pod創建結果,觀察volumes部分:
- # kubectl describe pod test-pod2
- Name: test-pod2
- Namespace: default
- Node: kube-node2/172.16.10.102
- ......
- Mounts:
- /test-data from test-volume (rw)
- ......
- Volumes:
- test-volume:
- Type: HostPath (bare host directory volume)
- Path: /data
- HostPathType: Directory
- ......
我們登錄到容器中,進入掛載的/test-data目錄中,創建個測試文件。
- # kubectl exec -it test-pod2 -c test-hostpath /bin/sh
- / # echo 'testtesttest' > /test-data/test.log
- / # exit
我們在運行該pod的node節點上,可以看到如下的文件和內容。
- [root@kube-node2 test-data]# cat /test-data/test.log
- testtesttest
現在,我們把該pod刪除掉,再看看node節點上的hostPath使用的目錄與數據會有什么變化。
- [root@kube-node1 ~]# kubectl delete pod test-pod2
- pod "test-pod2" deleted
到運行原pod的node節點上查看如下。
- [root@kube-node2 test-data]# ls -l
- total 4
- -rw-r--r-- 1 root root 13 Nov 14 00:25 test.log
- [root@kube-node2 test-data]# cat /test-data/test.log
- testtesttest
在使用hostPath volume卷時,即便pod已經被刪除了,volume卷中的數據還在!
單節點的k8s本地測試環境與hostPath volume
有時我們需要搭建一個單節點的k8s測試環境,就利用到hostPath作為后端的存儲卷,模擬真實環境提供PV、StorageClass和PVC的管理功能支持。
- apiVersion: storage.k8s.io/v1
- kind: StorageClass
- metadata:
- namespace: kube-system
- name: standard
- annotations:
- storageclass.beta.kubernetes.io/is-default-class: "true"
- labels:
- addonmanager.kubernetes.io/mode: Reconcile
- provisioner: kubernetes.io/host-path
-
該場景僅能用于單節點的k8s測試環境中
3、emptyDir和hostPath在功能上的異同分析
二者都是node節點的本地存儲卷方式;
- emptyDir可以選擇把數據存到tmpfs類型的本地文件系統中去,hostPath并不支持這一點;
- hostPath除了支持掛載目錄外,還支持File、Socket、CharDevice和BlockDevice,既支持把已有的文件和目錄掛載到容器中,也提供了“如果文件或目錄不存在,就創建一個”的功能;
- emptyDir是臨時存儲空間,完全不提供持久化支持;
- hostPath的卷數據是持久化在node節點的文件系統中的,即便pod已經被刪除了,volume卷中的數據還會留存在node節點上;
4、local volume的概念
這是一個很新的存儲類型,建議在k8s v1.10+以上的版本中使用。該local volume類型目前還只是beta版。
Local volume 允許用戶通過標準PVC接口以簡單且可移植的方式訪問node節點的本地存儲。 PV的定義中需要包含描述節點親和性的信息,k8s系統則使用該信息將容器調度到正確的node節點。
配置要求
- 使用local-volume插件時,要求使用到了存儲設備名或路徑都相對固定,不會隨著系統重啟或增加、減少磁盤而發生變化。
- 靜態provisioner配置程序僅支持發現和管理掛載點(對于Filesystem模式存儲卷)或符號鏈接(對于塊設備模式存儲卷)。 對于基于本地目錄的存儲卷,必須將它們通過bind-mounted的方式綁定到發現目錄中。
StorageClass與延遲綁定
官方推薦在使用local volumes時,創建一個StorageClass并把volumeBindingMode字段設置為“WaitForFirstConsumer”。
雖然local volumes還不支持動態的provisioning管理功能,但我們仍然可以創建一個StorageClass并使用延遲卷綁定的功能,將volume binding延遲至pod scheduling階段執行。
這樣可以確保PersistentVolumeClaim綁定策略將Pod可能具有的任何其他node節點約束也進行評估,例如節點資源要求、節點選擇器、Pod親和性和Pod反親和性。
- kind: StorageClass
- apiVersion: storage.k8s.io/v1
- metadata:
- name: local-storage
- provisioner: kubernetes.io/no-provisioner
- volumeBindingMode: WaitForFirstConsumer
外部static provisioner
配置local volume后,可以使用一個外部的靜態配置器來幫助簡化本地存儲的管理。 Provisioner 配置程序將通過為每個卷創建和清理PersistentVolumes來管理發現目錄下的卷。
Local storage provisioner要求管理員在每個節點上預配置好local volumes,并指明該local volume是屬于以下哪種類型:
- Filesystem volumeMode (default) PVs – 需要掛載到發現目錄下面。
- Block volumeMode PVs – 需要在發現目錄下創建一個指向節點上的塊設備的符號鏈接。
一個local volume,可以是掛載到node本地的磁盤、磁盤分區或目錄。
Local volumes雖然可以支持創建靜態PersistentVolume,但到目前為止仍不支持動態的PV資源管理。
這意味著,你需要自己手動去處理部分PV管理的工作,但考慮到至少省去了在創建pod時手動定義和使用PV的工作,這個功能還是很值得的。
創建基于Local volumes的PV的示例
- 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
-
- nodeAffinity字段是必須配置的,k8s依賴于這個標簽為你定義的Pods在正確的nodes節點上找到需要使用的local volumes。
- 使用volumeMode字段時,需要啟用BlockVolume 這一Alpha feature特性。
- volumeMode字段的默認值是Filesystem,但也支持配置為Block,這樣就會把node節點的local volume作為容器的一個裸塊設備掛載使用。
數據安全風險
local volume仍受node節點可用性方面的限制,因此并不適用于所有應用程序。 如果node節點變得不健康,則local volume也將變得不可訪問,使用這個local volume的Pod也將無法運行。 使用local voluems的應用程序必須能夠容忍這種降低的可用性以及潛在的數據丟失,是否會真得導致這個后果將取決于node節點底層磁盤存儲與數據保護的具體實現了。
5、hostPath與local volume在功能上的異同分析
二者都基于node節點本地存儲資源實現了容器內數據的持久化功能,都為某些特殊場景下提供了更為適用的存儲解決方案;
前者時間很久了,所以功能穩定,而后者因為年輕,所以功能的可靠性與穩定性還需要經歷時間和案例的歷練,尤其是對Block設備的支持還只是alpha版本;
二者都為k8s存儲管理提供了PV、PVC和StorageClass的方法實現;
- local volume實現的StorageClass不具備完整功能,目前只支持卷的延遲綁定;
- hostPath是單節點的本地存儲卷方案,不提供任何基于node節點親和性的pod調度管理支持;
- local volume適用于小規模的、多節點的k8s開發或測試環境,尤其是在不具備一套安全、可靠且性能有保證的存儲集群服務時;
6、local volume的安裝配置方法
local-volume項目及地址
https://github.com/kubernetes-incubator/external-storage/tree/master/local-volume
Step 1:配置k8s集群使用本地磁盤存儲
如果使用block塊設備,則需要啟用Alpha的功能特性:k8s v1.10+
- $ export KUBE_FEATURE_GATES=”BlockVolume=true”
注:如果是已經部署好的k8s v1.10+集群,需要為幾個主要組件均開啟對該特性的支持后,才能使用block塊設備功能。如果k8s是低于1.10版本,則還需要啟用其它的幾個功能特性,因為在低版本中這些功能特性還都是alpha版本的。
根據大家搭建k8s的方法的不同,下面提供了四種情況下的配置說明。
- Option 1: GCE(Google Compute Engine)集群
使用kube-up.sh啟動的GCE集群將自動格式化并掛載所請求的Local SSDs,因此您可以使用預先生成的部署規范部署配置器并跳至步驟4,除非您要自定義配置器規范或存儲類。
- $ NODE_LOCAL_SSDS_EXT=<n>,<scsi|nvme>,fs cluster/kube-up.sh
- $ kubectl create -f provisioner/deployment/kubernetes/gce/class-local-ssds.yaml
- $ kubectl create -f provisioner/deployment/kubernetes/gce/provisioner_generated_gce_ssd_volumes.yaml
Option 2: GKE(Google Kubernetes Engine)集群
GKE集群將自動格式化并掛載所請求的Local SSDs。在GKE documentation中有更詳細的說明。
然后,跳至步驟4。
Option 3: 使用裸機環境搭建的集群
1.根據應用程序的使用要求對每個節點上的本地數據磁盤進行分區和格式化。 2.定義一個StorageClass,并在一個發現目錄下掛載所有要使用的存儲文件系統。 發現目錄是在configmap中指定,見下文。 3.如上所述,使用KUBEFEATUREGATES配置Kubernetes API Server, controller-manager, scheduler, 和所有節點上的 kubelets。 4.如果沒有使用默認的Kubernetes調度程序策略,則必須啟用以下特性:
- Pre-1.9: NoVolumeBindConflict
- 9+: VolumeBindingChecker
說明:在我們使用測試環境中,是一套3節點的k8s測試環境,為了模擬測試local volume功能,直接結合使用了下面option4中提供的ram disks測試方法,創建了3個tmpfs格式的文件系統掛載資源。
Option 4: 使用一個本機單節點的測試集群
創建/mnt/disks目錄,并在該目錄下掛載幾個子目錄。下面是使用三個ram disks做一個真實存儲卷的模擬測試。
- $ mkdir /mnt/fast-disks
- $ for vol in vol1 vol2 vol3;
- do
- mkdir -p /mnt/fast-disks/$vol
- mount -t tmpfs $vol /mnt/fast-disks/$vol
- done
(2)創建單機k8s本地測試集群
- $ ALLOW_PRIVILEGED=true LOG_LEVEL=5 FEATURE_GATES=$KUBE_FEATURE_GATES hack/local-up-cluster.sh
Step 2: 創建一個StorageClass (1.9+)
要延遲卷綁定直到pod調度并處理單個pod中的多個本地PV,必須創建StorageClass并將volumeBindingMode設置為WaitForFirstConsumer。
- # Only create this for K8s 1.9+
- apiVersion: storage.k8s.io/v1
- kind: StorageClass
- metadata:
- name: fast-disks
- provisioner: kubernetes.io/no-provisioner
- volumeBindingMode: WaitForFirstConsumer
- # Supported policies: Delete, Retain
- reclaimPolicy: Delete
- $ kubectl create -f provisioner/deployment/kubernetes/example/default_example_storageclass.yaml
-
yaml文件請到local volume項目文件中查找需要使用的yaml文件
Step 3: 創建local persistent volumes
Option 1: local volume static provisioner 方式
配置一個外部的靜態配置器。
(1)生成Provisioner的ServiceAccount,Roles,DaemonSet和ConfigMap規范,并對其進行自定義配置。
此步驟使用helm模板生成需要的配置規格。 有關設置說明,請參閱helm README。
使用默認值生成Provisioner的配置規格,請運行:
helm template ./helm/provisioner > ./provisioner/deployment/kubernetes/provisioner_generated.yaml
這里是將模板經過渲染后得到最終使用的各項資源定義文件。 如果是使用自定義的配置文件的話:
- helm template ./helm/provisioner --values custom-values.yaml > ./provisioner/deployment/kubernetes/provisioner_generated.yaml
(2)部署Provisioner
如果用戶對Provisioner的yaml文件的內容感到滿意,就可以使用kubectl創建Provisioner的DaemonSet和ConfigMap了。
- # kubectl create -f ./provisioner/deployment/kubernetes/provisioner_generated.yaml
- configmap "local-provisioner-config" created
- daemonset.extensions "local-volume-provisioner" created
- serviceaccount "local-storage-admin" created
- clusterrolebinding.rbac.authorization.k8s.io "local-storage-provisioner-pv-binding" created
- clusterrole.rbac.authorization.k8s.io "local-storage-provisioner-node-clusterrole" created
- clusterrolebinding.rbac.authorization.k8s.io "local-storage-provisioner-node-binding" created
(3)檢查已自動發現的local volumes
一旦啟動,外部static provisioner將發現并自動創建出 local-volume PVs。
我們查看下上面測試中創建出的PVs有哪些:
- # kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- local-pv-436f0527 495Mi RWO Delete Available fast-disks 2m
- local-pv-77a4ffb0 495Mi RWO Delete Available fast-disks 2m
- local-pv-97f7ec5c 495Mi RWO Delete Available fast-disks 2m
- local-pv-9f0ddba3 495Mi RWO Delete Available fast-disks 2m
- local-pv-a0dfdc91 495Mi RWO Delete Available fast-disks 2m
- local-pv-a52333e3 495Mi RWO Delete Available fast-disks 2m
- local-pv-bed86926 495Mi RWO Delete Available fast-disks 2m
- local-pv-d037a0d1 495Mi RWO Delete Available fast-disks 2m
- local-pv-d26c3252 495Mi RWO Delete Available fast-disks 2m
-
因為是有3個node節點,每個上面的/mnt/fast-disks自動發現目錄下掛載了3個文件系統,所以這里查詢的結果是生成了9個PVs
查看某一個PV的詳細描述信息:
- # kubectl describe pv local-pv-436f0527
- Name: local-pv-436f0527
- Labels: <none>
- Annotations: pv.kubernetes.io/provisioned-by=local-volume-provisioner-kube-node2-c3733876-b56f-11e8-990b-080027395360
- Finalizers: [kubernetes.io/pv-protection]
- StorageClass: fast-disks
- Status: Available
- Claim:
- Reclaim Policy: Delete
- Access Modes: RWO
- Capacity: 495Mi
- Node Affinity:
- Required Terms:
- Term 0: kubernetes.io/hostname in [kube-node2]
- Message:
- Source:
- Type: LocalVolume (a persistent volume backed by local storage on a node)
- Path: /mnt/fast-disks/vol2
- Events: <none>
-
此時就可以直接通過引用名為fast-disks的storageClassName名稱來聲明使用上述PV并將其綁定到PVC。
Option 2: 手動創建 local persistent volume
參照前文介紹local volume概念的章節中已經講解過的PersistentVolume使用示例。
Step 4: 創建 local persistent volume claim
- kind: PersistentVolumeClaim
- apiVersion: v1
- metadata:
- name: example-local-claim
- spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 50Mi
- storageClassName: fast-disks
-
請在使用時替換為您實際的存儲容量需求和storageClassName值。
- # kubectl create -f local-pvc.yaml
- persistentvolumeclaim "example-local-claim" created
- # kubectl get pvc
- NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
- example-local-claim Pending
- # kubectl describe pvc example-local-claim
- Name: example-local-claim
- Namespace: default
- StorageClass: fast-disks
- Status: Pending
- Volume:
- Labels: <none>
- Annotations: <none>
- Finalizers: [kubernetes.io/pvc-protection]
- Capacity:
- Access Modes:
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
-
Normal WaitForFirstConsumer 6s (x6 over 59s) persistentvolume-controller waiting for first consumer to be created before binding
我們可以看到存儲卷延遲綁定的效果,在綁定到容器前,該PVC的狀態會是pending
Step 5:創建一個測試Pod并引用上面創建的PVC
- apiVersion: v1
- kind: Pod
- metadata:
- name: local-pvc-pod
- spec:
- containers:
- - image: busybox
- name: test-local-pvc
- command: [ "sleep", "3600" ]
- volumeMounts:
- - mountPath: /data
- name: data-volume
- volumes:
- - name: data-volume
- persistentVolumeClaim:
- claimName: example-local-claim
-
創建并查看:
- # kubectl create -f example-local-pvc-pod.yaml
- pod "local-pvc-pod" created
- # kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- client1 1/1 Running 67 64d 172.30.80.2 kube-node3
- local-pvc-pod 1/1 Running 0 2m 172.30.48.6 kube-node1
-
查看pod中容器掛載PVC的配置詳情,這里只截取了部分信息:
- # kubectl describe pod local-pvc-pod
- Name: local-pvc-pod
- Namespace: default
- Node: kube-node1/172.16.10.101
- Start Time: Thu, 15 Nov 2018 16:39:30 +0800
- Labels: <none>
- Annotations: <none>
- Status: Running
- IP: 172.30.48.6
- Containers:
- test-local-pvc:
- ......
- Mounts:
- /data from data-volume (rw)
- /var/run/secrets/kubernetes.io/serviceaccount from default-token-qkhcf (ro)
- Conditions:
- Type Status
- Initialized True
- Ready True
- PodScheduled True
- Volumes:
- data-volume:
- Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
- ClaimName: example-local-claim
- ReadOnly: false
- ......
- [root@kube-node1 ~]# kubectl exec -it local-pvc-pod -c test-local-pvc /bin/sh
- / # ls
- bin data dev etc home proc root sys tmp usr var
- / # df -h
- Filesystem Size Used Available Use% Mounted on
- overlay 41.0G 8.1G 32.8G 20% /
- tmpfs 64.0M 0 64.0M 0% /dev
- tmpfs 495.8M 0 495.8M 0% /sys/fs/cgroup
- vol3 495.8M 0 495.8M 0% /data
-
再回過頭來看下PVC的狀態,已經變成了Bound:
- # kubectl get pvc
- NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
- example-local-claim Bound local-pv-a0dfdc91 495Mi RWO fast-disks 1h
-
7、一個關于local volume功能局限性問題的討論
在上面的實驗過程中不知道大家有沒有發現一處問題,就是我們在定義PVC時是指定的申請50Mi的空間,而實際掛載到測試容器上的存儲空間是495.8M,剛好是我們在某個node節點上掛載的一個文件系統的全部空間。
為什么會這樣呢?這就是我們所使用的這個local persistent volume外部靜態配置器的功能局限性所在了。它不支持動態的PV空間申請管理。
也就是說,雖然通過這個靜態PV配置器,我們省去了手寫PV YAML文件的痛苦,但仍然需要手工處理這項工作:
- 手工維護在ConfigMap中指定的自動發現目錄下掛載的文件系統資源,或者是block設備的符號鏈接;
- 我們需要對能夠使用的本地存儲資源提前做一個全局的規劃,然后劃分為各種尺寸的卷后掛載到自動發現目錄下,當然了只要是還有空閑存儲資源,現有現掛載也是可以的。
那如果以前給某容器分配的一個存儲空間不夠用了怎么辦?
給大家的一個建議是使用Linux下的LVM(邏輯分區管理)來管理每個node節點上的本地磁盤存儲空間。
- 創建一個大的VG分組,把一個node節點上可以使用的存儲空間都放進去;
- 按未來一段時間內的容器存儲空間使用預期,提前批量創建出一部分邏輯卷LVs,都掛載到自動發現目錄下去;
- 不要把VG中的存儲資源全部用盡,預留少部分用于未來給個別容器擴容存儲空間的資源;
- 使用lvextend為特定容器使用的存儲卷進行擴容;
8、如果容器需要使用block塊設備怎么配置
有幾點會與上面的配置方法上不同。
首先,是要在k8s主要的組件上均開啟用于支持block塊設備的特性。
- KUBE_FEATURE_GATES="BlockVolume=true"
其次是,定義一個”Block”類型的volumeMode PVC,為容器申請一個”Block”類型的PV。
- kind: PersistentVolumeClaim
- apiVersion: v1
- metadata:
- name: example-block-local-claim
- spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 50Mi
- volumeMode: Block
- storageClassName: fast-disks
-
9、Local volumes的***實踐
- 為了更好的IO隔離效果,建議將一整塊磁盤作為一個存儲卷使用;
- 為了得到存儲空間的隔離,建議為每個存儲卷使用一個獨立的磁盤分區;
- 在仍然存在指定了某個node節點的親和性關系的舊PV時,要避免重新創建具有相同節點名稱的node節點。 否則,系統可能會認為新節點包含舊的PV。
- 對于具有文件系統的存儲卷,建議在fstab條目和該卷的mount安裝點的目錄名中使用它們的UUID(例如ls -l /dev/disk/by-uuid的輸出)。 這種做法可確保不會安裝錯誤的本地卷,即使其設備路徑發生了更改(例如,如果/dev/sda1在添加新磁盤時變為/dev/sdb1)。 此外,這種做法將確保如果創建了具有相同名稱的另一個節點時,該節點上的任何卷仍然都會是唯一的,而不會被誤認為是具有相同名稱的另一個節點上的卷。
- 對于沒有文件系統的原始塊存儲卷,請使用其唯一ID作為符號鏈接的名稱。 根據您的環境,/dev/disk/by-id/中的卷ID可能包含唯一的硬件序列號。 否則,應自行生成一個唯一ID。 符號鏈接名稱的唯一性將確保如果創建了另一個具有相同名稱的節點,則該節點上的任何卷都仍然是唯一的,而不會被誤認為是具有相同名稱的另一個節點上的卷。
10、停用local volume的方法
當您想要停用本地卷時,這是一個可能的工作流程。
- 關閉使用這些卷的Pods;
- 從node節點上移除local volumes(比如unmounting, 拔出磁盤等等);
- 手動刪除相應的PVCs對象;
- Provisioner將嘗試清理卷,但會由于卷不再存在而失敗;
- 手動刪除相應的PVs對象。 注:以上工作也是拜我們所使用的外部靜態配置器所賜。
參考資料:
https://blog.csdn.net/watermelonbig/article/details/84108424
https://github.com/kubernetes-incubator/external-storage/tree/master/local-volume https://kubernetes.io/docs/concepts/storage/volumes/