本文发表已超过一年。较旧的文章可能包含过时内容。请检查页面信息自发布以来是否已不正确。

Raw Block Volume 支持进阶至 Beta

Kubernetes v1.13 将原始块存储卷(raw block volume)的支持升级到 Beta。此功能允许将持久卷作为块设备(而不是挂载的文件系统)暴露给容器内部。

什么是块设备?

块设备可以实现以固定大小块随机访问数据。硬盘驱动器、固态硬盘和 CD-ROM 驱动器都是块设备的例子。

通常,持久存储采用分层方式实现,在块设备(如机械硬盘或固态硬盘)之上有一个文件系统(如 ext4)。应用程序读写的是文件而不是直接操作块。操作系统使用指定的文件系统负责将文件读写到底层设备上的块。

值得注意的是,尽管整个磁盘是块设备,但磁盘分区也是,来自存储区域网络 (SAN) 设备的 LUN 也是。

为什么要将原始块存储卷添加到 Kubernetes?

有一些特殊应用需要直接访问块设备,例如,文件系统层会引入不必要的开销。最常见的情况是数据库,它们更倾向于直接在底层存储上组织数据。原始块设备也常用于本身实现某种存储服务的软件(软件定义存储系统)。

从程序员的角度来看,块设备是一个非常大的字节数组,通常有最小的读写粒度,通常是 512 字节,但经常是 4K 或更大。

随着在 Kubernetes 内部运行数据库软件和存储基础设施软件变得越来越普遍,Kubernetes 对原始块设备支持的需求也变得更加重要。

哪些卷插件支持原始块?

截至本文发布时,以下树内(in-tree)卷类型支持原始块:

  • AWS EBS
  • Azure Disk
  • Cinder
  • Fibre Channel
  • GCE PD
  • iSCSI
  • 本地卷
  • RBD (Ceph)
  • Vsphere

树外(out-of-tree)的 CSI 卷驱动程序 也可能支持原始块存储卷。Kubernetes CSI 对原始块存储卷的支持目前处于 Alpha 阶段。请参阅此处的文档。

Kubernetes 原始块存储卷 API

原始块存储卷与普通卷有很多共同点。两者都是通过创建绑定到 PersistentVolume 对象的 PersistentVolumeClaim 对象来请求的,并且通过将其包含在 PodSpec 的 volumes 数组中附加到 Kubernetes 的 Pod。

然而,有两个重要的区别。首先,要请求一个原始块 PersistentVolumeClaim,你必须在 PersistentVolumeClaimSpec 中设置 volumeMode = "Block"。将 volumeMode 留空等同于指定 volumeMode = "Filesystem",这将导致传统行为。PersistentVolumes 在其 PersistentVolumeSpec 中也有一个 volumeMode 字段,并且 "Block" 类型的 PVC 只能绑定到 "Block" 类型的 PV,而 "Filesystem" 类型的 PVC 只能绑定到 "Filesystem" 类型的 PV。

其次,当在你的 Pod 中使用原始块存储卷时,你必须在 PodSpec 的 Container 部分指定一个 VolumeDevice,而不是 VolumeMountVolumeDevicesdevicePaths 而不是 mountPaths,在容器内部,应用程序将看到该路径下的设备,而不是挂载的文件系统。

应用程序打开、读取和写入容器内部的设备节点,就像它们在非容器化或虚拟化环境中与系统上的任何块设备交互一样。

创建新的原始块 PVC

首先,确保你选择的存储类关联的供应器支持原始块。然后创建 PVC。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Block
  storageClassName: my-sc
  resources:
    requests:
    storage: 1Gi

使用原始块 PVC

当你在 Pod 定义中使用 PVC 时,你可以选择块设备的设备路径,而不是文件系统的挂载路径。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: busybox
      command:
        - sleep
        - “3600”
      volumeDevices:
        - devicePath: /dev/block
          name: my-volume
      imagePullPolicy: IfNotPresent
  volumes:
    - name: my-volume
      persistentVolumeClaim:
        claimName: my-pvc

作为存储厂商,如何向我的 CSI 插件添加原始块设备支持?

对 CSI 插件的原始块支持仍处于 Alpha 阶段,但现在就可以添加支持。 CSI 规范详细说明了如何处理具有 BlockVolume 能力而不是 MountVolume 能力的卷请求。CSI 插件可以同时支持这两种卷,也可以只支持其中一种。更多详细信息请参阅此处的文档。

问题/陷阱

由于块设备实际上是设备,因此可以在容器内部对其执行文件系统卷无法执行的底层操作。例如,实际是 SCSI 磁盘的块设备支持使用 Linux ioctls 向设备发送 SCSI 命令。

不过,默认情况下,Linux 不允许容器从容器内部向磁盘发送 SCSI 命令。为了实现这一点,你必须向容器安全上下文授予 SYS_RAWIO 能力。请参阅此处的文档。

此外,虽然 Kubernetes 保证会将块设备提供给容器,但不能保证它实际上是 SCSI 磁盘或任何其他类型的磁盘。用户必须确保为 Pod 使用所需的磁盘类型,或者只部署能够处理各种块设备类型的应用程序。

如何了解更多?

查看关于快照功能的更多文档:原始块存储卷支持

如何参与?

加入 Kubernetes 存储 SIG 和 CSI 社区,帮助我们添加更多出色的功能并改进现有功能,例如原始块存储!

https://github.com/kubernetes/community/tree/master/sig-storage https://github.com/container-storage-interface/community/blob/master/README.md

特别感谢所有帮助向 Kubernetes 添加块存储卷支持的贡献者,包括: