阅读本文前建议你熟悉一下 Pod

    Docker 也有 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录。 Docker 提供卷驱动程序,但是其功能非常有限。

    Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁持久卷。 对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。

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

    使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的 的初始内容以及挂载在容器中的卷(如果定义了的话)所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作,如果被允许的话,都会影响接下来容器中进程访问文件系统时所看到的内容。

    卷挂载在镜像中的指定路径下。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。

    卷不能挂载到其他卷之上(不过存在一种 的相关机制),也不能与其他卷有硬链接。

    卷类型

    Kubernetes 支持下列类型的卷:

    特性状态: Kubernetes v1.17 [deprecated]

    awsElasticBlockStore 卷将 Amazon Web服务(AWS) 挂载到你的 Pod 中。与 emptyDir 在 Pod 被删除时也被删除不同,EBS 卷的内容在删除 Pod 时会被保留,卷只是被卸载掉了。 这意味着 EBS 卷可以预先填充数据,并且该数据可以在 Pod 之间共享。

    说明: 你在使用 EBS 卷之前必须使用 aws ec2 create-volume 命令或者 AWS API 创建该卷。

    使用 awsElasticBlockStore 卷时有一些限制:

    • Pod 运行所在的节点必须是 AWS EC2 实例。
    • 这些实例需要与 EBS 卷在相同的地域(Region)和可用区(Availability-Zone)。
    • EBS 卷只支持被挂载到单个 EC2 实例上。

    创建 EBS 卷

    在将 EBS 卷用到 Pod 上之前,你首先要创建它。

    确保该区域与你的群集所在的区域相匹配。还要检查卷的大小和 EBS 卷类型都适合你的用途。

    AWS EBS 配置示例

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: test-ebs
    5. spec:
    6. containers:
    7. - image: k8s.gcr.io/test-webserver
    8. name: test-container
    9. volumeMounts:
    10. - mountPath: /test-ebs
    11. name: test-volume
    12. volumes:
    13. - name: test-volume
    14. # 此 AWS EBS 卷必须已经存在
    15. awsElasticBlockStore:
    16. volumeID: "<volume-id>"
    17. fsType: ext4

    如果 EBS 卷是分区的,你可以提供可选的字段 partition: "<partition number>" 来指定要挂载到哪个分区上。

    AWS EBS CSI 卷迁移

    特性状态: Kubernetes v1.17 [beta]

    如果启用了对 awsElasticBlockStoreCSIMigration 特性支持,所有插件操作都不再指向树内插件(In-Tree Plugin),转而指向 ebs.csi.aws.com 容器存储接口(Container Storage Interface,CSI)驱动。 为了使用此特性,必须在集群中安装 , 并确保 CSIMigrationCSIMigrationAWS Beta 功能特性被启用。

    AWS EBS CSI 迁移结束

    特性状态: Kubernetes v1.17 [alpha]

    要禁止控制器管理器和 kubelet 加载 awsElasticBlockStore 存储插件, 请将 InTreePluginAWSUnregister 标志设置为 true

    azureDisk (已弃用)

    特性状态: Kubernetes v1.19 [deprecated]

    azureDisk 卷类型用来在 Pod 上挂载 Microsoft Azure 数据盘(Data Disk) 。 若需了解更多详情,请参考 。

    azureDisk 的 CSI 迁移

    特性状态: Kubernetes v1.24 [stable]

    启用 azureDiskCSIMigration 特性后,所有插件操作从现有的树内插件重定向到 disk.csi.azure.com 容器存储接口(CSI)驱动程序。 为了使用此特性,必须在集群中安装 , 并且 CSIMigration 特性必须被启用。

    azureDisk CSI 迁移完成

    特性状态: Kubernetes v1.21 [alpha]

    要禁止控制器管理器和 kubelet 加载 azureDisk 存储插件, 请将 InTreePluginAzureDiskUnregister 标志设置为 true

    azureFile (已弃用)

    特性状态: Kubernetes v1.21 [deprecated]

    azureFile 卷类型用来在 Pod 上挂载 Microsoft Azure 文件卷(File Volume)(SMB 2.1 和 3.0)。 更多详情请参考 azureFile 卷插件

    azureFile CSI 迁移

    特性状态: Kubernetes v1.21 [beta]

    启用 azureFileCSIMigration 特性后,所有插件操作将从现有的树内插件重定向到 file.csi.azure.com 容器存储接口(CSI)驱动程序。要使用此特性,必须在集群中安装 Azure 文件 CSI 驱动程序, 并且 CSIMigrationCSIMigrationAzureFile 必须被启用。

    Azure 文件 CSI 驱动尚不支持为同一卷设置不同的 fsgroup。 如果 CSIMigrationAzureFile 特性被启用,用不同的 fsgroup 来使用同一卷也是不被支持的。

    azureDisk CSI 迁移完成

    特性状态: Kubernetes v1.21 [alpha]

    要禁止控制器管理器和 kubelet 加载 azureDisk 存储插件, 请将 InTreePluginAzureDiskUnregister 标志设置为 true

    cephfs

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

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

    更多信息请参考 CephFS 示例

    cinder (已弃用)

    特性状态: Kubernetes v1.18 [deprecated]

    说明:

    Kubernetes 必须配置了 OpenStack Cloud Provider。

    cinder 卷类型用于将 OpenStack Cinder 卷挂载到 Pod 中。

    Cinder 卷示例配置

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: test-cinder
    5. spec:
    6. containers:
    7. - image: k8s.gcr.io/test-webserver
    8. name: test-cinder-container
    9. volumeMounts:
    10. - mountPath: /test-cinder
    11. name: test-volume
    12. volumes:
    13. - name: test-volume
    14. # 此 OpenStack 卷必须已经存在
    15. cinder:
    16. volumeID: "<volume-id>"
    17. fsType: ext4

    OpenStack CSI 迁移

    特性状态: Kubernetes v1.24 [stable]

    自 Kubernetes 1.21 版本起,Cinder 的 CSIMigration 特性是默认被启用的。 此特性会将插件的所有操作从现有的树内插件重定向到 cinder.csi.openstack.org 容器存储接口(CSI)驱动程序。 为了使用此特性,必须在集群中安装 OpenStack Cinder CSI 驱动程序, 你可以通过设置 CSIMigrationOpenStackfalse 来禁止 Cinder CSI 迁移。

    要禁止控制器管理器和 kubelet 加载树内 Cinder 插件,你可以启用 InTreePluginOpenStackUnregister 特性门控

    configMap

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

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

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: configmap-pod
    5. spec:
    6. containers:
    7. - name: test
    8. image: busybox:1.28
    9. volumeMounts:
    10. - name: config-vol
    11. mountPath: /etc/config
    12. volumes:
    13. - name: config-vol
    14. configMap:
    15. name: log-config
    16. items:
    17. - key: log_level

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

    说明:

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

    downwardAPI

    downwardAPI 卷用于使 downward API 数据对应用程序可用。 这种卷类型挂载一个目录并在纯文本文件中写入所请求的数据。

    说明: 容器以 subPath 卷挂载方式使用 downwardAPI 时,将不能接收到它的更新。

    更多详细信息请参考 。

    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 配置示例

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: test-pd
    5. spec:
    6. containers:
    7. - image: k8s.gcr.io/test-webserver
    8. name: test-container
    9. volumeMounts:
    10. - mountPath: /cache
    11. name: cache-volume
    12. volumes:
    13. - name: cache-volume
    14. emptyDir: {}

    fc (光纤通道)

    fc 卷类型允许将现有的光纤通道块存储卷挂载到 Pod 中。 可以使用卷配置中的参数 targetWWNs 来指定单个或多个目标 WWN(World Wide Names)。 如果指定了多个 WWN,targetWWNs 期望这些 WWN 来自多路径连接。

    说明: 你必须配置 FC SAN Zoning,以便预先向目标 WWN 分配和屏蔽这些 LUN(卷),这样 Kubernetes 主机才可以访问它们。

    更多详情请参考 FC 示例

    是一个开源的、集群化的容器数据卷管理器。 Flocker 提供了由各种存储后端所支持的数据卷的管理和编排。

    使用 flocker 卷可以将一个 Flocker 数据集挂载到 Pod 中。 如果数据集在 Flocker 中不存在,则需要首先使用 Flocker CLI 或 Flocker API 创建数据集。 如果数据集已经存在,那么 Flocker 将把它重新附加到 Pod 被调度的节点。 这意味着数据可以根据需要在 Pod 之间共享。

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

    更多详情请参考 Flocker 示例

    gcePersistentDisk

    gcePersistentDisk 卷能将谷歌计算引擎 (GCE) 持久盘(PD) 挂载到你的 Pod 中。 不像 emptyDir 那样会在 Pod 被删除的同时也会被删除,持久盘卷的内容在删除 Pod 时会被保留,卷只是被卸载了。 这意味着持久盘卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

    注意: 在使用 PD 前,你必须使用 gcloud 或者 GCE API 或 UI 创建它。

    使用 gcePersistentDisk 时有一些限制:

    • 运行 Pod 的节点必须是 GCE VM
    • 这些 VM 必须和持久盘位于相同的 GCE 项目和区域(zone)

    GCE PD 的一个特点是它们可以同时被多个消费者以只读方式挂载。 这意味着你可以用数据集预先填充 PD,然后根据需要并行地在尽可能多的 Pod 中提供该数据集。 不幸的是,PD 只能由单个使用者以读写模式挂载 —— 即不允许同时写入。

    在由 ReplicationController 所管理的 Pod 上使用 GCE PD 将会失败,除非 PD 是只读模式或者副本的数量是 0 或 1。

    创建 GCE 持久盘(PD)

    在 Pod 中使用 GCE 持久盘之前,你首先要创建它。

    1. gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk

    GCE 持久盘配置示例

    区域持久盘

    区域持久盘 特性允许你创建能在同一区域的两个可用区中使用的持久盘。 要使用这个特性,必须以持久卷(PersistentVolume)的方式提供卷;直接从 Pod 引用这种卷是不可以的。

    手动供应基于区域 PD 的 PersistentVolume

    使用为 GCE PD 定义的存储类 可以实现动态供应。在创建 PersistentVolume 之前,你首先要创建 PD。

    1. gcloud beta compute disks create --size=500GB my-data-disk
    2. --region us-central1
    3. --replica-zones us-central1-a,us-central1-b

    PersistentVolume 示例:

    1. apiVersion: v1
    2. kind: PersistentVolume
    3. metadata:
    4. name: test-volume
    5. labels:
    6. failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
    7. spec:
    8. capacity:
    9. storage: 400Gi
    10. accessModes:
    11. - ReadWriteOnce
    12. gcePersistentDisk:
    13. pdName: my-data-disk
    14. fsType: ext4
    15. nodeAffinity:
    16. required:
    17. nodeSelectorTerms:
    18. - matchExpressions:
    19. # failure-domain.beta.kubernetes.io/zone 应在 1.21 之前使用
    20. - key: topology.kubernetes.io/zone
    21. values:
    22. - us-central1-a
    23. - us-central1-b

    GCE CSI 迁移

    启用 GCE PD 的 CSIMigration 特性后,所有插件操作将从现有的树内插件重定向到 pd.csi.storage.gke.io 容器存储接口( CSI )驱动程序。 为了使用此特性,必须在集群中上安装 GCE PD CSI驱动程序, 并且 CSIMigrationCSIMigrationGCE Beta 特性必须被启用。

    GCE CSI 迁移完成

    特性状态: Kubernetes v1.21 [alpha]

    要禁止控制器管理器和 kubelet 加载 gcePersistentDisk 存储插件,请将 InTreePluginGCEUnregister 标志设置为 true

    gitRepo (已弃用)

    警告: gitRepo 卷类型已经被废弃。如果需要在容器中提供 git 仓库,请将一个 卷挂载到 InitContainer 中,使用 git 命令完成仓库的克隆操作,然后将 EmptyDir 卷挂载到 Pod 的容器中。

    gitRepo 卷是一个卷插件的例子。 该查卷挂载一个空目录,并将一个 Git 代码仓库克隆到这个目录中供 Pod 使用。

    下面给出一个 gitRepo 卷的示例:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: server
    5. spec:
    6. containers:
    7. - image: nginx
    8. name: nginx
    9. volumeMounts:
    10. - mountPath: /mypath
    11. name: git-volume
    12. volumes:
    13. - name: git-volume
    14. gitRepo:
    15. repository: "git@somewhere:me/my-git-repository.git"
    16. revision: "22f1d8406d464b0c0874075539c1f2e96c253775"

    glusterfs

    glusterfs 卷能将 Glusterfs (一个开源的网络文件系统) 挂载到你的 Pod 中。不像 emptyDir 那样会在删除 Pod 的同时也会被删除,glusterfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 glusterfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。 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 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。
    • 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
    • 下层主机上创建的文件或目录只能由 root 用户写入。你需要在 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

    hostPath 配置示例:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: test-pd
    5. spec:
    6. containers:
    7. - image: k8s.gcr.io/test-webserver
    8. name: test-container
    9. volumeMounts:
    10. - mountPath: /test-pd
    11. name: test-volume
    12. volumes:
    13. - name: test-volume
    14. hostPath:
    15. # 宿主上目录位置
    16. path: /data
    17. # 此字段为可选
    18. type: Directory

    注意: FileOrCreate 模式不会负责创建文件的父目录。 如果欲挂载的文件的父目录不存在,Pod 启动会失败。 为了确保这种模式能够工作,可以尝试把文件和它对应的目录分开挂载,如 所示。

    hostPath FileOrCreate 配置示例

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: test-webserver
    5. spec:
    6. containers:
    7. - name: test-webserver
    8. image: k8s.gcr.io/test-webserver:latest
    9. volumeMounts:
    10. - mountPath: /var/local/aaa
    11. name: mydir
    12. - mountPath: /var/local/aaa/1.txt
    13. name: myfile
    14. volumes:
    15. - name: mydir
    16. hostPath:
    17. # 确保文件所在目录成功创建。
    18. path: /var/local/aaa
    19. type: DirectoryOrCreate
    20. - name: myfile
    21. hostPath:
    22. path: /var/local/aaa/1.txt
    23. type: FileOrCreate

    iscsi

    iscsi 卷能将 iSCSI (基于 IP 的 SCSI) 卷挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,iscsi 卷的内容在删除 Pod 时会被保留,卷只是被卸载。 这意味着 iscsi 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

    注意: 在使用 iSCSI 卷之前,你必须拥有自己的 iSCSI 服务器,并在上面创建卷。

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

    更多详情请参考 iSCSI 示例

    local

    local 卷所代表的是某个被挂载的本地存储设备,例如磁盘、分区或者目录。

    local 卷只能用作静态创建的持久卷。尚不支持动态配置。

    hostPath 卷相比,local 卷能够以持久和可移植的方式使用,而无需手动将 Pod 调度到节点。系统通过查看 PersistentVolume 的节点亲和性配置,就能了解卷的节点约束。

    然而,local 卷仍然取决于底层节点的可用性,并不适合所有应用程序。 如果节点变得不健康,那么 local 卷也将变得不可被 Pod 访问。使用它的 Pod 将不能运行。 使用 local 卷的应用程序必须能够容忍这种可用性的降低,以及因底层磁盘的耐用性特征而带来的潜在的数据丢失风险。

    下面是一个使用 local 卷和 nodeAffinity 的持久卷示例:

    使用 local 卷时,你需要设置 PersistentVolume 对象的 nodeAffinity 字段。 Kubernetes 调度器使用 PersistentVolume 的 nodeAffinity 信息来将使用 local 卷的 Pod 调度到正确的节点。

    PersistentVolume 对象的 volumeMode 字段可被设置为 “Block” (而不是默认值 “Filesystem”),以将 local 卷作为原始块设备暴露出来。

    使用 local 卷时,建议创建一个 StorageClass 并将其 volumeBindingMode 设置为 WaitForFirstConsumer。要了解更多详细信息,请参考 local StorageClass 示例。 延迟卷绑定的操作可以确保 Kubernetes 在为 PersistentVolumeClaim 作出绑定决策时,会评估 Pod 可能具有的其他节点约束,例如:如节点资源需求、节点选择器、Pod亲和性和 Pod 反亲和性。

    你可以在 Kubernetes 之外单独运行静态驱动以改进对 local 卷的生命周期管理。 请注意,此驱动尚不支持动态配置。 有关如何运行外部 local 卷驱动,请参考 。

    说明: 如果不使用外部静态驱动来管理卷的生命周期,用户需要手动清理和删除 local 类型的持久卷。

    nfs

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

    注意: 在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用。

    要了解更多详情请参考 。

    persistentVolumeClaim

    persistentVolumeClaim 卷用来将(PersistentVolume)挂载到 Pod 中。 持久卷申领(PersistentVolumeClaim)是用户在不知道特定云环境细节的情况下“申领”持久存储(例如 GCE PersistentDisk 或者 iSCSI 卷)的一种方法。

    更多详情请参考持久卷示例

    portworxVolume 是一个可伸缩的块存储层,能够以超融合(hyperconverged)的方式与 Kubernetes 一起运行。 支持对服务器上存储的指纹处理、基于存储能力进行分层以及跨多个服务器整合存储容量。 Portworx 可以以 in-guest 方式在虚拟机中运行,也可以在裸金属 Linux 节点上运行。

    portworxVolume 类型的卷可以通过 Kubernetes 动态创建,也可以预先配备并在 Kubernetes Pod 内引用。 下面是一个引用预先配备的 PortworxVolume 的示例 Pod:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: test-portworx-volume-pod
    5. containers:
    6. - image: k8s.gcr.io/test-webserver
    7. name: test-container
    8. volumeMounts:
    9. - mountPath: /mnt
    10. name: pxvol
    11. volumes:
    12. - name: pxvol
    13. # 此 Portworx 卷必须已经存在
    14. portworxVolume:
    15. volumeID: "pxvol"
    16. fsType: "<fs-type>"

    说明:

    在 Pod 中使用 portworxVolume 之前,你要确保有一个名为 pxvol 的 PortworxVolume 存在。

    更多详情可以参考 Portworx 卷

    projected (投射)

    投射卷能将若干现有的卷来源映射到同一目录上。更多详情请参考投射卷

    quobyte (已弃用)

    quobyte 卷允许将现有的 Quobyte 卷挂载到你的 Pod 中。

    说明: 在使用 Quobyte 卷之前,你首先要进行安装 Quobyte 并创建好卷。

    Quobyte 支持。 推荐使用 CSI 插件以在 Kubernetes 中使用 Quobyte 卷。 Quobyte 的 GitHub 项目包含以 CSI 形式部署 Quobyte 的 说明 及使用示例。

    rbd

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

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

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

    更多详情请参考 。

    RBD CSI 迁移

    特性状态: Kubernetes v1.23 [alpha]

    启用 RBD 的 CSIMigration 特性后,所有插件操作从现有的树内插件重定向到 rbd.csi.ceph.com 驱动程序。 要使用该特性,必须在集群内安装 Ceph CSI 驱动,并启用 CSIMigrationcsiMigrationRBD

    说明:

    作为一位管理存储的 Kubernetes 集群操作者,在尝试迁移到 RBD CSI 驱动前,你必须完成下列先决事项:

    • 你必须在集群中安装 v3.5.0 或更高版本的 Ceph CSI 驱动(rbd.csi.ceph.com)。
    • 因为 clusterID 是 CSI 驱动程序必需的参数,而树内存储类又将 monitors 作为一个必需的参数,所以 Kubernetes 存储管理者需要根据 monitors 的哈希值(例:#echo -n '<monitors_string>' | md5sum)来创建 clusterID,并保持该 monitors 存在于该 clusterID 的配置中。
    • 同时,如果树内存储类的 adminId 的值不是 admin,那么其 adminSecretName 就需要被修改成 adminId 参数的 base64 编码值。

    secret

    secret 卷用来给 Pod 传递敏感信息,例如密码。你可以将 Secret 存储在 Kubernetes API 服务器上,然后以文件的形式挂载到 Pod 中,无需直接与 Kubernetes 耦合。 secret 卷由 tmpfs(基于 RAM 的文件系统)提供存储,因此它们永远不会被写入非易失性(持久化的)存储器。

    说明: 使用前你必须在 Kubernetes API 中创建 secret。

    说明: 容器以 卷挂载方式挂载 Secret 时,将感知不到 Secret 的更新。

    更多详情请参考配置 Secrets

    storageOS (已弃用)

    storageos 卷允许将现有的 StorageOS 卷挂载到你的 Pod 中。

    StorageOS 在 Kubernetes 环境中以容器的形式运行,这使得应用能够从 Kubernetes 集群中的任何节点访问本地的或挂接的存储。为应对节点失效状况,可以复制数据。 若需提高利用率和降低成本,可以考虑瘦配置(Thin Provisioning)和数据压缩。

    作为其核心能力之一,StorageOS 为容器提供了可以通过文件系统访问的块存储。

    StorageOS 容器需要 64 位的 Linux,并且没有其他的依赖关系。 StorageOS 提供免费的开发者授权许可。

    注意: 你必须在每个希望访问 StorageOS 卷的或者将向存储资源池贡献存储容量的节点上运行 StorageOS 容器。有关安装说明,请参阅 。

    1. apiVersion: v1
    2. kind: Pod
    3. labels:
    4. name: redis
    5. role: master
    6. name: test-storageos-redis
    7. spec:
    8. containers:
    9. - name: master
    10. image: kubernetes/redis:v1
    11. env:
    12. - name: MASTER
    13. value: "true"
    14. ports:
    15. - containerPort: 6379
    16. volumeMounts:
    17. - mountPath: /redis-master-data
    18. name: redis-data
    19. volumes:
    20. - name: redis-data
    21. storageos:
    22. # `redis-vol01` 卷必须在 StorageOS 中存在,并位于 `default` 名字空间内
    23. volumeName: redis-vol01
    24. fsType: ext4

    关于 StorageOS 的进一步信息、动态供应和持久卷申领等等,请参考 StorageOS 示例

    vsphereVolume(弃用)

    说明: 建议你改用 vSphere CSI 树外驱动程序。

    vsphereVolume 用来将 vSphere VMDK 卷挂载到你的 Pod 中。 在卸载卷时,卷的内容会被保留。 vSphereVolume 卷类型支持 VMFS 和 VSAN 数据仓库。

    进一步信息可参考 vSphere 卷

    vSphere CSI 迁移

    特性状态: Kubernetes v1.19 [beta]

    vsphereVolumeCSIMigration 特性被启用时,所有插件操作都被从树内插件重定向到 csi.vsphere.vmware.com CSI 驱动。 为了使用此功能特性,必须在集群中安装 ,并启用 CSIMigrationCSIMigrationvSphere 特性门控

    你可以在 VMware 的文档页面 中找到有关如何迁移的其他建议。

    说明:

    vSphere CSI 驱动不支持内置 vsphereVolume 的以下 StorageClass 参数:

    • diskformat
    • hostfailurestotolerate
    • forceprovisioning
    • cachereservation
    • diskstripes
    • objectspacereservation
    • iopslimit

    使用这些参数创建的现有卷将被迁移到 vSphere CSI 驱动,不过使用 vSphere CSI 驱动所创建的新卷都不会理会这些参数。

    vSphere CSI 迁移完成

    特性状态: Kubernetes v1.19 [beta]

    为了避免控制器管理器和 kubelet 加载 vsphereVolume 插件,你需要将 InTreePluginvSphereUnregister 特性设置为 true。你还必须在所有工作节点上安装 csi.vsphere.vmware.com 驱动。

    Portworx CSI 迁移

    特性状态: Kubernetes v1.23 [alpha]

    Kubernetes 1.23 中加入了 Portworx 的 CSIMigration 特性,但默认不会启用,因为该特性仍处于 alpha 阶段。 该特性会将所有的插件操作从现有的树内插件重定向到 pxd.portworx.com 容器存储接口(Container Storage Interface, CSI)驱动程序。 集群中必须安装 。 要启用此特性,请在 kube-controller-manager 和 kubelet 中设置 CSIMigrationPortworx=true

    有时,在单个 Pod 中共享卷以供多方使用是很有用的。 volumeMounts.subPath 属性可用于指定所引用的卷内的子路径,而不是其根路径。

    下面例子展示了如何配置某包含 LAMP 堆栈(Linux Apache MySQL PHP)的 Pod 使用同一共享卷。 此示例中的 subPath 配置不建议在生产环境中使用。 PHP 应用的代码和相关数据映射到卷的 html 文件夹,MySQL 数据库存储在卷的 mysql 文件夹中:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: my-lamp-site
    5. spec:
    6. containers:
    7. - name: mysql
    8. image: mysql
    9. env:
    10. - name: MYSQL_ROOT_PASSWORD
    11. value: "rootpasswd"
    12. volumeMounts:
    13. - mountPath: /var/lib/mysql
    14. name: site-data
    15. subPath: mysql
    16. - name: php
    17. image: php:7.0-apache
    18. volumeMounts:
    19. - mountPath: /var/www/html
    20. name: site-data
    21. subPath: html
    22. volumes:
    23. - name: site-data
    24. persistentVolumeClaim:
    25. claimName: my-lamp-site-data

    使用带有扩展环境变量的 subPath

    特性状态: Kubernetes v1.17 [stable]

    使用 subPathExpr 字段可以基于 Downward API 环境变量来构造 subPath 目录名。 subPathsubPathExpr 属性是互斥的。

    在这个示例中,Pod 使用 subPathExpr 来 hostPath 卷 /var/log/pods 中创建目录 pod1hostPath 卷采用来自 downwardAPI 的 Pod 名称生成目录名。 宿主目录 /var/log/pods/pod1 被挂载到容器的 /logs 中。

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: pod1
    5. spec:
    6. containers:
    7. - name: container1
    8. env:
    9. - name: POD_NAME
    10. valueFrom:
    11. fieldRef:
    12. apiVersion: v1
    13. fieldPath: metadata.name
    14. image: busybox:1.28
    15. command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
    16. volumeMounts:
    17. - name: workdir1
    18. mountPath: /logs
    19. # 包裹变量名的是小括号,而不是大括号
    20. subPathExpr: $(POD_NAME)
    21. restartPolicy: Never
    22. volumes:
    23. - name: workdir1
    24. hostPath:
    25. path: /var/log/pods

    资源

    emptyDir 卷的存储介质(磁盘、SSD 等)是由保存 kubelet 数据的根目录(通常是 /var/lib/kubelet)的文件系统的介质确定。 Kubernetes 对 emptyDir 卷或者 hostPath 卷可以消耗的空间没有限制,容器之间或 Pod 之间也没有隔离。

    要了解如何使用资源规约来请求空间,可参考 如何管理资源

    Out-of-Tree 卷插件包括 和 FlexVolume(已弃用)。 它们使存储供应商能够创建自定义存储插件,而无需将插件源码添加到 Kubernetes 代码仓库。

    以前,所有卷插件(如上面列出的卷类型)都是“树内(In-Tree)”的。 “树内”插件是与 Kubernetes 的核心组件一同构建、链接、编译和交付的。 这意味着向 Kubernetes 添加新的存储系统(卷插件)需要将代码合并到 Kubernetes 核心代码库中。

    CSI 和 FlexVolume 都允许独立于 Kubernetes 代码库开发卷插件,并作为扩展部署(安装)在 Kubernetes 集群上。

    对于希望创建树外(Out-Of-Tree)卷插件的存储供应商,请参考 卷插件常见问题

    CSI

    容器存储接口 (CSI) 为容器编排系统(如 Kubernetes)定义标准接口,以将任意存储系统暴露给它们的容器工作负载。

    更多详情请阅读 。

    说明: Kubernetes v1.13 废弃了对 CSI 规范版本 0.2 和 0.3 的支持,并将在以后的版本中删除。

    说明: CSI 驱动可能并非兼容所有的 Kubernetes 版本。 请查看特定 CSI 驱动的文档,以了解各个 Kubernetes 版本所支持的部署步骤以及兼容性列表。

    一旦在 Kubernetes 集群上部署了 CSI 兼容卷驱动程序,用户就可以使用 csi 卷类型来挂接、挂载 CSI 驱动所提供的卷。

    csi 卷可以在 Pod 中以三种方式使用:

    • 通过 PersistentVolumeClaim(#persistentvolumeclaim) 对象引用
    • 使用一般性的临时卷 (Alpha 特性)
    • 使用 , 前提是驱动支持这种用法(Beta 特性)

    存储管理员可以使用以下字段来配置 CSI 持久卷:

    • driver:指定要使用的卷驱动名称的字符串值。 这个值必须与 CSI 驱动程序在 GetPluginInfoResponse 中返回的值相对应;该接口定义在 CSI 规范中。 Kubernetes 使用所给的值来标识要调用的 CSI 驱动程序;CSI 驱动程序也使用该值来辨识哪些 PV 对象属于该 CSI 驱动程序。

    • volumeHandle:唯一标识卷的字符串值。 该值必须与 CSI 驱动在 CreateVolumeResponsevolume_id 字段中返回的值相对应;接口定义在 中。 在所有对 CSI 卷驱动程序的调用中,引用该 CSI 卷时都使用此值作为 volume_id 参数。

    • readOnly:一个可选的布尔值,指示通过 ControllerPublished 关联该卷时是否设置该卷为只读。默认值是 false。 该值通过 ControllerPublishVolumeRequest 中的 readonly 字段传递给 CSI 驱动。

    • fsType:如果 PV 的 VolumeModeFilesystem,那么此字段指定挂载卷时应该使用的文件系统。 如果卷尚未格式化,并且支持格式化,此值将用于格式化卷。 此值可以通过 ControllerPublishVolumeRequestNodeStageVolumeRequestNodePublishVolumeRequestVolumeCapability 字段传递给 CSI 驱动。

    • volumeAttributes:一个字符串到字符串的映射表,用来设置卷的静态属性。 该映射必须与 CSI 驱动程序返回的 CreateVolumeResponse 中的 volume.attributes 字段的映射相对应; CSI 规范 中有相应的定义。 该映射通过ControllerPublishVolumeRequestNodeStageVolumeRequest、和 NodePublishVolumeRequest 中的 volume_attributes 字段传递给 CSI 驱动。

    • controllerPublishSecretRef:对包含敏感信息的 Secret 对象的引用; 该敏感信息会被传递给 CSI 驱动来完成 CSI ControllerPublishVolumeControllerUnpublishVolume 调用。 此字段是可选的;在不需要 Secret 时可以是空的。 如果 Secret 对象包含多个 Secret 条目,则所有的 Secret 条目都会被传递。

    • nodeStageSecretRef:对包含敏感信息的 Secret 对象的引用。 该信息会传递给 CSI 驱动来完成 CSI NodeStageVolume 调用。 此字段是可选的,如果不需要 Secret,则可能是空的。 如果 Secret 对象包含多个 Secret 条目,则传递所有 Secret 条目。

    • nodePublishSecretRef:对包含敏感信息的 Secret 对象的引用。 该信息传递给 CSI 驱动来完成 CSI NodePublishVolume 调用。 此字段是可选的,如果不需要 Secret,则可能是空的。 如果 Secret 对象包含多个 Secret 条目,则传递所有 Secret 条目。

    CSI 原始块卷支持

    特性状态: Kubernetes v1.18 [stable]

    具有外部 CSI 驱动程序的供应商能够在 Kubernetes 工作负载中实现原始块卷支持。

    你可以和以前一样,安装自己的 带有原始块卷支持的 PV/PVC, 采用 CSI 对此过程没有影响。

    CSI 临时卷

    特性状态: Kubernetes v1.16 [beta]

    你可以直接在 Pod 规约中配置 CSI 卷。采用这种方式配置的卷都是临时卷, 无法在 Pod 重新启动后继续存在。 进一步的信息可参阅临时卷

    有关如何开发 CSI 驱动的更多信息,请参考 。

    Windows CSI 代理

    特性状态: Kubernetes v1.22 [stable]

    CSI 节点插件需要执行多种特权操作,例如扫描磁盘设备和挂载文件系统等。 这些操作在每个宿主操作系统上都是不同的。对于 Linux 工作节点而言,容器化的 CSI 节点插件通常部署为特权容器。对于 Windows 工作节点而言,容器化 CSI 节点插件的特权操作是通过 来支持的。csi-proxy 是一个由社区管理的、独立的可执行二进制文件, 需要被预安装到每个 Windows 节点上。

    要了解更多的细节,可以参考你要部署的 CSI 插件的部署指南。

    从树内插件迁移到 CSI 驱动程序

    特性状态: Kubernetes v1.17 [beta]

    启用 CSIMigration 特性后,针对现有树内插件的操作会被重定向到相应的 CSI 插件(应已安装和配置)。 因此,操作员在过渡到取代树内插件的 CSI 驱动时,无需对现有存储类、PV 或 PVC(指树内插件)进行任何配置更改。

    所支持的操作和特性包括:配备(Provisioning)/删除、挂接(Attach)/解挂(Detach)、 挂载(Mount)/卸载(Unmount)和调整卷大小。

    上面的节列出了支持 CSIMigration 并已实现相应 CSI 驱动程序的树内插件。

    下面是支持 Windows 节点上持久性存储的树内插件:

    特性状态: Kubernetes v1.23 [deprecated]

    FlexVolume 是一个使用基于 exec 的模型来与驱动程序对接的树外插件接口。 用户必须在每个节点上的预定义卷插件路径中安装 FlexVolume 驱动程序可执行文件,在某些情况下,控制平面节点中也要安装。

    Pod 通过 flexvolume 树内插件与 FlexVolume 驱动程序交互。 更多详情请参考 FlexVolume 文档。

    下面的 FlexVolume 插件 以 PowerShell 脚本的形式部署在宿主系统上,支持 Windows 节点:

    说明:

    FlexVolume 已被弃用。推荐使用树外 CSI 驱动来将外部存储整合进 Kubernetes。

    FlexVolume 驱动的维护者应开发一个 CSI 驱动并帮助用户从 FlexVolume 驱动迁移到 CSI。 FlexVolume 用户应迁移工作负载以使用对等的 CSI 驱动。

    挂载卷的传播

    挂载卷的传播能力允许将容器安装的卷共享到同一 Pod 中的其他容器,甚至共享到同一节点上的其他 Pod。

    卷的挂载传播特性由 Container.volumeMounts 中的 mountPropagation 字段控制。 它的值包括:

    • None - 此卷挂载将不会感知到主机后续在此卷或其任何子目录上执行的挂载变化。 类似的,容器所创建的卷挂载在主机上是不可见的。这是默认模式。

      该模式等同于 Linux 内核文档 中描述的 private 挂载传播选项。

    • HostToContainer - 此卷挂载将会感知到主机后续针对此卷或其任何子目录的挂载操作。

      换句话说,如果主机在此挂载卷中挂载任何内容,容器将能看到它被挂载在那里。

      类似的,配置了 Bidirectional 挂载传播选项的 Pod 如果在同一卷上挂载了内容,挂载传播设置为 HostToContainer 的容器都将能看到这一变化。

      该模式等同于 中描述的 rslave 挂载传播选项。

    配置

    在某些部署环境中,挂载传播正常工作前,必须在 Docker 中正确配置挂载共享(mount share),如下所示。

    编辑你的 Docker systemd 服务文件,按下面的方法设置 MountFlags

    1. MountFlags=shared

    或者,如果存在 MountFlags=slave 就删除掉。然后重启 Docker 守护进程:

    参考 示例。