Volume类型

volume是kubernetes Pod中多个容器访问的共享目录。volume被定义在pod上,被这个pod的多个容器挂载到相同或不同的路径下。volume的生命周期与pod的生命周期相同,pod内的容器停止和重启时一般不会影响volume中的数据。所以一般volume被用于持久化pod产生的数据。

Kubernetes提供了众多的volume类型,包括emptyDir、hostPath、nfs、glusterfs、cephfs、ceph rbd等。具体可以参考官方文档。

本篇文章我们简单说下emptyDir和hostPath。

emptyDir

emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配 一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,当Pod从node上移除时,emptyDir中的数据会被永久删除。

emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。

下面是一个pod挂载emptyDir的示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - image: test-webserver
    name: test-container
    volumeMounts:
    - name: cache-volume
      mountPath: /cache
  volumes:
  - name: cache-volume
    emptyDir: {}
hostPath

hostPath Volume为pod挂载宿主机上的目录或文件,使得容器可以使用宿主机的高速文件系统进行存储。缺点是,在k8s中,pod都是动态在各node节点上调度。当一个pod在当前node节点上启动并通过hostPath存储了文件到本地以后,下次调度到另一个节点上启动时,就无法使用在之前节点上存储的文件。

hostPath使用示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
 - image: test-webserver
    name: test-container
    volumeMounts:
    - name: test-volume
      mountPath: /www
  volumes:
 - name: test-volume
    hostPath:
      path: /data
NFS

nfs远程文件存储并没有一个“存储设备”需要挂载在宿主机上 所以不需要attach阶段

直接将远端 NFS 服务器的目录(比如:“/”目录)挂载到Volume的宿主机目录上即可

mount -t nfs <NFS服务器地址>:/ /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>

通过挂载操作,Volume的宿主机目录就成为了一个远程NFS目录的挂载点,后面你在这个目录里写入的所有文件,都会被保存在远程NFS服务器

所以,我们也就完成了对这个Volume宿主机目录的“持久化”

PV PVC

存储工程师把分布式存储系统上的总空间划分成一个一个小的存储块

  • k8s管理员根据存储块创建与之一一对应的pv资源
  • pv属于集群级别资源 不属于任何名称空间 定义的时候不能指定名称空间
  • 用户在创建pod的时候同时创建与pv一一对应的pvc资源

创建Pod的时候,系统里并没有合适的PV跟它定义的PVC绑定 也就是说此时容器想要使用的Volume不存在.这时候Pod的启动就会报错

动态卷供应

Kubernetes只会将StorageClass相同的PVC和PV绑定起来

  • 自动创建PV的机制Dynamic Provisioning
  • 人工管理PV的方式就叫作Static Provisioning
  • StorageClass对象就是创建PV的模板
定义StorageClass一般包含Name,后端使用存储插件类型,存储插件需要使用到的参数等信息 定义好之后相当于定义了一块巨大的存储磁盘

当pvc中定义的storageClassName和StorageClass的Name相同的时候那么StorageClass会自动从巨大的存储磁盘创建一个指定storage大小的pv,创建的pv和pvc进行绑定

StorageClass对象会定义如下两个部分内容

  1. PV的属性. 比如,存储类型
  2. 创建这种PV需要用到的存储插件. 比如Ceph等等

k8s根据用户提交的PVC中指定的storageClassName的属性值找到对应的StorageClass.然后调用该StorageClass声明的存储插件创建出需要的PV

有了Dynamic Provisioning机制,运维人员只需要在Kubernetes集群里创建出数量有限的StorageClass对象就可以了

当开发人员提交了包含StorageClass字段的PVC之后,Kubernetes就会根据这个StorageClass创建出对应的PV

在没有StorageClass的情况下运维人员对开发人员定义的每一个pvc都要手动创建一个对应的pv与其进行绑定 这样就会大大的增加创建pv的工作量