K8s中Volume

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃
时,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速度会比硬盘块度了,但是,当主机重启的时候所有的数据都会丢失

[ 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]#

执行:

[ mnt]# vim volume.yaml
[ 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/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://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

K8s中Volume

使用这种卷类型是请注意,因为:
由于每个节点上的文件都不同,具有相同配置(例如从 podTemplate 创建的)的 pod 在不同节点上的行为可能会有所不同。
当 Kubernetes 按照计划添加资源感知调度时,将无法考虑 hostPath 使用的资源
在底层主机上创建的文件或目录只能由 root 写入。您需要在特权容器中以 root 身份运行进程,或修改主机上的文件权限以便写入 hostPath 卷。

[ 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]#
[ mnt]# vim pod1.yaml
[ 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文件夹

[ 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
[ 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/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 #

在子节点查看

[ /]# mkdir /data
[ /]# cd /data
[ 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]#

相关推荐