本文通过几个比较常用的类型的Volume配置演示一下Volume的使用

  • 示例1---通过emptyDir共享数据
  • 示例2---使用HostPath挂载宿主机文件
  • 示例3---挂载NFS至容器

一、通过emptyDir共享数据

EmptyDir是一个特殊的Volume类型,与上述Volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,所以一般emptyDir用于Pod中的不同Container共享数据,比如一个Pod存在两个容器A和B,容器A需要使用容器B产生的数据,此时可以采用emptyDir共享数据,类似的使用如Filebeat收集容器内程序产生的日志。

默认情况下,emptyDir 卷支持节点上的任何介质,可能是 SSD、磁盘或网络存储,具体取 决于自身的环境。可以将 emptyDir.medium 字段设置为 Memory,让 Kubernetes 使用 tmpfs(内存支持的文件系统),虽然 tmpfs 非常快,但是 tmpfs 在节点重启时,数据同样会被清除,并且 设置的大小会被计入到 Container 的内存限制当中。

1.定义一个yaml文件

[root@k8s-master01 practice]# vim emptydir.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /opt
          name: share-volume
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory

2.重新部署

[root@k8s-master01 practice]# kubectl apply -f emptydir.yaml

3.查看pod状态

[root@k8s-master01 practice]# kubectl get po
NAME                     READY   STATUS    RESTARTS      AGE
nginx-d8f544fdd-qgllm           2/2     Running   0               12m

4.验证-进入nginx的容器创建文件后,在nginx2容器查看 (1)进入nginx容器后,进入/opt目录下创建123文件

[root@k8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm  -c nginx -- sh
root@nginx-d8f544fdd-qgllm:/# cd /opt
root@nginx-d8f544fdd-qgllm:/opt# touch 123

(2)进入nginx2容器后,进入/mnt目录下查看123文件是否创建成功

[root@k8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm  -c nginx2 -- bash
root@nginx-d8f544fdd-qgllm:/# cd /mnt/
root@nginx-d8f544fdd-qgllm:/mnt# ls
123

二、使用HostPath挂载宿主机文件

hostPath 卷可将节点上的文件或目录挂载到 Pod 上,用于 Pod 自定义日志输出或访问 Docker 内部的容器等。

hostPath常用类型有如下:

取值 行为
默认选项,意味着挂载 hostPath 卷之前不会执行任何检查
DirectoryOrCreate 如果给定的 path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 Kubelet 具有相同的组和权限
Directory 目录必须存在于给定的路径下
FileOrCreate 如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设 置为 0644,和 Kubelet 具有相同的组和所有权。
File 文件必须存在于给定路径中
Socket 在给定路径上必须存在的 UNIX 套接字
CharDevice 在给定路径上必须存在的字符设备
BlockDevice 在给定路径上必须存在的块设备

hostPath注意事项有如下:

  • HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。
  • 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
  • 下层主机上创建的文件或目录只能由 root 用户写入。 你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

下面进行hostPath示例说明,将主机的/etc/timezone文件挂载到 Pod 的/etc/timezone:

1.定义一个yaml文件

[root@k8s-master01 practice]# vim emptydir-hostpath.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /opt
          name: share-volume
        - mountPath: /etc/timezone
          name: timezone
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory
      - name: timezone
        hostPath:
          path: /etc/timezone
          type: File

2.重新部署

[root@k8s-master01 practice]# kubectl apply -f emptydir-hostpath.yaml

3.查看pod状态

[root@k8s-master01 practice]# kubectl get po
NAME                     READY   STATUS    RESTARTS      AGE
nginx-85fdffcd78-f9pwz           2/2     Running   0               12m

4.查看挂载情况,观察到设置的nginx已成功进行挂载;而未设置的nginx2未进行挂载

[root@k8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz  -c nginx -- cat /etc/timezone
Asia/Shanghai

[root@k8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz  -c nginx2 -- cat /etc/timezone
cat: can't open '/etc/timezone': No such file or directory

三、挂载NFS至容器

在生产环境中,考虑到数据的高可用性,仍然不建议使用NFS作为后端存储。因为NFS存在单点故障,很多企业并非对其实现高可用,并且NFS的性能存在很大的瓶颈。所以生产中,建议使用分布式存储,在公有云中建议使用公有云提供的NAS存储来替代NFS,并且NAS性能更好,可用性更高。NFS作为一个比较流行的远端存储工具,在非生产环境中是一个比较好用的选择,可以快速地搭建使用。

首先我们需要安装一下NFS

1.每台机器安装NFS客户端

$ yum install nfs-utils -y

2.在k8s-node01(192.168.1.34)启动nfs

[root@k8s-node01 ~]# systemctl start nfs-server

在k8s-node01(192.168.1.34)查看nfs支持的版本

[root@k8s-node01 ~]# cat /proc/fs/nfsd/versions
-2 +3 +4 +4.1 +4.2

3.在k8s-node01(192.168.1.34)上创建一个共享目录

[root@k8s-node01 ~]# mkdir  -p  /data/nfs/test_nfs

4.在k8s-node01(192.168.134)编辑授权文件,这里网段根据自己主机来定,我这里网段是192.168.1.0/24

[root@k8s-node01 ~]# vim /etc/exports
/data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

5.在k8s-node01(192.168.1.34)配置生效

[root@k8s-node01 ~]# exportfs -r

6.在k8s-node01(192.168.1.34)重新加载NFS

[root@k8s-node01 ~]# systemctl reload nfs-server

7.在k8s-master01上进行挂载测试

[root@k8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/
[root@k8s-master01 ~]# cd /mnt/
[root@k8s-master01 mnt]# touch test123

8.在k8s-node01(192.168.1.34)进行验证

[root@k8s-node01 ~]# cd /data/nfs/
[root@k8s-node01 nfs]# ls
test123  test_nfs

接下来,我们对上面的测试进行卸载

1.针对上诉测试进行卸载

[root@k8s-master01 ~]# umount /mnt/

最后,和emptyDir、HostPath的配置方法类似,NFS的Volume配置也是在Volumes字段中配置的,和emptyDir不同的是,NFS属于持久化存储的一种,在Pod删除或者重启后,数据依旧会存储在NFS节点上。

1.在k8s-master01上定义一个yaml文件

[root@k8s-master01 ~]# vim nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /opt
          name: share-volume
        - mountPath: /etc/timezone
          name: timezone
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
        - mountPath: /opt
          name: nfs-volume
      volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory
      - name: timezone
        hostPath:
          path: /etc/timezone
          type: File
      - name: nfs-volume
        nfs:
          server: 192.168.1.34
          path: /data/nfs/test_nfs

2.在k8s-master01重新部署

[root@k8s-master01 ~]# kubectl replace -f nfs.yaml

3.在k8s-master01查看pod状态

[root@k8s-master01 ~]# kubectl get po
NAME                            READY   STATUS        RESTARTS       AGE
nginx-5f974586bc-wv89n          2/2     Running       0              29s

4.在k8s-master01以容器的方式进入pod,查看挂载已经成功

[root@k8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n  -c nginx2 -- sh
/ # df -Th
Filesystem           Type            Size      Used Available Use% Mounted on
overlay              overlay        35.0G      4.5G     30.4G  13% /
tmpfs                tmpfs          64.0M         0     64.0M   0% /dev
tmpfs                tmpfs           3.9G         0      3.9G   0% /sys/fs/cgroup
/dev/mapper/centos-root
                     xfs            35.0G      4.5G     30.4G  13% /mnt
192.168.1.34:/data/nfs/test_nfs
                     nfs4           35.0G      3.6G     31.4G  10% /opt

5.在k8s-master01挂载目录中创建文件

[root@k8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n  -c nginx2 -- sh
/ # cd /opt/
/opt # touch 11111

6.在k8s-node01上进行结果验证

[root@k8s-node01 ~]# cd /data/nfs/test_nfs
[root@k8s-node01 test_nfs]# ls
11111

注意:Kubernetes所有的节点都需要安装上nfs-utils才可以正常挂载NFS。