入门Kubernetes-数据存储

一、Volume介绍:

 在k8s中Pod的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。

 为了持久化保存容器数据,k8s 提供了卷(Volume)的抽象概念来解决上述问题。

 卷(Volume)的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。

 Kubernetes Volume 支持多种卷类型,包括 emptyDir、hostPath、nfs、local、configMap、AWSElasticBlockStore、Cinder、CSI等。

  按照存储可大概划分为:

  入门Kubernetes-数据存储

  临时存储:emptydir   

  半持久化存储:hostpath

  持久化存储:nfs、ceph、Cinder等

 接下来分别介绍几种常用类型:emptyDir、hostPath、nfs(PV、PVC)

二、Volume:emptyDir

 emptyDir 是最基础的 Volume 类型。正如其名字所示,一个 emptyDir Volume 是 Host 上的一个空目录。

 emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。(emptyDir Volume 的生命周期与 Pod 一致

 Pod 中的所有容器都可以共享 Volume,它们可以指定各自的挂载路径。

 验证示例:

apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  containers:
    - image: busybox
      name: producer
      volumeMounts:
        - mountPath: /producer_dir #挂载到容器中的路径
          name: shared-volume
      args:
        - /bin/sh
        - -c
        - echo "hello world" > /producer_dir/hello; sleep 3000
    - image: busybox
      name: consumer
      volumeMounts:
        - mountPath: /consumer_dir #挂载到容器中的路径
          name: shared-volume
      args:
        - /bin/sh
        - -c
        - cat /consumer_dir/hello; sleep 3000
  volumes:
    - name: shared-volume
      emptyDir: {} #指定存储方式为emptydir
  1. 创建一个名为[shared-volume]的emptyDir的卷
  2. 容器producer 将 shared-volume挂载到 producer_dir 目录
  3. 容器producer 通过echo 命令向hello 文件中写入文本-hello world
  4. 容器consumer 将 shared-volume挂载到 consumer_dir目录
  5. 容器consumer 通过cat命令读取consumer_dir中hello文件内容

  通过命令:kubectl logs 查看读取内容。

# 输出producer-consumer Pod中容器 consumer 的日志:
kubectl logs producer-consumer -c consumer
hello world

  显示容器 consumer 成功读取到 producer 写入的数据,验证了两个容器共享 emptyDir Volume。

三、Volume:hostPath

 hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大应急方式。

 hostPath 的一些用法有:

  • 运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径。
  • 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys
  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

 除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type,下表为type取值

取值 行为
  空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory 在给定路径上必须存在的目录。
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File 在给定路径上必须存在的文件。
Socket 在给定路径上必须存在的 UNIX 套接字。
CharDevice 在给定路径上必须存在的字符设备。
BlockDevice 在给定路径上必须存在的块设备。

 hostPath示例:

apiVersion: v1
kind: Pod
metadata:
  name: localpod
spec:
  containers:
    - image: busybox
      name: local
      volumeMounts:
        - mountPath: /localdir #挂载到容器中的路径
          name: mydir
        - mountPath: loacl.txt
          name: myfile
      args:
        - /bin/sh
        - -c
        - echo "local dir test" > /localdir/test.txt; 
        - -c
        - cat loacl.txt; 
  volumes:
    - name: mydir
      hostPath:
        # 确保文件所在目录成功创建。
        path: /var/local
        type: DirectoryOrCreate
    - name: myfile
      hostPath:
        # 确保文件创建成功
        path: /var/local/test.txt
        type: FileOrCreate

  步骤:

   1、创建两个hostPath类型的Volume

   2、将这两个卷都挂载到local容器中

   3、容器启动时,写入文件内容“local dir test”,并读取出来。

四、Volume:持久化存储-nfs

 说到持久化存储:就需要提k8s中提供的重要的几种资源类型:

  • PersistentVolume (PV): 外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。
  • StorageClass:另外一种提供存储资源的方式, 提供更多的层级选型, 如iops等参数。 但是具体的参数与提供方是绑定的。 如aws和gce它们提供的storageclass的参数可选项是有不同的。
  • PersistentVolumeClaim (PVC):是对 PV 的申请 (Claim)。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernetes 会查找并提供满足条件的 PV。

 PersistentVolume :

 生命周期:

  • Provisioning- 配置阶段, 分为static, dynamic两种方式。静态的方式是创建一系列的pv,然后pvc从pv中请求。 动态的方式是基于storageclass的。
  • Binding - 绑定阶段, pvc根据请求的条件筛选并绑定对应的pv。 一定pvc绑定pv后, 就会排斥其它绑定,即其它pvc无法再绑定同一个pv,即使这个pv设定的access mode允许多个node读写。 此外 ,pvc 如何匹配不到相应条件的pv, 那么就会显示unbound状态, 直到匹配为止。 需要注意的是,pvc请求100Gi大小的存储,即使用户创建了很多50Gi大小的存储, 也是无法被匹配的。
  • Using- 使用阶段, pods 挂载存储, 即在pod的template文件中定义volumn使用某个pvc。
  • Releasing - 释放阶段, 当pvc对象被删除后, 就处于释放阶段。 在这个阶段, 使用的pv还不能被其它的pvc请求。 之前数据可能还会留存下来, 取决于用户在pv中设定的policy, 见persistentVolumeReclaimPolicy。
  • Reclaiming - 重声明阶段。 到这个阶段, 会告诉cluster如何处理释放的pv。 数据可能被保留(需要手工清除), 回收和删除。动态分配的存储总是会被删除掉的。
  • Recycling - 回收阶段。回收阶段会执行基本的递归删除(取决于volumn plugins的支持),把pv上的数据删除掉, 以使pv可以被新的pvc请求。 用户也可以自定义一个 recycler pod , 对数据进行删除。

 卷模式:

  PV支持两种卷模式:

  • Filesystem  卷会被 Pod 挂载(Mount) 到某个目录。 如果卷的存储来自某块设备而该设备目前为空,Kuberneretes 会在第一次挂载卷之前 在设备上创建文件系统。
  • Block将卷作为原始块设备来使用。 这类卷以块设备的方式交给 Pod 使用,其上没有任何文件系统。 这种模式对于为 Pod 提供一种使用最快可能方式来访问卷而言很有帮助,Pod 和 卷之间不存在文件系统层。另外,Pod 中运行的应用必须知道如何处理原始块设备。

 访问模式:

  PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。 如下表所示,提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为 对应卷所支持的模式值。 例如,NFS 可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器 上以只读的方式导出。每个 PV 卷都会获得自身的访问模式集合,描述的是 特定 PV 卷的能力。

访问模式有:

    • ReadWriteOnce (RWO)  -- 卷可以被一个节点以读写方式挂载;
    • ReadOnlyMany (ROX)    -- 卷可以被多个节点以只读方式挂载;
    • ReadWriteMany (RWX)  -- 卷可以被多个节点以读写方式挂载
卷插件 ReadWriteOnce ReadOnlyMany ReadWriteMany
AWSElasticBlockStore ? - -
AzureFile ? ? ?
AzureDisk ? - -
CephFS ? ? ?
Cinder ? - -
CSI 取决于驱动 取决于驱动 取决于驱动
FC ? ? -
FlexVolume ? ? 取决于驱动
Flocker ? - -
GCEPersistentDisk ? ? -
Glusterfs ? ? ?
HostPath ? - -
iSCSI ? ? -
Quobyte ? ? ?
NFS ? ? ?
RBD ? ? -
VsphereVolume ? - - (Pod 运行于同一节点上时可行)
PortworxVolume ? - ?
ScaleIO ? ? -
StorageOS ? - -

 回收策略:

  目前的回收策略有:

  • Retain -- 手动回收
  • Recycle -- 基本擦除 (rm -rf /thevolume/*)
  • Delete -- 诸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷这类关联存储资产也被删除

  目前,仅 NFS 和 HostPath 支持回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)

 持久化存储验证:

  1、nfs服务搭建:

 所有节点安装nfs

yum install -y nfs-common nfs-utils 

 在master节点创建共享目录

[root@k8s-master k8s]# mkdir /nfsdata

 授权共享目录

[root@k8s-master k8s]# chmod 666 /nfsdata

 编辑exports文件

[root@k8s-master k8s]# cat /etc/exports
/nfsdata *(rw,no_root_squash,no_all_squash,sync)

 配置生效

  [root@k8s-master k8s]# export -r

 启动rpc和nfs(注意顺序)

[root@k8s-master k8s]# systemctl start rpcbind
[root@k8s-master k8s]# systemctl start nfs

2、创建PV:

#创建Pv:name-pv01
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
  labels:
    name: pv01
spec:
  # 所有节点可共享访问
  accessModes: ["ReadWriteMany"]
# 回收策略:清除PV数据
persistentVolumeReclaimPolicy:Recycle
# 指定PV的Class为 nfs
storageClassName:nfs capacity:
# Pv大小1G storage: 1Gi #nfs 服务设置,以及目录设置 nfs: server: 192.168.115.6 path: /home

  3、创建PVC:

#创建名为mypvc的PVC
apiVersion: v1
kind: PersisitentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessmodes: ["ReadWriteMany"]   #所有节点可读写
  resources:                  #指定资源说明
    requests:                  #指定请求
      storage: 4Gi            #指定请求存储空间的大小      

  4、创建POD使用PVC

#创建Pod并使用PVC
apiVersion: v1
kind: Pod
metadata:
  name: pvnginx
  labels:
    app: pvnginx
spec:
  containers:
    - name: my-pvnginx
      image: nginx
      ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
       volumeMounts:
         - name: html
           mountPath: /data/html
  volumes:
    - name: html
      persistentVolumeClaim:    #指明使用pvc模式
        claimname: mypvc         #指明使用的pvc名称

总结:  

 1、对于不需要持久化的数据可采用emptyDir类型卷来存储相关数据,其生命周期同Pod相同

 2、当需要访问当前主机文件时,可以采用hostPath类型的卷来实现

 3、PV、PVC在实际场景中应用较多,需要了解透彻:包括PV的动/静态创建、PVC、生命周期等基本概念

参考:

  https://kubernetes.io/zh/docs/concepts/storage/ 

https://kubernetes.io/zh/docs/concepts/storage/

入门Kubernetes-数据存储

上一篇:作用域与作用域链 - js函数高级


下一篇:json序列化