zoukankan      html  css  js  c++  java
  • 云原生k8s 应用存储与持久化数据卷

    本文主题

    1. K8s Volume 使用场景
    2. PVC/PV/StorageClass 基本操作和概念解析
    3. PVC+PV 体系的设计与实现原理

    一、Volumes 介绍

    Pod Volumes

    首先来看一下 Pod Volumes 的使用场景:

    • 场景一:如果 pod 中的某一个容器在运行时异常退出,被 kubelet 重新拉起之后,如何保证之前容器产生的重要数据没有丢失?
    • 场景二:如果同一个 pod 中的多个容器想要共享数据,应该如何去做?

    以上两个场景,其实都可以借助 Volumes 来很好地解决,接下来首先看一下 Pod Volumes 的常见类型:

    1. 本地存储,常用的有 emptydir/hostpath;
    2. 网络存储:网络存储当前的实现方式有两种,一种是 in-tree,它的实现的代码是放在 K8s 代码仓库中的,随着k8s对存储类型支持的增多,这种方式会给k8s本身的维护和发展带来很大的负担;而第二种实现方式是 out-of-tree,它的实现其实是给 K8s 本身解耦的,通过抽象接口将不同存储的driver实现从k8s代码仓库中剥离,因此out-of-tree 是后面社区主推的一种实现网络存储插件的方式;
    3. Projected Volumes:它其实是将一些配置信息,如 secret/configmap 用卷的形式挂载在容器中,让容器中的程序可以通过POSIX接口来访问配置数据;
    4. PV 与 PVC 就是今天要重点介绍的内容。

    k8s支持的卷类型

    cephfs

    cephfs 卷允许你将现存的 CephFS 卷挂载到 Pod 中。 不像 emptyDir 那样会在 Pod 被删除的同时也会被删除,cephfs 卷的内容在 Pod 被删除 时会被保留,只是卷被卸载了。这意味着 cephfs 卷可以被预先填充数据,且这些数据可以在 Pod 之间共享。同一 cephfs 卷可同时被多个写者挂载。

    说明: 在使用 Ceph 卷之前,你的 Ceph 服务器必须已经运行并将要使用的 share 导出(exported)。

    更多信息请参考 CephFS 示例 https://github.com/kubernetes/examples/tree/master/volumes/cephfs/

    configMap

    configMap 卷 提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被 Pod 中运行的 容器化应用使用。

    引用 configMap 对象时,你可以在 volume 中通过它的名称来引用。 你可以自定义 ConfigMap 中特定条目所要使用的路径。 下面的配置显示了如何将名为 log-config 的 ConfigMap 挂载到名为 configmap-pod 的 Pod 中:

    apiVersion: v1
    kind: Pod
    metadata:
      name: configmap-pod
    spec:
      containers:
        - name: test
          image: busybox
          volumeMounts:
            - name: config-vol
              mountPath: /etc/config
      volumes:
        - name: config-vol
          configMap:
            name: log-config
            items:
              - key: log_level
                path: log_level
    

    log-config ConfigMap 以卷的形式挂载,并且存储在 log_level 条目中的所有内容 都被挂载到 Pod 的 /etc/config/log_level 路径下。 请注意,这个路径来源于卷的 mountPath 和 log_level 键对应的 path

    说明:
    • 在使用 ConfigMap 之前你首先要创建它。
    • 容器以 subPath 卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新。
    • 文本数据挂载成文件时采用 UTF-8 字符编码。如果使用其他字符编码形式,可使用 binaryData 字段。

    emptyDir

    当 Pod 分派到某个 Node 上时,emptyDir 卷会被创建,并且在 Pod 在该节点上运行期间,卷一直存在。 就像其名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。

    说明: 容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃期间 emptyDir 卷中的数据是安全的。

    emptyDir 的一些用途:

    • 缓存空间,例如基于磁盘的归并排序。
    • 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
    • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

    取决于你的环境,emptyDir 卷存储在该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储。但是,你可以将 emptyDir.medium 字段设置为 "Memory",以告诉 Kubernetes 为你挂载 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。

    说明: 当启用 SizeMemoryBackedVolumes 特性门控时, 你可以为基于内存提供的卷指定大小。 如果未指定大小,则基于内存的卷的大小为 Linux 主机上内存的 50%。
     
     

    emptyDir 配置示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}


    glusterfs

    glusterfs 卷能将 Glusterfs (一个开源的网络文件系统) 挂载到你的 Pod 中。不像 emptyDir 那样会在删除 Pod 的同时也会被删除,glusterfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 glusterfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。 GlusterFS 可以被多个写者同时挂载。

    说明: 在使用前你必须先安装运行自己的 GlusterFS。

    更多详情请参考 GlusterFS 示例

    hostPath

    警告:

    HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。

    如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问, 则必须要求 volumeMounts 使用 readOnly 挂载以使策略生效。

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

    hostPath 配置示例: 

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /test-pd
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          # 宿主上目录位置
          path: /data
          # 此字段为可选
          type: Directory


    rbd

    rbd 卷允许将 Rados 块设备 卷挂载到你的 Pod 中. 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,rbd 卷的内容在删除 Pod 时 会被保存,卷只是被卸载。 这意味着 rbd 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

    注意: 在使用 RBD 之前,你必须安装运行 Ceph。

    RBD 的一个特性是它可以同时被多个用户以只读方式挂载。 这意味着你可以用数据集预先填充卷,然后根据需要在尽可能多的 Pod 中并行地使用卷。 不幸的是,RBD 卷只能由单个使用者以读写模式安装。不允许同时写入。

    更多详情请参考 RBD 示例

     

  • 相关阅读:
    js设计模式-迭代器模式
    js设计模式-代理模式
    js设计模式-策略模式
    js设计模式-单例模式
    js设计模式中的高阶函数的一些应用
    深入react技术栈记录(二)
    深入react技术栈记录(一)
    响应式开发(1)
    Angular Js 与bootstrap, angular 与 vue.js
    for in 中的index
  • 原文地址:https://www.cnblogs.com/shanghai1918/p/15529455.html
Copyright © 2011-2022 走看看