kubernetes系列10—存儲卷詳解
1、認識存儲卷
1.1 背景
默認情況下容器中的磁盤文件是非持久化的,容器中的磁盤的生命周期是短暫的,這就帶來了一系列的問題:第一,當一個容器損壞之后,kubelet 會重啟這個容器,但是文件會丟失-這個容器會是一個全新的狀態;第二,當很多容器在同一Pod中運行的時候,很多時候需要數據文件的共享。Kubernete Volume解決了這個問題。
?
1.2 介紹
Docker有一個Volumes的概念,雖然這個Volume有點寬松和管理性比較小。在Docker中,一個 Volume 是一個簡單的所在主機的一個目錄或者其它容器中的。生命周期是沒有辦法管理,直到最近才有 local-disk-backed 磁盤。Docker現在提供了磁盤驅動,但是功能非常有限(例如Docker1.7只能掛在一個磁盤每個容器,并且無法傳遞參數)
從另外一個方面講,Kubernetes volume,擁有明確的生命周期,與所在的Pod的生命周期相同。因此,Kubernetes volume獨立與任何容器,與Pod相關,所以數據在重啟的過程中還會保留,當然,如果這個Pod被刪除了,那么這些數據也會被刪除。更重要的是,Kubernetes volume 支持多種類型,任何容器都可以使用多個Kubernetes volume。
它的核心,一個 volume 就是一個目錄,可能包含一些數據,這些數據對pod中的所有容器都是可用的,這個目錄怎么使用,什么類型,由什么組成都是由特殊的volume 類型決定的。
要使用Volume,pod需要指定Volume的類型和內容(spec.volumes字段),和映射到容器的位置(spec.containers.volumeMounts字段)。
容器中的進程可以看成由Docker鏡像和卷組成的文件系統視圖。Docker鏡像位于文件系統層次結構的根目錄下,任何卷都安裝在圖像中的指定路徑上。卷無法裝入其他卷或具有到其他卷的硬鏈接。Pod中的每個容器必須獨立指定每個卷的安裝位置。
?
1.3 存儲卷常用類型
- ?非持久性存儲
- ?emptyDir
- ?hostPath
- ?網絡連接性存儲
- ?SAN:iSCSI
- ?NFS:nfs,cfs
- ?分布式存儲
- ?glusterfs、rbd、cephfs
- ?云端存儲
- ?EBS、Azure Disk、阿里云、gitRepo
1 | $ kubectl explain pod.spec.volumes 查詢k8s支持的所有類型存儲卷 |
?
2、emptyDir存儲卷
2.1 emptyDir介紹
使用emptyDir,當Pod分配到Node上時,將會創建emptyDir,并且只要Node上的Pod一直運行,Volume就會一直存。當Pod(不管任何原因)從Node上被刪除時,emptyDir也同時會刪除,存儲的數據也將永久刪除。
常用于作為臨時目錄、或緩存使用。
?
2.2 演示:創建emptyDir存儲卷
(1)編寫yaml文件,并創建
先創建一個名為html的存儲卷;再由2個pod都掛載此存儲卷;
pod1基于此存儲卷作為nginx的主目錄;pod2向此存儲卷目錄寫入東西;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | [root@master volumes] # vim vol-emptyDir-demo.yaml apiVersion: v1 kind: Pod metadata: ?? name: pod-vol-demo ?? namespace: default ?? labels: ???? app: myapp ???? tier: frontend ?? annotations: ???? along.com /created-by : "cluster admin" spec: ?? volumes: ?? - name: html ???? emptyDir: {} ?? containers: ?? - name: myapp ???? image: ikubernetes /myapp :v1 ???? imagePullPolicy: IfNotPresent ???? ports: ???? - name: http ?????? containerPort: 80 ???? volumeMounts: ???? - name: html ?????? mountPath: /usr/share/nginx/html/ ?? - name: busybox ???? image: busybox:latest ???? imagePullPolicy: IfNotPresent ???? volumeMounts: ???? - name: html ?????? mountPath: /data/ ???? command : ???? - "/bin/sh" ???? - "-c" ???? - "while true; do echo $(date) >> /data/index.html; sleep 2; done" [root@master volumes] # kubectl apply -f vol-emptyDir-demo.yaml pod /pod-vol-demo created |
(2)驗證
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ---pod創建成功 [root@master ~] # kubectl get pods -o wide NAME?????????? READY???? STATUS??? RESTARTS?? AGE?????? IP???????????? NODE pod-vol-demo?? 2 /2 ?????? Running?? 0????????? 13s?????? 10.244.1.106?? node1 ---訪問業務,輸出是pod2的輸入 [root@master ~] # curl 10.244.1.106 Tue Jan 29 07:19:13 UTC 2019 Tue Jan 29 07:19:15 UTC 2019 Tue Jan 29 07:19:17 UTC 2019 Tue Jan 29 07:19:19 UTC 2019 Tue Jan 29 07:19:21 UTC 2019 Tue Jan 29 07:19:23 UTC 2019 Tue Jan 29 07:19:25 UTC 2019 Tue Jan 29 07:19:27 UTC 2019 Tue Jan 29 07:19:29 UTC 2019 |
3、hostPath存儲卷
3.1 emptyDir介紹
hostPath允許掛載Node(宿主機)上的文件系統到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。
?
3.2 hostPath類型
值 | 行為 |
---|---|
空 | 空字符串(默認)用于向后兼容,這意味著在安裝hostPath卷之前不會執行任何檢查。 |
DirectoryOrCreate | 如果給定路徑中不存在任何內容,則將根據需要創建一個空目錄,權限設置為0755,與Kubelet具有相同的組和所有權。 |
Directory | 目錄必須存在于給定路徑中 |
FileOrCreate | 如果給定路徑中不存在任何內容,則會根據需要創建一個空文件,權限設置為0644,與Kubelet具有相同的組和所有權。 |
File | 文件必須存在于給定路徑中 |
Socket | UNIX套接字必須存在于給定路徑中 |
CharDevice | 字符設備必須存在于給定路徑中 |
BlockDevice | 塊設備必須存在于給定路徑中 |
?
3.2 演示:創建hostPath存儲卷
(1)編寫yaml文件,并創建
創建存儲卷,使用DirectoryOrCreate類型,node節點不存在會自動創建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | [root@master volumes] # vim vol-hostpath-demo.yaml apiVersion: v1 kind: Pod metadata: ?? name: vol-hostpath ?? namespace: default spec: ?? volumes: ?? - name: html ???? hostPath: ?????? path: /data/pod/volume1/ ?????? type : DirectoryOrCreate ?? containers: ?? - name: myapp ???? image: ikubernetes /myapp :v1 ???? volumeMounts: ???? - name: html ?????? mountPath: /usr/share/nginx/html/ [root@master volumes] # kubectl apply -f vol-hostpath-demo.yaml pod /vol-hostpath created |
(2)查詢驗證
1 2 3 4 5 6 | [root@master volumes] # kubectl get pods -o wide NAME?????????? READY???? STATUS??? RESTARTS?? AGE?????? IP???????????? NODE vol-hostpath?? 1 /1 ?????? Running?? 0????????? 3s??????? 10.244.1.111?? node1 ---在node1上查詢是否生產目錄 [root@node1 ~] # ll -d /data/pod/volume1/index.html -rw-r--r-- 1 root root 17 Sep 21 14:44 /data/pod/volume1/index .html |
(3)驗證存儲卷功能
1 2 3 4 5 | ---在node1上生成文件 [root@node1 ~] # echo "node01.along.com" > /data/pod/volume1/index.html ---訪問pod內服務,顯示成功 [root@master volumes] # curl 10.244.1.111 node01.along.com |
(4)就算pod被刪除再重建,只要node還在,存儲卷就還在
1 2 3 4 5 6 7 8 9 | [root@master volumes] # kubectl delete -f vol-hostpath-demo.yaml pod "vol-hostpath" deleted [root@master volumes] # kubectl apply -f vol-hostpath-demo.yaml pod /vol-hostpath created [root@master volumes] # kubectl get pods -o wide NAME?????????? READY???? STATUS??? RESTARTS?? AGE?????? IP???????????? NODE vol-hostpath?? 1 /1 ?????? Running?? 0????????? 3s??????? 10.244.1.112?? node1 [root@master volumes] # curl 10.244.1.112 node01.along.com |
4、共享存儲NFS存儲卷
4.1 NFS存儲卷介紹
NFS 是Network File System的縮寫,即網絡文件系統。Kubernetes中通過簡單地配置就可以掛載NFS到Pod中,而NFS中的數據是可以永久保存的,同時NFS支持同時寫操作。Pod被刪除時,Volume被卸載,內容被保留。這就意味著NFS能夠允許我們提前對數據進行處理,而且這些數據可以在Pod之間相互傳遞。
?
4.2 演示:創建NFS存儲卷
4.2.1 在一臺服務器搭建NFS
(1)事前準備
① 修改k8s集群服務的hosts文件,使之能解析nfs服務器
1 2 3 4 5 | [root@master volumes] # vim /etc/hosts 192.168.130.103 master 192.168.130.104 node1 192.168.130.105 node2 192.168.130.106 nfs |
② 在k8s集群服務器,安裝nfs-utils 工具
1 | $ yum -y install nfs-utils |
(2)在106服務器上提供nfs服務
1 2 3 4 5 6 7 | [root@nfs ~] # yum -y install nfs-utils [root@nfs ~] # mkdir /data/volumes -p [root@nfs ~] # vim /data/volumes/index.html <h1>NFS stor< /h1 > [root@nfs ~] # vim /etc/exports /data/volumes ?? 192.168.130.0 /24 (rw,no_root_squash) [root@nfs ~] # systemctl start nfs |
4.2.1 創建NFS存儲卷
(1)編寫yaml文件,并創建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | [root@master volumes] # vim vol-nfs-demo.yaml apiVersion: v1 kind: Pod metadata: ?? name: vol-nfs ?? namespace: default spec: ?? volumes: ?? - name: html ???? nfs: ?????? path: /data/volumes ?????? server: nfs ?? containers: ?? - name: myapp ???? image: ikubernetes /myapp :v1 ???? volumeMounts: ???? - name: html ?????? mountPath: /usr/share/nginx/html/ [root@master volumes] # kubectl apply -f vol-nfs-demo.yaml pod /vol-nfs created |
(2)驗證,訪問服務成功
1 2 3 4 5 | [root@master ~] # kubectl get pods -o wide NAME????? READY???? STATUS??? RESTARTS?? AGE?????? IP???????????? NODE vol-nfs?? 1 /1 ?????? Running?? 0????????? 9s??????? 10.244.1.115?? node1 [root@master ~] # curl 10.244.1.115 <h1>NFS stor< /h1 > |
刪除pod,再創建,也還存在數據。
?
5、一些不常用的存儲卷
5.1 gitRepo
(1)介紹
gitRepo volume將git代碼下拉到指定的容器路徑中
?
(2)示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | apiVersion: v1 kind: Pod metadata: ?? name: server spec: ?? volumes: ?? - name: git-volume ???? gitRepo: ?????? repository: "git@github.com:alonghub/my-git-repository.git" ????? revision: "22f1d8406d464b0c0874075539c1f2e96c253775" ?? containers: ?? - name: myapp ???? image: ikubernetes /myapp :v1 ???? imagePullPolicy: IfNotPresent ???? ports: ???? - name: http ?????? containerPort: 80 ???? volumeMounts: ???? - name: git-volume ?????? mountPath: /usr/share/nginx/html/ |
5.2 glusterfs
glusterfs,允許將Glusterfs(一個開源網絡文件系統)Volume安裝到pod中。不同于emptyDir,Pod被刪除時,Volume只是被卸載,內容被保留。味著glusterfs能夠允許我們提前對數據進行處理,而且這些數據可以在Pod之間“切換”。
注意::必須先運行自己的GlusterFS安裝,然后才能使用它。
有關更多詳細信息,請參閱GlusterFS示例。
?
5.3 RBD
RBD允許Rados Block Device格式的磁盤掛載到Pod中,同樣的,當pod被刪除的時候,rbd也僅僅是被卸載,內容保留,rbd能夠允許我們提前對數據進行處理,而且這些數據可以在Pod之間“切換”。
有關更多詳細信息,請參閱RBD示例。
?
5.4 cephfs
cephfs Volume可以將已經存在的CephFS Volume掛載到pod中,與emptyDir特點不同,pod被刪除的時,cephfs僅被被卸載,內容保留。cephfs能夠允許我們提前對數據進行處理,而且這些數據可以在Pod之間“切換”。
提示:可以使用自己的Ceph服務器運行導出,然后在使用cephfs。
有關更多詳細信息,請參閱CephFS示例