Kubernetes本地持久化方案

Kubernetes中的本地存储意味着在每一个节点服务器上本地可用的存储设备或文件系统。本文介绍Kubernetes中现有的本地存储解决方案,包括官方原生支持的存储方式以及社区的一些常见方案。node

目前官方支持如下3种本地存储方式:git

  • emptyDir
  • hostPath
  • Local Persistent Volume

emptyDir

当 Pod 指定到某个节点上时,首先建立的是一个emptyDir卷,而且只要 Pod 在该节点上运行,卷就一直存在。 就像它的名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载emptyDir卷的路径可能相同也可能不一样,可是这些容器均可以读写emptyDir卷中相同的文件。 当 Pod 由于某些缘由被从节点上删除时,emptyDir卷中的数据也会永久删除。github

注意:容器崩溃并不会致使 Pod 被从节点上移除,所以容器崩溃时 `emptyDir` 卷中的数据是安全的。

emptyDir 的一些用途:docker

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

默认状况下, emptyDir 卷存储在支持该节点所使用的介质上;这里的介质能够是磁盘或 SSD 或网络存储,这取决于您的环境。 可是,您能够将 emptyDir.medium 字段设置为 "Memory",以告诉 Kubernetes 为您安装 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度很是快,可是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,而且您所写入的全部文件都会计入容器的内存消耗,受容器内存限制约束。数据库

emptyDir的位置应该在运行pod的给定节点上的/var/lib/kubelet/pods/{podid}/volumes/kubernetes.io~empty-dir/ 目录下。ubuntu

Pod 示例

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - image: my-app-image
    name: my-app
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir: {}
Pod中的全部容器共享使用emptyDir卷。所以,咱们使用emptyDir的一个场景是,Pod中init容器负责到配置中心或是秘钥管理中心拉取一些配置,而后写入到emptyDir中,这样业务容器就能够读取到配置。

hostPath

hostPath卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。 虽然这不是大多数 Pod 须要的,可是它为一些应用程序提供了强大的逃逸机会。后端

例如,hostPath 的一些用法有:api

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

除了必需的 path 属性以外,用户能够选择性地为 hostPath 卷指定 type缓存

例如:安全

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - image: my-app-image
    name: my-app
    volumeMounts:
      - mountPath: /test-pd
        name: test-volume
  volumes:
  - name: test-volume 
    hostPath:
    path: /data  #directory on host
    type: Directory #optional

type: Directory定义目录必须在主机上已经存在,所以在使用主机路径以前,您必须首先在该目录中手动建立它。

类型的其余值是DirectoryOrCreateFileFileOrCreate。若是* OrCreate在主机上尚不存在,将动态建立。

使用此卷类型的缺点:

  • 因为不一样节点的hostPath文件/目录内容不一样,所以同一模板建立的Pod在不一样节点上的行为可能有所不一样
  • 用hostPath在主机上建立的文件或目录只能由root写入。这意味着您要么须要以root用户身份运行容器进程,要么将主机上的文件权限修改成非root用户可写,这可能会致使安全问题
  • 不该该将hostPath卷类型用于StatefulSets

Local Persistent Volume

Local PV(本地持久化存储),指的就是利用机器上的磁盘来存放业务须要持久化的数据,和远端存储相似,此时数据依然独立于 Pod 的生命周期,即便业务 Pod 被删除,数据也不会丢失。

同时,和远端存储相比,本地存储能够避免网络 IO 开销,拥有更高的读写性能,因此分布式文件系统和分布式数据库这类对 IO 要求很高的应用很是适合本地存储。

可是,在使用本地永久卷时,有一些重要的限制和注意事项须要考虑:

  • 使用本地存储将您的应用程序绑定到特定节点,从而使您的应用程序难以调度。使用本地存储的应用程序应指定较高的优先级,以便在须要时能够抢占不须要本地存储的较低优先级的Pod。
  • 若是该节点或本地卷遇到故障并变得不可访问,则该容器也将变得不可访问。要从这些状况中恢复过来,可能须要手动干预,外部控制器或操做员。
  • 尽管大多数远程存储系统都实现了同步复制,可是大多数本地磁盘产品并不能提供数据持久性保证。意味着磁盘或节点丢失可能致使该磁盘上的全部数据丢失。

Local PV和hostPath区别

为了更好地了解本地持久卷的好处,将其与HostPath卷进行比较颇有用。 HostPath卷将主机节点文件系统中的文件或目录装载到Pod中。一样,本地永久卷将本地磁盘或分区安装到Pod中。

最大的区别是Kubernetes调度程序了解本地持久卷属于哪一个节点。对于HostPath卷,调度程序可能会将引用HostPath卷的pod移至其余节点,从而致使数据丢失。可是对于本地持久卷,Kubernetes调度程序可确保始终将使用本地持久卷的容器调度到同一节点。

尽管能够经过持久卷声明(PVC)引用HostPath卷,也能够在pod定义中直接内联HostPath卷,可是只能经过PVC引用本地持久卷。因为Persistent Volume对象是由管理员管理的,所以,Pod不能访问主机上的任何路径,所以能够提供额外的安全优点。

其余好处包括支持在安装期间格式化块设备以及使用fsGroup进行卷全部权。

如何使用Local PV?

工做负载可使用与远程存储后端相同的PersistentVolumeClaim接口请求本地持久卷。这使得跨集群,云和本地环境轻松交换存储后端。

首先,应该建立一个StorageClass来设置volumeBindingMode:WaitForFirstConsumer来启用卷拓扑感知调度。该模式指示Kubernetes等待绑定PVC,直到Pod开始使用它。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

而后,能够配置并运行外部静态预配器,觉得节点上的全部本地磁盘建立PV。

$ kubectl get pv
NAME                CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM  STORAGECLASS   REASON      AGE
local-pv-27c0f084   368Gi      RWO            Delete           Available          local-storage              8s
local-pv-3796b049   368Gi      RWO            Delete           Available          local-storage              7s
local-pv-3ddecaea   368Gi      RWO            Delete           Available          local-storage              7s

以后,经过建立带有volumeClaimTemplates的PVC和Pod或StatefulSet,工做负载能够开始使用PV。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: local-test
spec:
  serviceName: "local-service"
  replicas: 3
  selector:
    matchLabels:
      app: local-test
  template:
    metadata:
      labels:
        app: local-test
    spec:
      containers:
      - name: test-container
        image: k8s.gcr.io/busybox
        command:
        - "/bin/sh"
        args:
        - "-c"
        - "sleep 100000"
        volumeMounts:
        - name: local-vol
          mountPath: /usr/test-pod
  volumeClaimTemplates:
  - metadata:
      name: local-vol
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "local-storage"
      resources:
        requests:
          storage: 368Gi

一旦StatefulSet启动并运行,PVC都将绑定:

$ kubectl get pvc
NAME                     STATUS   VOLUME              CAPACITY   ACCESS MODES   STORAGECLASS      AGE
local-vol-local-test-0   Bound    local-pv-27c0f084   368Gi      RWO            local-storage     3m45s
local-vol-local-test-1   Bound    local-pv-3ddecaea   368Gi      RWO            local-storage     3m40s
local-vol-local-test-2   Bound    local-pv-3796b049   368Gi      RWO            local-storage     3m36s

当再也不须要磁盘时,能够删除PVC。外部静态预配器将清理磁盘,并使PV再次可用。

社区的一些方案:

  • TopoLVM

TopoLVM

TopoLVM,一个用于本地存储的新CSI插件,可以使用LVM动态配置卷。它实现了动态卷配置,原始块卷,文件系统指标,并将实如今线卷大小调整和临时卷。

架构

TopoLVM 组件包括:

  • topolvm-controller: CSI controller
  • topolvm-scheduler: 用于TopoLVM 的scheduler extender
  • topolvm-node: CSI node 服务
  • lvmd: 管理LVM卷的gRPC 服务

特性

  • 动态配置:建立PersistentVolumeClaim对象时动态建立卷。
  • 原始块体积:这些体积可用做容器内的块设备。
  • 拓扑:TopoLVM使用CSI拓扑功能将Pod调度到LVM卷存在的节点。
  • 扩展的调度程序:TopoLVM扩展了通用Pod调度程序,以对具备更大存储容量的节点进行优先级排序。
  • 监控指标:使用状况统计信息从kubelet中导出为Prometheus指标。

因为不是k8s原生方案,因此在使用前,咱们须要先安装。关于安装,你们参考官方文档便可。

示例:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: topolvm-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: topolvm-provisioner
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app.kubernetes.io/name: my-pod
spec:
  containers:
  - name: ubuntu
    image: quay.io/cybozu/ubuntu:18.04
    command: ["/usr/local/bin/pause"]
    volumeMounts:
    - mountPath: /test1
      name: my-volume
  volumes:
    - name: my-volume
      persistentVolumeClaim:
        claimName: topolvm-pvc
相关文章
相关标签/搜索