Kubernetes中的emptyDir存储卷和节点存储卷

Kubernetes支持存储卷类型中,emptyDir存储卷的生命周期与其所属的Pod对象相同,它无法脱离Pod对象的生命周期提供数据存储功能,因此emptyDir通常仅用于数据缓存或临时存储。不过基于emptyDir构建的gitRepo存储卷可以在Pod对象的生命周期起始时从响应的Git仓库中复制相应的数据文件到底层的emptyDir中,从而使得它具有了一定意义上的持久性。

emptyDir存储卷

emptyDir存储卷是Pod对象生命周期中的一个临时目录,类似于Docker上的docker挂载卷,在Pod对象启动时即被创建,而在Pod对象被移除时会被一并删除。不具有持久能力的emptyDir存储卷只能用于某些特殊场景中,例如,用一Pod内的多个容器间文件的共享,或者作为容器数据的临时存储目录用于数据缓存系统等。

emptyDir存储卷则定义于.spec.volumes.emptyDir嵌套字段中,可用字段主要包含两个,具体如下:

medium:此目录所在存储介质的类型,可取值为defaultMemory,默认为default,表示使用节点的默认存储介质:Memory 表示基于RAM的临时文件系统tmpfs,空间受于内存,但性能非常好,通常用于为容器中的应用提供缓存空间。

sizeLimit:当前存储卷的空间限额,默认值为 nil,表示不限制;不过在 medium 字段为Memory时,建议定义此限额。

1.创建Pod对象配置清单

下面是一个使用了emptyDir存储卷的简单示例,它保持于vol-emptydir.yaml配置文件:

apiVersion: v1
kind: Pod
metadata:
  name: vol-emptydir-pod
spec:
  volumes:
  - name: html
    emptyDir: { }
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  - name: pagegen
    image: alpine
    volumeMounts:
    - name: html
      mountPath: /html
    command: [ "/bin/sh", "-c" ]
    args:                        #定义循环,每10秒向/html/文件中追加写入当前主机名和时间
    - while true; do
        echo $(hostname) $(date) >> /html/index.html;
        sleep 10;
      done

上面示例中定义的存储卷名称为html,挂载于容器nginx的 /usr/share/nginx/html目录,以及容器pagegen的/html目录。容器pagegen每隔10秒向存储卷上的index.html文件中追加一行信息,而容器nginx中的nginx进程则以其站点主页。如下图所示:

Kubernetes中的emptyDir存储卷和节点存储卷

2.创建Pod对象

kubectl apply -f vol-emptydir.yaml

3.查看Pod状态 Pod对象的详细信息中会显示存储卷的相关状态,包括其是否创建成功(在Events字段中输出)、相关的类型及参数(在Volumes字段中输出)以及容器中挂载状态等信息(在Containers字段中输出),如下面命令所示:

kubectl describe pods/vol-emptydir-pod
Containers:
  nginx:
    Mounts:
      /usr/share/nginx/html from html (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-xxqkj (ro)
  pagegen:
    Command:
      /bin/sh
      -c
    Args:
      while true; do echo $(hostname) $(date) >> /html/index.html; sleep 10; done
    Mounts:
      /html from html (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-xxqkj (ro)

4.访问Pod中Nginx pagegen容器每隔10秒向 html/index.html 追加写入信息,Nginx容器挂载的也是此临时存储,所以Nginx的网页文件也是从这里获取。

curl http://172.20.1.18
vol-emptydir-pod Fri Jun 12 02:47:29 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:39 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:49 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:59 UTC 2020
vol-emptydir-pod Fri Jun 12 02:48:09 UTC 2020
vol-emptydir-pod Fri Jun 12 02:48:19 UTC 2020

5.进入容器 以下分别进入Nginx容器以及pagegen容器查看其挂载

通过 -c 来指定容器名称进入指定容器

kubectl exec -it pods/vol-emptydir-pod -c nginx -- /bin/sh
# ls /usr/share/nginx/html
index.html
# head -3 /usr/share/nginx/html/index.html
vol-emptydir-pod Fri Jun 12 02:47:29 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:39 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:49 UTC 2020

进入pagegen容器

kubectl exec -it pods/vol-emptydir-pod -c pagegen -- /bin/sh
/ # ls /html/
index.html
/ # head -3 /html/index.html
vol-emptydir-pod Fri Jun 12 02:47:29 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:39 UTC 2020
vol-emptydir-pod Fri Jun 12 02:47:49 UTC 2020
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh -c while true; do echo $(hostname) $(date) >> /html/index.html; sleep 10; done
  286 root      0:00 /bin/sh
  303 root      0:00 sleep 10
  304 root      0:00 ps aux

作为边车 (sidecar)的容器pagegen,其每隔10秒生成一行信息追加到存储卷上的index.html文件中,因此,通过主容器nginx的应用访问到文件内存也会处理不停的变动中。另外,emptyDir存储卷也可以基于RAM创建tmpfs文件系统的存储卷,常用于为容器的应用提高高性能缓存,下面是一个配置示例:

cat vol-emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: vol-emptydir-pod
spec:
  volumes:
  - name: html
    emptyDir:
      medium: Memory                #指定临时存储到内存
      sizeLimit: 256Mi              #给予的内存空间大小
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  - name: pagegen
    image: alpine
    volumeMounts:
    - name: html
      mountPath: /html
    command: [ "/bin/sh", "-c" ]
    args:
    - while true; do
        echo $(hostname) $(date) >> /html/index.html;
        sleep 10;
      done

emptyDir卷简单易用,但仅能用于临时存储,另外还存在一些类型的存储卷构建在emptyDir之上,并额外提供了emptyDir没有的功能。

节点存储卷 hostPath

hostPath类型的存储卷是指将工作节点上某文件系统的目录或文件挂载于Pod中的一种存储卷,它可独立于Pod资源的生命周期,因而具有持久性。但它是工作节点本地的存储空间,仅适用于特定情况下的存储卷使用需求,例如,将工作节点上的文件系统关联为Pod的存储卷,从而使得容器访问接待您文件系统上的数据。这一点在运行有管理任务的系统级Pod资源需要访问节点上的文件时比较有用。

配置hostPath存储卷的嵌套字段共有两个:一个是用于指定工作节点上的目录路径的必须按字段path 一个是指定存储卷类型的type,它支持使用的卷类型包含如下几种:

•DirectoryOrCreate:指定的路径不存在时自动将其创建为权限是0755的空目录,属主属组均为kubelet。

•Directory:必须存在的目录路径

•FileOrCreate:指定的路径不存在时自动将其创建为权限0644的空文件,属主和属组同是kubelet。

•File:必须存在的文件路径

•Socket:必须存在的Socket文件路径

•CharDevice:必须存在的字符设备文件路径

•BlockDevice:必须存在的块设备文件路径

Kubernetes中的emptyDir存储卷和节点存储卷

下面是定义在vo-hostpath.yaml配置文件中的Pod资源,它运行着日志收集代理应用filebeat,负责收集工作节点及容器相关的日志信息发往Redis服务器,它使用了三个hostPath类型的存储卷:

1.创建资源配置清单

apiVersion: v1
kind: Pod
metadata:
  name: vo-hostpath-pod
spec:
  containers:
  - name: filebeat
    image: ikubernetes/filebeat:5.6.7-alpine
    env:                            #定义变量
    - name: REDIS_HOST              #变量名
      value: redis.ilinux.io:6379   #变量值
    - name: LOG_LEVEL                   #变量明
      value: info                   #变量值
    volumeMounts:                   #卷挂载配置
    - name: varlog                  #挂载名称为varlog的卷
      mountPath: /var/log           #挂载到容器中的/var/log目录中
    - name: socket                  #挂载名称为socket的卷
      mountPath: /var/run/docker.sock#挂载到容器中的/var/run/docker.sock
    - name: varlibdockercontainers  #挂载名称为varlibdockercontainers的卷
      mountPath: /var/lib/docker/containers#挂载到容器中的/var/lib/docker/containers目录中
      readOnly: true                #为只读挂载
  volumes:                          #卷配置
  - name: varlog                    #自定义的卷名称
    hostPath:                       #节点路径配置
      path: /var/log                #在节点上的路径
      type: DirectoryOrCreate        #节点上不存在/var/log目录时,则自动创建权限为0755的目录,属性信息为kubelet用户
  - name: varlibdockercontainers
    hostPath:
      path: /var/lib/docker/containers
      type: Directory
  - name: socket
    hostPath:
      path: /var/run/docker.sock
      type: Socket                        #节点上必须存在/var/run/docker.sock,否则创建Pod失败

2.创建Pod对象

kubectl apply -f vo-hostpath.yaml

3.查看Pod对象详细信息 如下命令可以到Pod的挂载信息

kubectl describe pods/vo-hostpath-pod | grep -A 12 Volumes
Volumes:
  varlog:
    Type:          HostPath (bare host directory volume)
    Path:          /var/log
    HostPathType:
  varlibdockercontainers:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/docker/containers
    HostPathType:
  socket:
    Type:          HostPath (bare host directory volume)
    Path:          /var/run/docker.sock
    HostPathType:

如下这台Pod运行在了Node02节点之上,那么就会把Node02上的 /var/log 、/var/lib/docker/containers目录以及 /var/run/docker.sock文件挂载至我们创建的Pod之中。

kubectl get pods -o wide | grep vo-hostpath-pod
vo-hostpath-pod               1/1     Running            0          3m37s   172.20.2.28   k8s-node02   <none>           <none>

4.进入Pod查看挂载信息


kubectl exec -it pods/vo-hostpath-pod -- /bin/sh

#查看/var/log
/ # ls /var/log
alternatives.log          chrony                    kern.log                  syslog.2.gz               vmware-vmsvc-root.1.log
alternatives.log.1        cloud-init-output.log     kern.log.1                syslog.3.gz               vmware-vmsvc-root.2.log
apt                       cloud-init.log            kern.log.2.gz             syslog.4.gz               vmware-vmsvc-root.3.log
auth.log                  containers                kern.log.3.gz             syslog.5.gz               vmware-vmsvc-root.log
auth.log.1                dist-upgrade              kern.log.4.gz             syslog.6.gz               vmware-vmtoolsd-root.log
auth.log.2.gz             dpkg.log                  landscape                 syslog.7.gz               wtmp
auth.log.3.gz             dpkg.log.1                lastlog                   tallylog                  wtmp.1
auth.log.4.gz             dpkg.log.2.gz             lxd                       unattended-upgrades
bootstrap.log             faillog                   pods                      vmware-network.1.log
btmp                      installer                 syslog                    vmware-network.2.log
btmp.1                    journal                   syslog.1                  vmware-network.log

#查看/var/lib/docker/containers信息
/ # ls  /var/lib/docker/containers/
222ff7ab4b939691d4690ebd353e4dae39782d48dba190f6473d02f65e35e9c5  9b362d8f03d2f87573487a8d6a266c1a77b6e2cfb28654ba5a3016008155564f
2ddb2bd4c2dfd44b48a430502e8f0479651ac2084b14070c7bd6f128907e6d27  d2e2af23b3a406d941a1f19a989c6a529b7cfda32a75579ff171148e3bce771d
2f0c31b8e6fff99953a096af8153b37b572f71a3e98a9e09665486b6ca6d940f  e0d8e9913767ef45c700648f20f025440f1313be242b6f0cf3577b1b92d61acb
31baeb1aef75acf16544042add63293e8547008c1ae1d40ab62f8fd24fa203a4  ee09c6588feb6665d24f61a887fe4a9d4df366625f80e9b7b0520c6066b3a754
3dbada0509671af1193b39b86f72d1ed9022914f7ba7886bd975cfa70c554559  ef1fcc1b0de6817b2d2c8b81a187e72a93c960c816ee118bf5ba9d1a07fff7d6
47686a866a3e9f1e0b82bb582072c612b95ea0d1c68951ea44b3f751eb49dbcb  f52a7a55801bec13b26f2c02fbc5c32cb758f690de5480ff246f379ebbb3fac7
6bc85638f22115f3479ef025b94159a7d8e5e5988fb508c28d118f510c767e0f  f6b5e6bc12ba8121d2aceca137eaf31929d46664648154b45800697a8bd5a23c
9afc7bb18dc7d858f514ec001ad47c6fd6d5ac67f25aa0e777c4762b9ccfaf45

#查看/var/run/docker.sock文件
/ # ls -lrth  /var/run/docker.sock
srw-rw----    1 root     ping           0 May  8 03:27 /var/run/docker.sock
/ # exit;

这类Pod资源通常受控于daemonset类型的Pod控制器,它运行于集群中的每个工作节点之上,负责收集工作节点上系统级的相关逐句,因此使用hostPath存储卷也是理所应当的。

读者在创建上述Pod资源时,如果有可用的Redis服务器,则可通过REDIS_HOST传递给Pod资源,待其Ready之后即可通过Redis服务器查看到由其发送的日志信息。在filebeat应用架构中。这些日志信息会发到Elasticsearch,并通过Kibana进行展示。

另外,使用hostPath存储卷时需要注意到,不同节点上的文件或许并不完全相同,于是,那些要求事先必须存在的文件或目录的满足状态也可能会有所不同;另外基于资源可用状态的调度器Pod时,hostPath资源的可用性状态不会被考虑在内;再者,在节点中创建的文件或目录默认仅有root可写,若期望容器内的进程拥有写权限,则要么将它们运行为特权容器,要么修改节点上的目录权限。

那些并非执行系统级管理任务的且不受控于Daemonset控制器的无状态应用在Pod资源被重新调度至其它节点运行时,此前创建的文件或目录大多数都不会存在。因此hostPath存储卷虽然能持久保存数据,但对被调度器按需调度的应用来说并不适用,这时需要用到的是独立于集群节点的持久性存储卷、即网络存储卷。

好啦!今天的分享到这里就结束了,希望大家持续关注马哥教育官网,每天都会有大量优质内容与大家分享!

文章来源于网络,侵删!

相关新闻

历经多年发展,已成为国内好评如潮的Linux云计算运维、SRE、Devops、网络安全、云原生、Go、Python开发专业人才培训机构!