容器磁盤上的文件的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題。首先,當容器崩潰
時,kubelet 會重啟它,但是容器中的文件將丟失——容器以干凈的狀態(鏡像最初的狀態)重新啟動。其次,在
Pod 中同時運行多個容器時,這些容器之間通常需要共享文件。Kubernetes 中的 Volume 抽象就很好的解決了這些問題
背景
Kubernetes 中的卷有明確的壽命 —— 與封裝它的 Pod 相同。所f以,卷的生命比 Pod 中的所有容器都長,當這
個容器重啟時數據仍然得以保存。當然,當 Pod 不再存在時,卷也將不復存在。也許更重要的是,Kubernetes
支持多種類型的卷,Pod 可以同時使用任意數量的卷卷的類型。
emptyDir
一個emptyDir 第一次創建是在一個pod被指定到具體node的時候,並且會一直存在在pod的生命周期當中,正如它的名字一樣,它初始化是一個空的目錄,pod中的容器都可以讀寫這個目錄,這個目錄可以被掛在到各個容器相同或者不相同的的路徑下。當一個pod因為任何原因被移除的時候,這些數據會被永久刪除。注意:一個容器崩潰了不會導致數據的丟失,因為容器的崩潰並不移除pod.
emptyDir 磁盤的作用:
scratch space, such as for a disk-based mergesortcw
checkpointing a long computation for recovery from crashes
holding files that a content-manager container fetches while a webserver container serves the data
- 普通空間,基於磁盤的數據存儲
- 作為從崩潰中恢復的備份點
- 存儲那些那些需要長久保存的數據,例web服務中的數據
默認的,emptyDir 磁盤會存儲在主機所使用的媒介上,可能是SSD,或者網絡硬盤,這主要取決於你的環境。當然,我們也可以將emptyDir.medium的值設置為Memory來告訴Kubernetes 來掛在一個基於內存的目錄tmpfs,因為
tmpfs速度會比硬盤塊度了,但是,當主機重啟的時候所有的數據都會丟失
[root@k8s-master mnt]# cat volume.yaml apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: wangyanglinux/myapp:v2 name: test-container volumeMounts: - mountPath: /cache name: cache-volume - name: liveness-exec-container image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","sleep 6000s"] volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {} [root@k8s-master mnt]#
執行:
[root@k8s-master mnt]# vim volume.yaml [root@k8s-master mnt]# kubectl create -f volume.yaml pod/test-pd created [root@k8s-master mnt]# kubectl describe pod test-pd Name: test-pd Namespace: default Priority: 0 Node: k8s-node02/192.168.180.136 Start Time: Fri, 27 Dec 2019 13:44:38 +0800 Labels: <none> Annotations: <none> Status: Running IP: 10.244.1.49 IPs: IP: 10.244.1.49 Containers: test-container: Container ID: docker://236b2b8c29ed6d42b74aaef24bc1d43d21863598c7c5a5cd19b9fc953993c7c0 Image: wangyanglinux/myapp:v2 Image ID: docker-pullable://wangyanglinux/myapp@sha256:85a2b81a62f09a414ea33b74fb8aa686ed9b168294b26b4c819df0be0712d358 Port: <none> Host Port: <none> State: Running Started: Fri, 27 Dec 2019 13:44:40 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /cache from cache-volume (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-6wcrh (ro) liveness-exec-container: Container ID: docker://304943afd2171d58d2b36d93f3833405f7e2651ffb67ad807adaf80c8a6fd330 Image: busybox Image ID: docker-pullable://busybox@sha256:1828edd60c5efd34b2bf5dd3282ec0cc04d47b2ff9caa0b6d4f07a21d1c08084 Port: <none> Host Port: <none> Command: /bin/sh -c sleep 6000s State: Running Started: Fri, 27 Dec 2019 13:44:40 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /cache from cache-volume (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-6wcrh (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: cache-volume: Type: EmptyDir (a temporary directory that shares a pod's lifetime) Medium: SizeLimit: <unset> default-token-6wcrh: Type: Secret (a volume populated by a Secret) SecretName: default-token-6wcrh Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned default/test-pd to k8s-node02 Normal Pulled 8s kubelet, k8s-node02 Container image "wangyanglinux/myapp:v2" already present on machine Normal Created 8s kubelet, k8s-node02 Created container test-container Normal Started 7s kubelet, k8s-node02 Started container test-container Normal Pulled 7s kubelet, k8s-node02 Container image "busybox" already present on machine Normal Created 7s kubelet, k8s-node02 Created container liveness-exec-container Normal Started 7s kubelet, k8s-node02 Started container liveness-exec-container [root@k8s-master mnt]# kubectl get pod NAME READY STATUS RESTARTS AGE test-pd 2/2 Running 0 107s [root@k8s-master mnt]# !711 kubectl exec test-pd -it -- /bin/sh Defaulting container name to test-container. Use 'kubectl describe pod/test-pd -n default' to see all of the containers in this pod. / # ls bin cache dev etc home lib media mnt proc root run sbin srv sys tmp usr var / # exit
看來里面有這個文件夾
hostPath
hostPath 卷將主機節點的文件系統中的文件或目錄掛載到集群中
hostPath 的用途如下:
運行需要訪問 Docker 內部的容器;使用 /var/lib/docker 的 hostPath
在容器中運行 cAdvisor;使用 /dev/cgroups 的 hostPath
允許 pod 指定給定的 hostPath 是否應該在 pod 運行之前存在,是否應該創建,以及它應該以什么形式存在
除了所需的 path 屬性之外,用戶還可以為 hostPath 卷指定 type
使用這種卷類型是請注意,因為:
由於每個節點上的文件都不同,具有相同配置(例如從 podTemplate 創建的)的 pod 在不同節點上的行為可能會有所不同。
當 Kubernetes 按照計划添加資源感知調度時,將無法考慮 hostPath 使用的資源
在底層主機上創建的文件或目錄只能由 root 寫入。您需要在特權容器中以 root 身份運行進程,或修改主機上的文件權限以便寫入 hostPath 卷。
[root@k8s-master mnt]# cat pod1.yaml apiVersion: v1 kind: Pod metadata: name: test-pd1 spec: containers: - image: wangyanglinux/myapp:v2 name: test-container volumeMounts: - mountPath: /test-pd1 name: test-volume1 volumes: - name: test-volume1 hostPath: path: /data type: Directory [root@k8s-master mnt]#
[root@k8s-master mnt]# vim pod1.yaml [root@k8s-master mnt]# kubectl create -f pod1.yaml pod/test-pd1 created [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 101m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 9s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 102m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 23s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 102m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 25s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 102m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 48s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 102m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 50s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 103m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 79s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 103m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 81s <none> k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 104m 10.244.1.49 k8s-node02 <none> <none> test-pd1 0/1 ContainerCreating 0 3m2s <none> k8s-node01 <none> <none>
假如子節點沒有data文件夾
[root@k8s-master mnt]# kubectl describe pod test-pd1 Name: test-pd1 Namespace: default Priority: 0 Node: k8s-node01/192.168.180.135 Start Time: Fri, 27 Dec 2019 15:31:19 +0800 Labels: <none> Annotations: <none> Status: Pending IP: IPs: <none> Containers: test-container: Container ID: Image: wangyanglinux/myapp:v2 Image ID: Port: <none> Host Port: <none> State: Waiting Reason: ContainerCreating Ready: False Restart Count: 0 Environment: <none> Mounts: /test-pd1 from test-volume1 (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-6wcrh (ro) Conditions: Type Status Initialized True Ready False ContainersReady False PodScheduled True Volumes: test-volume1: Type: HostPath (bare host directory volume) Path: /data HostPathType: Directory default-token-6wcrh: Type: Secret (a volume populated by a Secret) SecretName: default-token-6wcrh Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned default/test-pd1 to k8s-node01 Warning FailedMount 21s (x6 over 36s) kubelet, k8s-node01 MountVolume.SetUp failed for volume "test-volume1" : hostPath type check failed: /data is not a directory
[root@k8s-master mnt]# kubectl describe pod test-pd1 Name: test-pd1 Namespace: default Priority: 0 Node: k8s-node01/192.168.180.135 Start Time: Fri, 27 Dec 2019 15:31:19 +0800 Labels: <none> Annotations: <none> Status: Running IP: 10.244.2.55 IPs: IP: 10.244.2.55 Containers: test-container: Container ID: docker://5a8696561897043c9c141acae2f66eea2ca6d4b834a15c143c953a269113e25b Image: wangyanglinux/myapp:v2 Image ID: docker-pullable://wangyanglinux/myapp@sha256:85a2b81a62f09a414ea33b74fb8aa686ed9b168294b26b4c819df0be0712d358 Port: <none> Host Port: <none> State: Running Started: Fri, 27 Dec 2019 15:32:04 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /test-pd1 from test-volume1 (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-6wcrh (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: test-volume1: Type: HostPath (bare host directory volume) Path: /data HostPathType: Directory default-token-6wcrh: Type: Secret (a volume populated by a Secret) SecretName: default-token-6wcrh Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned default/test-pd1 to k8s-node01 Warning FailedMount 106s (x6 over 2m1s) kubelet, k8s-node01 MountVolume.SetUp failed for volume "test-volume1" : hostPath type check failed: /data is not a directory Normal Pulled 77s kubelet, k8s-node01 Container image "wangyanglinux/myapp:v2" already present on machine Normal Created 77s kubelet, k8s-node01 Created container test-container Normal Started 77s kubelet, k8s-node01 Started container test-container [root@k8s-master mnt]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 2/2 Running 1 109m 10.244.1.49 k8s-node02 <none> <none> test-pd1 1/1 Running 0 3m9s 10.244.2.55 k8s-node01 <none> <none> [root@k8s-master mnt]# kubectl exec test-pd1 -it -- /bin/sh / # ls bin etc lib mnt root sbin sys tmp var dev home media proc run srv test-pd1 usr / # cd test-pd1 /test-pd1 # date > index.html /test-pd1 # ls -l total 4 -rw-r--r-- 1 root root 29 Dec 27 07:35 index.html /test-pd1 #
在子節點查看
[root@k8s-node01 /]# mkdir /data [root@k8s-node01 /]# cd /data [root@k8s-node01 data]# ll 總用量 4 -rw-r--r-- 1 root root 29 12月 27 15:35 index.html [root@k8s-node01 data]# cat index.html Fri Dec 27 07:35:52 UTC 2019 [root@k8s-node01 data]#