K8s 的數據卷volume


K8s 的數據卷volume

Volume

 容器磁盤上的文件的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題。首先,當容器崩潰時,kubelet會重啟它,但是容器中的文件將丟失——容器以干凈點狀態(鏡像最初點狀態)重新啟動。其次,在pod中同時運行多個容器時,這些容器之間通常需要共享文件。Kubernetes中的volume就能很好的解決了這些問題。

背景

Docker中也有一個volume的概念,盡管它稍微寬松一些,管理也很少。在Docker中,卷就像是磁盤或是另一個容器中的一個目錄。它的生命周期不受管理,直到最近才有了local-disk-backed卷。Docker現在提供來卷驅動程序,但是功能還非常有限(例如Docker1.7只允許每個容器使用一個卷驅動,並且無法給卷傳遞參數)。

另一方面,Kubernetes中的卷有明確的壽命——與封裝他的Pod相同。所以,卷的生命比Pod中點所有容器都長,當這個容器重啟時數據仍然得以保存。當然,當pod不再存在時,卷也將不復存在。也許更重要點的是,Kubernetes支持多種類型的卷,Pod可以同時使用任意數量的卷。

卷的核心是目錄,可能還包含了一些數據,可以通過pod中的容器來訪問。該目錄是如何形成的、支持該目錄的介質以及內容取決於所使用的特定卷類型。

要使用卷,需要為pod指定為卷(spec.volumes 字段)以及將它掛載到容器的位置(spec.containers.volumeMounts 字段)。

容器中的進程看到的是其由Docker鏡像和卷組成點文件系統視圖。Docker鏡像位於文件系統層次結構的根目錄,任何卷都被掛載在鏡像的指定路徑中。卷無法掛載到其他卷上或與其他卷有硬鏈接。Pod中的每個容器都必須獨立指定每個卷的掛載位置。

 

Pod使用Volume步驟:

  1、在Pod上定義存儲卷,並關聯至目標存儲服務上;

  2、在需要用到存儲卷的容器上,掛載其所屬Pod的存儲卷。

volume的資源清單詳解

spec: volumes: - name <string> #存儲卷名稱標識,僅可使用DNS標簽格式的字符,在當前Pod中必須唯一 VOL_TYPE <Object> #存儲卷插件及具體的目標存儲供給方的相關配置 containers: - name: ... image: ... volumeMounts: - name <string> #要掛載的存儲卷的名稱,必須匹配存儲卷列表中的某項定義 mountPatch <string> #容器文件系統上的掛載點路徑 readOnly <boolean> #是否掛載為只讀模式,默認為"否" subPath <string> #掛載存儲卷上的一個子目錄至指定的掛載點 subPathExpr <string> #掛載由指定的模式匹配到的存儲卷的文件或目錄至掛載點 mountPropagation <string> #掛載卷的傳播模式 

卷的類型

Kubernetes 1.19.4 ⽀持以下類型的卷:

awsElasticBlockStore azureDisk azureFile cephfs cinder configMap csi downwardAPI emptyDir ephemeral fc flexVolume flocker gcePersistentDisk gitRepo glusterfs hostPath iscsi name nfs persistentVolumeClaim photonPersistentDisk portworxVolume projected quobyte rbd scaleIO secret storageos vsphereVolume

上述類型中,emptyDir與hostPath屬於節點級別的卷類型,emptyDir的生命周期與Pod資源相同,而使用了hostPath卷的Pod一旦被重新調度至其他節點,那么它將無法在使用此前的數據。因此,這兩張類型都不具有持久性。要想使用持久類型的存儲卷,就得使用網絡存儲系統,如NFS,Ceph、GlusterFS等,或者雲端存儲,如awsElasticBlockStore、gcePersistentDisk。

然而,網絡存儲系統通常都不太容易使用,有的甚至很復雜,以至於對大多數用戶來說它是一個難以逾越點障礙。Kubernetes為此專門設計了一種集群級別的資源“persistentVolume”(簡稱PV),它借由管理員配置存儲系統,而后由用戶通過“persistentVolumeClaim”(簡稱PVC)存儲卷直接申請使用的機制大大簡化了終端存儲用戶的配置過程,有效降低了使用難度。

再者,Secret和ConfigMap算得上是兩種特殊的卷類型。

  1)Secret用於向Pod傳遞敏感信息,如密碼、私鑰、證書文件等,這些信息如果直接定義在鏡像中很容易導致泄露,有了Secre資源,用戶可以將這些信息存儲於集群中而后由Pod進行掛載,從而實現將敏感數據與系統解耦。

  2)ConfigMap資源則用於向Pod注入非敏感數據,使用時,用戶將數據直接存儲於ConfigMap對象中,而后直接在Pod中使用ConfigMap卷引用它即刻,它可以幫助實現容器配置文件集中化定義和管理。

常用卷詳解

1 emptyDir(臨時存儲卷)

當 Pod 被分配給節點時,⾸先創建 emptyDir 卷,並且只要該 Pod 在該節點上運⾏,該卷就會存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以讀取和寫⼊ emptyDir 卷中的相同⽂件,盡管該卷可以掛載到每個容器中的相同或不同路徑上。當出於任何原因從節點中刪除 Pod 時, emptyDir 中的數據將被永久刪除。

注意:容器崩潰不會從節點中移除pod,因此emptyDir卷中的數據在容器崩潰時是安全的。

emptyDir的用法有:

  • 暫存空間,例如用於基於磁盤的合並排序

  • 用作長時間計算崩潰恢復時的檢查點

  • Web服務器容器提供數據時,保存內容管理器容器提取的文件

總結:

  • emptyDir只是一個臨時掛載的文件,pod刪除后,該目錄也會在node節點上被刪除;但是容器崩潰時,該文件還存在.

范例:

#在master上編寫emptyDir資源清單
[root@ubuntu ~]# cat volume-emptyDir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: emptydir-pod    #注意此處只能是小寫字母或數字,大寫字母會報錯
spec:
  containers:
  - name: nginx-test
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}      #固定資源格式

#創建pod
[root@ubuntu ~]# kubectl apply -f volume-emptyDir.yaml
 #查看Pod
[root@ubuntu ~]# kubectl get pods -o wide
NAME                READY   STATUS             RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
emptydir-pod        1/1     Running            0          17s     10.244.2.62   ubuntu-210   <none>           <none>

#進入容器並在容器中創建文件測試
[root@ubuntu ~]# kubectl exec -it emptydir-pod -- bash
root@emptydir-pod:/# ls -l /cache/
total 0
root@emptydir-pod:/cache# touch /cache/nginx-emptydir.log
root@emptydir-pod:/cache# echo nginx-emptydir > /cache/nginx-emptydir.log 
root@emptydir-pod:/cache# cat /cache/nginx-emptydir.log 
nginx-emptydir

#在node節點上查找臨時存儲的文件位置
[root@ubuntu ~]# find / -name nginx-emptydir.log
/var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log

#查看文件內容
[root@ubuntu ~]# cat /var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log
nginx-emptydir

#測試掛載同步
[root@ubuntu ~]#kubectl exec -it  emptydir-pod  -- bash
root@emptydir-pod:/# rm -f  /cache/nginx.test
#在掛載節點驗證
[root@ubuntu ~]#ll  /var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/nginx.test
ls: cannot access '/var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/nginx.test': No such file or directory




#在master節點上刪除pod
[root@ubuntu ~]# kubectl delete -f volume-emptyDir.yaml 
pod "emptydir-pod" deleted

#在node節點上查看臨時存儲是否還存在
[root@ubuntu ~]# cat /var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume//nginx-emptydir.log
cat:/var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log: No such file or directory
[root@ubuntu ~]# ll /var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/
ls: cannot access '/var/lib/kubelet/pods/2e2f0fd0-17c2-466e-bf2d-81a8d0cb9aa0/volumes/kubernetes.io~empty-dir/cache-volume/': No such file or directory

 

2 hostPath(節點存儲卷)

hostPath類型的存儲卷是指將工作節點上某個文件系統的目錄或文件掛載於Pod中的一種存儲卷,它獨立於Pod資源的生命周期,因而具有持久性。但它是工作節點本地的存儲空間,僅適用於特定情況下的存儲卷使用要求,例如,將工作節點上的文件系統關聯為Pod的存儲卷,從而使得容器訪問節點文件系統上的數據。這一點在運行有管理任務的系統級Pod資源需要訪問節點上的文件時尤為有用。

hostPath的用途如如下:

  • 運行需要訪問Docker內部的容器;使用/var/lib/docker的hostPath

  • 在容器中運行cAdvisor;使用/dev/cgroups的hostPath

  • 運行pod指定給定的hostPath是否應該在pod運行之前存在,是否應該創建,以及它應該以什么形式存在

配置hostPath存儲卷點嵌套字段共有兩個:一個是用於指定工作節點上點目錄路徑的必須字段path;另一個是指定存儲卷類型的type,它支持使用的卷類型包含以下幾種:

  • DirectoryCreate:如果在給定的路徑上沒有任何東⻄存在,那么將根據需要在那⾥創建⼀個空⽬錄,權限設置為 0755,與 Kubelet 具有相同的組和所有權

  • Directory:給定的路徑下必須存在⽬錄

  • FileOrCreate:如果在給定的路徑上沒有任何東⻄存在,那么會根據需要創建⼀個空⽂件,權限設置為0644,與 Kubelet 具有相同的組和所有權。

  • File:給定的路徑下必須存在⽂件

  • Socket:給定的路徑下必須存在 UNIX 套接字

  • CharDevice:給定的路徑下必須存在字符設備

  • BlockDevice:給定的路徑下必須存在塊設備

注意:

  • 如資源清單中未配置type字段則為默認選項(默認的值為空字符串),空字符串(默認)⽤於向后兼容,這意味着在掛載 hostPath 卷之前不會執⾏任何檢查;就是不檢查path的類型

  • 由於每個節點上點文件都不同,具有相同配置(例如從podTemplate創建的)的pod在不同節點上的行為可能會有所不同

  • 當Kubetnetes安裝計划添加資源感知調度時,將無法考慮hostPath使用的資源

  • 在底層主機上創建的文件或目錄只能由root寫入。需要在特權容器中以root身份運行進程,或修改主機上的文件權限以便寫入hostPath卷。

范例:

[root@ubuntu ~]# cat volume-hostPath-test.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-test-pod
spec:
  containers:
  - name: nginx-hostpath
    image: nginx
    volumeMounts:
    - mountPath: /var/logs/
      name: data-log
 #定義hostPath卷名,和宿主機共享的路徑
  volumes:
  - name: data-log
    hostPath:
      path: /data/logs
      
#創建pod
[root@ubuntu ~]# kubectl apply -f volume-hostPath-test.yaml
[root@ubuntu ~]# kubectl get pods -o wide
NAME                READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
hostpath-test-pod   1/1     Running   0          66m   10.244.2.65   ubuntu-210   <none>           <none>
 #在node節點上的共享目錄上創建文件
[root@ubuntu ~]# echo 111 > /data/logs/1.txt
[root@ubuntu ~]# cat /data/logs/1.txt 
111

#在master節點上進入pod,查看掛載卷的文件內容
[root@ubuntu ~]# kubectl exec -it hostpath-test-pod -- bash
root@hostpath-test-pod:/# cat /var/logs/1.txt 
111
 #在pod內查看和創建創建文件
root@hostpath-test-pod:/# ls /var/logs/
1.txt
root@hostpath-test-pod:/# echo 222 > /var/logs/2.txt
root@hostpath-test-pod:/# cat /var/logs/2.txt 
222
root@hostpath-test-pod:/# ls /var/logs/
1.txt 2.txt
 #在Node節點上查看pod內部創建的文件
[root@ubuntu ~]# cat /data/logs/2.txt 
222

#刪除Pod
[root@ubuntu ~]# kubectl delete -f  volume-hostPath-test.yaml 
pod "hostpath-test-pod" deleted

#Node節點上查看文件是否存在
[root@ubuntu ~]# ll /data/logs/
total 16
-rw-r--r-- 1 root root    4 Dec  8 08:43 1.txt
-rw-r--r-- 1 root root    4 Dec  8 08:46 2.txt #可看到在Pod內部創建的文件依然存在,沒有隨pod的刪除而刪除,已初步實現了持久化.
[root@ubuntu ~]# cat /data/logs/2.txt 
222

 

3 nfs存儲卷

nfs卷能將NFS(網絡文件系統)掛載到你的pod中。不像emptyDir,當刪除Pod時,nfs卷的內容被保留,卷僅僅是被卸載。另外,NFS是文件系統級共享服務,它支持同時存在的多路掛載請求。

注意:要使用nfs,必須先擁有自己的NFS服務器,然后才能使用。

定義NFS存儲卷時,常用到以下字段:

  • server<string>:NFS服務器的IP地址或主機名,必選字段。

  • path<string>:NFS服務器導出(共享)的文件系統路徑,必選字段。

  • readOnly<boolean>:是否以只讀方式掛載,默認為false。

范例:

#先配置nfs服務器
[root@centos8 ~]# yum -y install nfs-utils
[root@centos8 ~]# cat /etc/exports
/data/test *(rw)
[root@centos8 ~]# mkdir -p /data/test
[root@centos8 ~]# echo nginx web > /data/test/index.html
[root@centos8 ~]# systemctl restart nfs-server

#測試能否正常掛載
[root@ubuntu ~]# apt -y install nfs-server
[root@ubuntu ~]# showmount -e 10.0.0.58
Export list for 10.0.0.58:
/data/test *
[root@ubuntu ~]# mount -t nfs 10.0.0.58:/data/test /mnt/
[root@ubuntu ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
udev                  955M     0  955M   0% /dev
tmpfs                 198M   13M  185M   7% /run
/dev/sda2              98G  5.4G   88G   6% /
tmpfs                 986M     0  986M   0% /dev/shm
tmpfs                 5.0M     0  5.0M   0% /run/lock
tmpfs                 986M     0  986M   0% /sys/fs/cgroup
/dev/loop1             97M   97M     0 100% /snap/core/9665
/dev/loop0             98M   98M     0 100% /snap/core/10444
/dev/sda3             976M  146M  764M  16% /boot
/dev/sda5              95G   61M   91G   1% /data
tmpfs                 198M     0  198M   0% /run/user/0
10.0.0.58:/data/test   50G  390M   50G   1% /mnt
[root@Ubuntu ~]#umount /mnt


#編寫資源清單
[root@ubuntu ~]# cat volume-nfs.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-nfs
  labels:
    app: nginx-nfs
spec:
  containers:
  - name: nginx-nfs
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: my-nfs-volume
  volumes:
  - name: my-nfs-volume
    nfs:
      server: 10.0.0.58
      path: /data/test

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80
    nodePort: 30016
    protocol: TCP
  type: NodePort
  selector:
    app: nginx-nfs
 #每個節點上都需要安裝nfs-utils,否則會報錯 #創建Pod及service
[root@ubuntu ~]# kubectl apply -f volume-nfs.yaml
[root@ubuntu ~]# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
nginx-nfs   1/1     Running   0          24m   10.244.2.67   ubuntu   <none>           <none>
[root@ubuntu ~]# kubectl get service nginx-service -o wide
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
nginx-service   NodePort   10.104.177.209   <none>        81:30016/TCP   25m   app=nginx-nfs

#進入Pod查看是否掛載成功
[root@ubuntu ~]# kubectl exec -it nginx-nfs -- bash
root@nginx-nfs:/# cat /usr/share/nginx/html/index.html 
nginx web

#訪問master宿主機IP瀏覽器測試 10.0.0.78:30016 出現nginx web 機成功

 

 

 

 

 

 

 

 

K8s 的數據卷volume


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM