[K8s]Kubernetes-存储(下)

Posted 若水三千

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[K8s]Kubernetes-存储(下)相关的知识,希望对你有一定的参考价值。

3 - CSI 卷克隆

本文档介绍 Kubernetes 中克隆现有 CSI 卷的概念。阅读前建议先熟悉卷。

介绍

CSI 卷克隆功能增加了通过在 dataSource 字段中指定存在的 PVC,来表示用户想要克隆的卷(Volume)。

克隆(Clone),意思是为已有的 Kubernetes 卷创建副本,它可以像任何其它标准卷一样被使用。唯一的区别就是配置后,后端设备将创建指定完全相同的副本,而不是创建一个“新的”空卷。

从 Kubernetes API 的角度看,克隆的实现只是在创建新的 PVC 时,增加了指定一个现有 PVC 作为数据源的能力。源 PVC 必须是 bound 状态且可用的(不在使用中)。

用户在使用该功能时,需要注意以下事项:

  • 克隆支持(VolumePVCDataSource)仅适用于 CSI 驱动。
  • 克隆支持仅适用于动态供应器。
  • CSI 驱动可能实现,也可能未实现卷克隆功能。
  • 仅当 PVC 与目标 PVC 存在于同一命名空间(源和目标 PVC 必须在相同的命名空间)时,才可以克隆 PVC。
  • 仅在同一存储类中支持克隆。
    • 目标卷必须和源卷具有相同的存储类
    • 可以使用默认的存储类并且 storageClassName 字段在规格中忽略了
  • 克隆只能在两个使用相同 VolumeMode 设置的卷中进行(如果请求克隆一个块存储模式的卷,源卷必须也是块存储模式)。

制备

克隆卷与其他任何 PVC 一样配置,除了需要增加 dataSource 来引用同一命名空间中现有的 PVC。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: clone-of-pvc-1
    namespace: myns
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: cloning
  resources:
    requests:
      storage: 5Gi
  dataSource:
    kind: PersistentVolumeClaim
    name: pvc-1

说明:
你必须为 spec.resources.requests.storage 指定一个值,并且你指定的值必须大于或等于源卷的值。

结果是一个名称为 clone-of-pvc-1 的新 PVC 与指定的源 pvc-1 拥有相同的内容。

使用

一旦新的 PVC 可用,被克隆的 PVC 像其他 PVC 一样被使用。可以预期的是,新创建的 PVC 是一个独立的对象。可以独立使用、克隆、快照或删除它,而不需要考虑它的原始数据源 PVC。这也意味着,源没有以任何方式链接到新创建的 PVC,它也可以被修改或删除,而不会影响到新创建的克隆。

4 - 临时卷

本文档描述 Kubernetes 中的临时卷(Ephemeral Volume)。建议先了解卷,特别是 PersistentVolumeClaim 和 PersistentVolume。

有些应用程序需要额外的存储,但并不关心数据在重启后仍然可用,既是否被持久地保存。例如,缓存服务经常受限于内存大小,将不常用的数据转移到比内存慢、但对总体性能的影响很小的存储中。

另有些应用程序需要以文件形式注入的只读数据,比如配置数据或密钥。

临时卷就是为此类用例设计的。因为卷会遵从 Pod 的生命周期,与 Pod 一起创建和删除,所以停止和重新启动 Pod 时,不会受持久卷在何处可用的限制。

临时卷在 Pod 规范中以内联方式定义,这简化了应用程序的部署和管理。

临时卷的类型

Kubernetes 为了不同的目的,支持几种不同类型的临时卷:

  • emptyDir:Pod 启动时为空,存储空间来自本地的 kubelet 根目录(通常是根磁盘)或内存
  • configMap、downwardAPI、secret:将不同类型的 Kubernetes 数据注入到 Pod 中
  • CSI 临时卷:类似于前面的卷类型,但由专门支持此特性的指定 CSI 驱动程序提供
  • 通用临时卷:它可以由所有支持持久卷的存储驱动程序提供

emptyDir、configMap、downwardAPI、secret 是作为本地临时存储提供的。它们由各个节点上的 kubelet 管理。

CSI 临时卷必须由第三方 CSI 存储驱动程序提供。

通用临时卷可以由第三方 CSI 存储驱动程序提供,也可以由支持动态配置的任何其他存储驱动程序提供。一些专门为 CSI 临时卷编写的 CSI 驱动程序,不支持动态供应:因此这些驱动程序不能用于通用临时卷。

使用第三方驱动程序的优势在于,它们可以提供 Kubernetes 本身不支持的功能,例如,与 kubelet 管理的磁盘具有不同运行特征的存储,或者用来注入不同的数据。

CSI 临时卷

FEATURE STATE: Kubernetes v1.16 [beta]

该特性需要启用参数 CSIInlineVolume 特性门控(feature gate)。该参数从 Kubernetes 1.16 开始默认启用。

说明: 只有一部分 CSI 驱动程序支持 CSI 临时卷。Kubernetes CSI 驱动程序列表显示了支持临时卷的驱动程序。

从概念上讲,CSI 临时卷类似于 configMap、downwardAPI 和 secret 类型的卷:其存储在每个节点本地管理,并在将 Pod 调度到节点后与其他本地资源一起创建。在这个阶段,Kubernetes 没有重新调度 Pods 的概念。卷创建不太可能失败,否则 Pod 启动将会受阻。特别是,这些卷不支持感知存储容量的 Pod 调度。它们目前也没包括在 Pod 的存储资源使用限制中,因为 kubelet 只能对它自己管理的存储强制执行。

下面是使用 CSI 临时存储的 Pod 的示例清单:

kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app
spec:
  containers:
    - name: my-frontend
      image: busybox
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-inline-vol
      command: [ "sleep", "1000000" ]
  volumes:
    - name: my-csi-inline-vol
      csi:
        driver: inline.storage.kubernetes.io
        volumeAttributes:
          foo: bar

volumeAttributes 决定驱动程序准备什么样的卷。这些属性特定于每个驱动程序,且没有实现标准化。有关进一步的说明,请参阅每个 CSI 驱动程序的文档。

作为一个集群管理员,你可以使用 PodSecurityPolicy 来控制在 Pod 中可以使用哪些 CSI 驱动程序,具体则是通过 allowedCSIDrivers 字段指定。

通用临时卷

FEATURE STATE: Kubernetes v1.21 [beta]

这个特性需要启用 GenericEphemeralVolume 特性门控。因为这是一个 beta 特性,默认情况下启用。

通用临时卷类似于 emptyDir 卷,因为它为每个 Pod 提供临时数据存放目录,在最初制备完毕时一般为空。不过通用临时卷也有一些额外的功能特性:

  • 存储可以是本地的,也可以是网络连接的。
  • 卷可以有固定的大小,pod不能超量使用。
  • 卷可能有一些初始数据,这取决于驱动程序和参数。
  • 当驱动程序支持,卷上的典型操作将被支持,包括(快照、克隆、调整大小和存储容量跟踪)。

示例:

kind: Pod
apiVersion: v1
metadata:
  name: my-app
spec:
  containers:
    - name: my-frontend
      image: busybox
      volumeMounts:
      - mountPath: "/scratch"
        name: scratch-volume
      command: [ "sleep", "1000000" ]
  volumes:
    - name: scratch-volume
      ephemeral:
        volumeClaimTemplate:
          metadata:
            labels:
              type: my-frontend-volume
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "scratch-storage-class"
            resources:
              requests:
                storage: 1Gi

生命周期和 PersistentVolumeClaim

关键的设计思想是在 Pod 的卷来源中允许使用卷申领的参数。PersistentVolumeClaim 的标签、注解和整套字段集均被支持。创建这样一个 Pod 后,临时卷控制器在 Pod 所属的命名空间中创建一个实际的 PersistentVolumeClaim 对象,并确保删除 Pod 时,同步删除 PersistentVolumeClaim。

如上设置将触发卷的绑定与/或准备操作,相应动作或者在 StorageClass 使用即时卷绑定时立即执行,或者当 Pod 被暂时性调度到某节点时执行 (WaitForFirstConsumer 卷绑定模式)。对于常见的临时卷,建议采用后者,这样调度器就可以自由地为 Pod 选择合适的节点。对于即时绑定,调度器则必须选出一个节点,使得在卷可用时,能立即访问该卷。

就资源所有权而言,拥有通用临时存储的 Pod 是提供临时存储 (ephemeral storage) 的 PersistentVolumeClaim 的所有者。当 Pod 被删除时,Kubernetes 垃圾收集器会删除 PVC,然后 PVC 通常会触发卷的删除,因为存储类的默认回收策略是删除卷。你可以使用带有 retain 回收策略的 StorageClass 创建准临时 (quasi-ephemeral) 本地存储:该存储比 Pod 寿命长,在这种情况下,你需要确保单独进行卷清理。

当这些 PVC 存在时,它们可以像其他 PVC 一样使用。特别是,它们可以被引用作为批量克隆或快照的数据源。PVC对象还保持着卷的当前状态。

PersistentVolumeClaim 的命名

自动创建的 PVCs 的命名是确定的:此名称是 Pod 名称和卷名称的组合,中间由连字符(-)连接。在上面的示例中,PVC 将命名为 my-app-scratch-volume。这种确定性命名方式使得与 PVC 交互变得更容易,因为一旦知道 Pod 名称和卷名,就不必搜索它。

这种确定性命名方式也引入了潜在的冲突,比如在不同的 Pod 之间(名为 “Pod-a” 的 Pod 挂载名为 "scratch" 的卷,和名为 "pod" 的 Pod 挂载名为 “a-scratch” 的卷,这两者均会生成名为 "pod-a-scratch" 的PVC),或者在 Pod 和手工创建的 PVC 之间。

以下冲突会被检测到:如果 PVC 是为 Pod 创建的,那么它只用于临时卷。此检测基于所有权关系。现有的 PVC 不会被覆盖或修改。但这并不能解决冲突,因为如果没有正确的 PVC,Pod 就无法启动。

注意: 当命名 Pods 和卷出现在同一个命名空间中时,要小心,以防止发生此类冲突。

安全

启用 GenericEphemeralVolume 特性会导致那些没有 PVCs 创建权限的用户,在创建 Pods 时,被允许间接的创建 PVCs。集群管理员必须意识到这一点。如果这不符合他们的安全模型,他们有如下选择:

  • 通过特性门控显式禁用该特性。
  • 当 volumes 列表不包含 ephemeral 卷类型时,使用 Pod 安全策略。(这一方式在 Kubernetes 1.21 版本已经弃用)
  • 使用一个准入 Webhook 拒绝包含通用临时卷的 Pods。

为 PVC 卷所设置的逐名字空间的配额仍然有效,因此即使允许用户使用这种新机制,他们也不能使用它来规避其他策略。

5 - 卷快照类

本文档描述了 Kubernetes 中 VolumeSnapshotClass 的概念。建议熟悉卷快照(Volume Snapshots)和 存储类(Storage Class)。

介绍

就像 StorageClass 为管理员提供了一种在配置卷时描述存储“类”的方法,VolumeSnapshotClass 提供了一种在配置卷快照时描述存储“类”的方法。

VolumeSnapshotClass 资源

每个 VolumeSnapshotClass 都包含 driver、deletionPolicy 和 parameters 字段,在需要动态配置属于该类的 VolumeSnapshot 时使用。

VolumeSnapshotClass 对象的名称很重要,是用户可以请求特定类的方式。管理员在首次创建 VolumeSnapshotClass 对象时设置类的名称和其他参数,对象一旦创建就无法更新。

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

管理员可以为未请求任何特定类绑定的 VolumeSnapshots 指定默认的 VolumeSnapshotClass,方法是设置注解 snapshot.storage.kubernetes.io/is-default-class: "true":

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

驱动程序

卷快照类有一个驱动程序,用于确定配置 VolumeSnapshot 的 CSI 卷插件。此字段必须指定。

删除策略

卷快照类具有 deletionPolicy 属性。用户可以配置当所绑定的 VolumeSnapshot 对象将被删除时,如何处理 VolumeSnapshotContent 对象。卷快照类的这个策略可以是 Retain 或者 Delete。这个策略字段必须指定。

如果删除策略是 Delete,那么底层的存储快照会和 VolumeSnapshotContent 对象一起删除。如果删除策略是 Retain,那么底层快照和 VolumeSnapshotContent 对象都会被保留。

参数

卷快照类具有描述属于该卷快照类的卷快照的参数,可根据 driver 接受不同的参数。

6 - 存储类

本文描述了 Kubernetes 中 StorageClass 的概念。建议先熟悉卷和持久卷的概念。

介绍

StorageClass 为管理员提供了描述存储 "类" 的方法。不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为"配置文件"。

StorageClass 资源

每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段,这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。

StorageClass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。当创建 StorageClass 对象时,管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。

管理员可以为没有申请绑定到特定 StorageClass 的 PVC 指定一个默认的存储类:更多详情请参阅 PersistentVolumeClaim 章节。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

存储制备器

每个 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。该字段必须指定。

卷插件
内置制备器
配置例子
AWSElasticBlockStore
AzureFile
AzureDisk
CephFS
-
-
Cinder
FC
-
-
FlexVolume
-
-
Flocker
-
GCEPersistentDisk
Glusterfs
iSCSI
-
-
Quobyte
NFS
-
RBD
VsphereVolume
PortworxVolume
ScaleIO
StorageOS
Local
-

你不限于指定此处列出的 "内置" 制备器(其名称前缀为 "kubernetes.io" 并打包在 Kubernetes 中)。你还可以运行和指定外部制备器,这些独立的程序遵循由 Kubernetes 定义的规范。外部供应商的作者完全可以自由决定他们的代码保存于何处、打包方式、运行方式、使用的插件(包括 Flex)等。代码仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 包含一个用于为外部制备器编写功能实现的类库。你可以访问代码仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 了解外部驱动列表。

例如,NFS 没有内部制备器,但可以使用外部制备器。也有第三方存储供应商提供自己的外部制备器。

回收策略

由 StorageClass 动态创建的 PersistentVolume 会在类的 reclaimPolicy 字段中指定回收策略,可以是 Delete 或者 Retain。如果 StorageClass 对象被创建时没有指定 reclaimPolicy,它将默认为 Delete。

通过 StorageClass 手动创建并管理的 PersistentVolume 会使用它们被创建时指定的回收政策。

允许卷扩展

FEATURE STATE: Kubernetes v1.11 [beta]

PersistentVolume 可以配置为可扩展。将此功能设置为 true 时,允许用户通过编辑相应的 PVC 对象来调整卷大小。

当下层 StorageClass 的 allowVolumeExpansion 字段设置为 true 时,以下类型的卷支持卷扩展。

卷类型
Kubernetes 版本要求
gcePersistentDisk
1.11
awsElasticBlockStore
1.11
Cinder
1.11
glusterfs
1.11
rbd
1.11
Azure File
1.11
Azure Disk
1.11
Portworx
1.11
FlexVolume
1.13
CSI
1.14 (alpha), 1.16 (beta)

说明: 此功能仅可用于扩容卷,不能用于缩小卷。

挂载选项

由 StorageClass 动态创建的 PersistentVolume 将使用类中 mountOptions 字段指定的挂载选项。

如果卷插件不支持挂载选项,却指定了挂载选项,则制备操作会失败。挂载选项在 StorageClass 和 PV 上都不会做验证,如果其中一个挂载选项无效,那么这个 PV 挂载操作就会失败。

卷绑定模式

volumeBindingMode 字段控制了卷绑定和动态制备应该发生在什么时候。

默认情况下,Immediate 模式表示一旦创建了 PersistentVolumeClaim 也就完成了卷绑定和动态制备。对于由于拓扑限制而非集群所有节点可达的存储后端,PersistentVolume 会在不知道 Pod 调度要求的情况下绑定或者制备。

集群管理员可以通过指定 WaitForFirstConsumer 模式来解决此问题。该模式将延迟 PersistentVolume 的绑定和制备,直到使用该 PersistentVolumeClaim 的 Pod 被创建。PersistentVolume 会根据 Pod 调度约束指定的拓扑来选择或制备。这些包括但不限于资源需求、 节点筛选器、pod 亲和性和互斥性、以及污点和容忍度。

以下插件支持动态供应的 WaitForFirstConsumer 模式:

  • AWSElasticBlockStore
  • GCEPersistentDisk
  • AzureDisk

以下插件支持预创建绑定 PersistentVolume 的 WaitForFirstConsumer 模式:

  • 上述全部
  • Local

FEATURE STATE: Kubernetes v1.17 [stable]

动态配置和预先创建的 PV 也支持 CSI卷,但是你需要查看特定 CSI 驱动程序的文档以查看其支持的拓扑键名和例子。

说明:
如果你选择使用 WaitForFirstConsumer,请不要在 Pod 规约中使用 nodeName 来指定节点亲和性。如果在这种情况下使用 nodeName,Pod 将会绕过调度程序,PVC 将停留在 pending 状态。
相反,在这种情况下,你可以使用节点选择器作为主机名,如下所示

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  nodeSelector:
    kubernetes.io/hostname: kube-01
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

允许的拓扑结构

FEATURE STATE: Kubernetes v1.12 [beta]

当集群操作人员使用了 WaitForFirstConsumer 的卷绑定模式,在大部分情况下就没有必要将制备限制为特定的拓扑结构。然而,如果还有需要的话,可以使用 allowedTopologies。

这个例子描述了如何将供应卷的拓扑限制在特定的区域,在使用时应该根据插件支持情况替换 zone 和 zones 参数。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
  - key: failure-domain.beta.kubernetes.io/zone
    values:
    - us-central1-a
    - us-central1-b

参数

Storage Classes 的参数描述了存储类的卷。取决于制备器,可以接受不同的参数。例如,参数 type 的值 io1 和参数 iopsPerGB 特定于 EBS PV。当参数被省略时,会使用默认值。

一个 StorageClass 最多可以定义 512 个参数。这些参数对象的总长度不能超过 256 KiB, 包括参数的键和值。

AWS EBS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4
  • type:io1,gp2,sc1,st1。详细信息参见 AWS 文档。默认值:gp2。
  • zone(弃用):AWS 区域。如果没有指定 zone 和 zones,通常卷会在 Kubernetes 集群节点所在的活动区域中轮询调度分配。zone 和 zones 参数不能同时使用。
  • zones(弃用):以逗号分隔的 AWS 区域列表。如果没有指定 zone 和 zones,通常卷会在 Kubernetes 集群节点所在的活动区域中轮询调度分配。zone和zones参数不能同时使用。
  • iopsPerGB:只适用于 io1 卷。每 GiB 每秒 I/O 操作。AWS 卷插件将其与请求卷的大小相乘以计算 IOPS 的容量,并将其限制在 20000 IOPS(AWS 支持的最高值,请参阅 AWS 文档。这里需要输入一个字符串,即 "10",而不是 10。
  • fsType:受 Kubernetes 支持的文件类型。默认值:"ext4"。
  • encrypted:指定 EBS 卷是否应该被加密。合法值为 "true" 或者 "false"。这里需要输入字符串,即 "true", 而非 true。
  • kmsKeyId:可选。加密卷时使用密钥的完整 Amazon 资源名称。如果没有提供,但 encrypted 值为 true,AWS 生成一个密钥。关于有效的 ARN 值,请参阅 AWS 文档。

说明:
zone 和 zones 已被弃用并被允许的拓扑结构取代。

GCE PD

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
   fstype: ext4
  replication-type: none
  • type:pd-standard 或者 pd-ssd。默认:pd-standard
  • zone(弃用):GCE 区域。如果没有指定 zone 和 zones,通常卷会在 Kubernetes 集群节点所在的活动区域中轮询调度分配。zone 和 zones 参数不能同时使用。
  • zones(弃用):逗号分隔的 GCE 区域列表。如果没有指定 zone 和 zones,通常卷会在 Kubernetes 集群节点所在的活动区域中轮询调度(round-robin)分配。zone 和 zones 参数不能同时使用。
  • fstype: ext4 或 xfs。默认: ext4。宿主机操作系统必须支持所定义的文件系统类型。
  • replication-type:none 或者 regional-pd。默认值:none。

如果 replication-type 设置为 none,会制备一个常规(当前区域内的)持久化磁盘。

如果 replication-type 设置为 regional-pd,会制备一个区域性持久化磁盘(Regional Persistent Disk)。

强烈建议设置 volumeBindingMode: WaitForFirstConsumer,这样设置后,当你创建一个 Pod,它使用的 PersistentVolumeClaim 使用了这个 StorageClass,区域性持久化磁盘会在两个区域里制备。其中一个区域是 Pod 所在区域。另一个区域是会在集群管理的区域中任意选择。磁盘区域可以通过 allowedTopologies 加以限制。

说明: zone 和 zones 已被弃用并被 allowedTopologies 取代。

Glusterfs

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://127.0.0.1:8081"
  clusterid: "630372ccdc720a92c681fb928f27b53f"
  restauthenabled: "true"
  restuser: "admin"
  secretNamespace: "default"
  secretName: "heketi-secret"
  gidMin: "40000"
  gidMax: "50000"
  volumetype: "replicate:3"
  • resturl:制备 gluster 卷的需求的 Gluster REST 服务/Heketi 服务 url。通用格式应该是 IPaddress:Port,这是 GlusterFS 动态制备器的必需参数。如果 Heketi 服务在 OpenShift/kubernetes 中安装并暴露为可路由服务,则可以使用类似于 http://heketi-storage-project.cloudapps.mystorage.com 的格式,其中 fqdn 是可解析的 heketi 服务网址。

  • restauthenabled:Gluster REST 服务身份验证布尔值,用于启用对 REST 服务器的身份验证。如果此值为 \'true\',则必须填写 restuser 和 restuserkey 或 secretNamespace + secretName。此选项已弃用,当在指定 restuser、restuserkey、secretName 或 secretNamespace 时,身份验证被启用。

  • restuser:在 Gluster 可信池中有权创建卷的 Gluster REST服务/Heketi 用户。

  • restuserkey:Gluster REST 服务/Heketi 用户的密码将被用于对 REST 服务器进行身份验证。此参数已弃用,取而代之的是 secretNamespace + secretName。

  • secretNamespace,secretName:Secret 实例的标识,包含与 Gluster REST 服务交互时使用的用户密码。这些参数是可选的,secretNamespace 和 secretName 都省略时使用空密码。所提供的 Secret 必须将类型设置为 "kubernetes.io/glusterfs",例如以这种方式创建:

    kubectl create secret generic heketi-secret \\
      --type="kubernetes.io/glusterfs" --from-literal=key=\'opensesame\' \\
      --namespace=default
    

    Secret 的例子可以在 glusterfs-provisioning-secret.yaml 中找到。

  • clusterid:630372ccdc720a92c681fb928f27b53f 是集群的 ID,当制备卷时,Heketi 将会使用这个文件。它也可以是一个 clusterid 列表,例如:"8452344e2becec931ece4e33c4674e4e,42982310de6c63381718ccfa6d8cf397"。这个是可选参数。

  • gidMin,gidMax:StorageClass GID 范围的最小值和最大值。在此范围(gidMin-gidMax)内的唯一值(GID)将用于动态制备卷。这些是可选的值。如果不指定,所制备的卷为一个 2000-2147483647 之间的值,这是 gidMin 和 gidMax 的默认值。

  • volumetype:卷的类型及其参数可以用这个可选值进行配置。如果未声明卷类型,则由制备器决定卷的类型。例如:

    • \'Replica volume\': volumetype: replicate:3 其中 \'3\' 是 replica 数量.
    • \'Disperse/EC volume\': volumetype: disperse:4:2 其中 \'4\' 是数据,\'2\' 是冗余数量.
    • \'Distribute volume\': volumetype: none

当动态制备持久卷时,Gluster 插件自动创建名为 gluster-dynamic-<claimname> 的端点和无头服务。在 PVC 被删除时动态端点和无头服务会自动被删除。

NFS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs
parameters:
  server: nfs-server.example.com
  path: /share
  readOnly: false
  • server:NFS 服务器的主机名或 IP 地址。
  • path:NFS 服务器导出的路径。
  • readOnly:是否将存储挂载为只读的标志(默认为 false)。

Kubernetes 不包含内部 NFS 驱动。你需要使用外部驱动为 NFS 创建 StorageClass。这里有些例子:

  • NFS Ganesha 服务器和外部驱动
  • NFS subdir 外部驱动

OpenStack Cinder

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gold
provisioner: kubernetes.io/cinder
parameters:
  availability: nova
  • availability:可用区域。如果没有指定,通常卷会在 Kubernetes 集群节点所在的活动区域中轮转调度。

说明:
FEATURE STATE: Kubernetes 1.11 [deprecated]
OpenStack 的内部驱动已经被弃用。请使用 OpenStack 的外部云驱动。

vSphere

vSphere 存储类有两种制备器

  • CSI 制备器: csi.vsphere.vmware.com
  • vCP 制备器: kubernetes.io/vsphere-volume

树内制备器已经被弃用。更多关于 CSI 制备器的详情,请参阅 Kubernetes vSphere CSI 驱动 和 vSphereVolume CSI 迁移。

CSI 制备器

vSphere CSI StorageClass 制备器在 Tanzu Kubernetes 集群下运行。示例请参 vSphere CSI 仓库。

vCP 制备器

以下示例使用 VMware Cloud Provider (vCP) StorageClass 调度器

  1. 使用用户指定的磁盘格式创建一个 StorageClass。

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast
    provisioner: kubernetes.io/vsphere-volume
    parameters:
      diskformat: zeroedthick
    

    diskformat: thin, zeroedthick 和 eagerzeroedthick。默认值: "thin"。

  2. 在用户指定的数据存储上创建磁盘格式的 StorageClass。

     apiVersion: storage.k8s.io/v1
     kind: StorageClass
     metadata:
       name: fast
     provisioner: kubernetes.io/vsphere-volume
     parameters:
     	diskformat: zeroedthick
     	datastore: VSANDatastore
    

    datastore:用户也可以在 StorageClass 中指定数据存储。卷将在 storage class 中指定的数据存储上创建,在这种情况下是 VSANDatastore。该字段是可选的。如果未指定数据存储,则将在用于初始化 vSphere Cloud Provider 的 vSphere 配置文件中指定的数据存储上创建该卷。

  3. Kubernetes 中的存储策略管理

    • 使用现有的 vCenter SPBM 策略

      vSphere 用于存储管理的最重要特性之一是基于策略的管理。基于存储策略的管理(SPBM)是一个存储策略框架,提供单一的统一控制平面的跨越广泛的数据服务和存储解决方案。SPBM 使能 vSphere 管理员克服先期的存储配置挑战,如容量规划,差异化服务等级和管理容量空间。

      SPBM 策略可以在 StorageClass 中使用 storagePolicyName 参数声明。

    • Kubernetes 内的 Virtual SAN 策略支持

      Vsphere Infrastructure(VI)管理员将能够在动态卷配置期间指定自定义 Virtual SAN 存储功能。你现在可以在动态制备卷期间以存储能力的形式定义存储需求,例如性能和可用性。存储能力需求会转换为 Virtual SAN 策略,之后当持久卷(虚拟磁盘)被创建时,会将其推送到 Virtual SAN 层。虚拟磁盘分布在 Virtual SAN 数据存储中以满足要求。

      你可以参考基于存储策略的动态制备卷管理,进一步了解有关持久卷管理的存储策略的详细信息。

Ceph RBD

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/rbd
parameters:
  monitors: 10.16.153.105:6789
  adminId: kube
  adminSecretName: ceph-secret
  adminSecretNamespace: kube-system
  pool: kube
  userId: kube
  userSecretName: ceph-secret-user
  userSecretNamespace: default
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"
  • monitors:Ceph monitor,逗号分隔。该参数是必需的。

  • adminId:Ceph 客户端 ID,用于在池 ceph 池中创建映像。默认是 "admin"。

  • adminSecret:adminId 的 Secret 名称。该参数是必需的。提供的 secret 必须有值为 "kubernetes.io/rbd" 的 type 参数。

  • adminSecretNamespace:adminSecret 的命名空间。默认是 "default"。

  • pool: Ceph RBD 池. 默认是 "rbd"。

  • userId:Ceph 客户端 ID,用于映射 RBD 镜像。默认与 adminId 相同。

  • userSecretName:用于映射 RBD 镜像的 userId 的 Ceph Secret 的名字。它必须与 PVC 存在于相同的 namespace 中。该参数是必需的。提供的 secret 必须具有值为 "kubernetes.io/rbd" 的 type 参数,例如以这样的方式创建:

    kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \\
      --from-literal=key=\'QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==\' \\
      --namespace=kube-system
    
  • userSecretNamespace:userSecretName 的命名空间。

  • fsType:Kubernetes 支持的 fsType。默认:"ext4"。

  • imageFormat:Ceph RBD 镜像格式,"1" 或者 "2"。默认值是 "1"。

  • imageFeatures:这个参数是可选的,只能在你将 imageFormat 设置为 "2" 才使用。目前支持的功能只是 layering。默认是 "",没有功能打开。

Quobyte

FEATURE STATE: Kubernetes v1.22 [deprecated]

Quobyte 树内(in-tree)存储插件已弃用,你可以在 Quobyte CSI 仓库中找到用于树外(out-of-tree)Quobyte 插件的 StorageClass 示例。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: slow
provisioner: kubernetes.io/quobyte
parameters:
    quobyteAPIServer: "http://138.68.74.142:7860"
    registry: "138.68.74.142:7861"
    adminSecretName: "quobyte-admin-secret"
    adminSecretNamespace: "kube-system"
    user: "root"
    group: "root"
    quobyteConfig: "BASE"
    quobyteTenant: "DEFAULT"
  • quobyteAPIServer:Quobyte API 服务器的格式是 "http(s)://api-server:7860"

  • registry:用于挂载卷的 Quobyte 仓库。你可以指定仓库为 <host>:<port> 或者如果你想指定多个 registry,在它们之间添加逗号,例如 <host1>:<port>,<host2>:<port>,<host3>:<port>。主机可以是一个 IP 地址,或者如果你有正在运行的 DNS,你也可以提供 DNS 名称。

  • adminSecretNamespace:adminSecretName 的名字空间。默认值是 "default"。

  • adminSecretName:保存关于 Quobyte 用户和密码的 Secret,用于对 API 服务器进行身份验证。提供的 secret 必须有值为 "kubernetes.io/quobyte" 的 type 参数和 user 与 password 的键值,例如以这种方式创建:

    kubectl create secret generic quobyte-admin-secret \\
      --type="kubernetes.io/quobyte" --from-literal=key=\'opensesame\' \\
      --namespace=kube-system
    
  • user:对这个用户映射的所有访问权限。默认是 "root"。

  • group:对这个组映射的所有访问权限。默认是 "nfsnobody"。

  • quobyteConfig:使用指定的配置来创建卷。你可以创建一个新的配置,或者,可以修改 Web 控制台或 quobyte CLI 中现有的配置。默认是 "BASE"。

  • quobyteTenant:使用指定的租户 ID 创建/删除卷。这个 Quobyte 租户必须已经于 Quobyte 中存在。默认是 "DEFAULT"。

Azure 磁盘

Azure Unmanaged Disk Storage Class(非托管磁盘存储类)

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: slow
provisioner: kubernetes.io/azure-disk
parameters:
  skuName: Standard_LRS
  location: eastus
  storageAccount: azure_storage_account_name
  • skuName:Azure 存储帐户 Sku 层。默认为空。
  • location:Azure 存储帐户位置。默认为空。
  • storageAccount:Azure 存储帐户名称。如果提供存储帐户,它必须位于与集群相同的资源组中,并且 location 是被忽略的。如果未提供存储帐户,则会在与群集相同的资源组中创建新的存储帐户。

Azure 磁盘 Storage Class(从 v1.7.2 开始)

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: slow
provisioner: kubernetes.io/azure-disk
parameters:
  storageaccounttype: Standard_LRS
  kind: managed
  • storageaccounttype:Azure 存储帐户 Sku 层。默认为空。
  • kind:可能的值是 shared、dedicated 和 managed(默认)。当 kind 的值是 shared 时,所有非托管磁盘都在集群的同一个资源组中的几个共享存储帐户中创建。当 kind 的值是 dedicated 时,将为在集群的同一个资源组中新的非托管磁盘创建新的专用存储帐户。
  • resourceGroup: 指定要创建 Azure 磁盘所属的资源组。必须是已存在的资源组名称。若未指定资源组,磁盘会默认放入与当前 Kubernetes 集群相同的资源组中。
  • Premium VM 可以同时添加 Standard_LRS 和 Premium_LRS 磁盘,而 Standard 虚拟机只能添加 Standard_LRS 磁盘。
  • 托管虚拟机只能连接托管磁盘,非托管虚拟机只能连接非托管磁盘。

Azure 文件

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: azurefile
provisioner: kubernetes.io/azure-file
parameters:
  skuName: Standard_LRS
  location: eastus
  storageAccount: azure_storage_account_name
  • skuName:Azure 存储帐户 Sku 层。默认为空。
  • location:Azure 存储帐户位置。默认为空。
  • storageAccount:Azure 存储帐户名称。默认为空。如果不提供存储帐户,会搜索所有与资源相关的存储帐户,以找到一个匹配 skuName 和 location 的账号。如果提供存储帐户,它必须存在于与集群相同的资源组中,skuName 和 location 会被忽略。
  • secretNamespace:包含 Azure 存储帐户名称和密钥的密钥的名称空间。默认值与 Pod 相同。
  • secretName:包含 Azure 存储帐户名称和密钥的密钥的名称。默认值为 azure-storage-account-<accountName>-secret
  • readOnly:指示是否将存储安装为只读的标志。默认为 false,表示"读/写"挂载。该设置也会影响VolumeMounts中的 ReadOnly 设置。

在存储制备期间,为挂载凭证创建一个名为 secretName 的 Secret。如果集群同时启用了 RBAC 和控制器角色,为 system:controller:persistent-volume-binder 的 clusterrole 添加 Secret 资源的 create 权限。

在多租户上下文中,强烈建议显式设置 secretNamespace 的值,否则其他用户可能会读取存储帐户凭据。

Portworx 卷

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: portworx-io-priority-high
provisioner: kubernetes.io/portworx-volume
parameters:
  repl: "1"
  snap_interval:   "70"
  priority_io:  "high"
  • fs:选择的文件系统:none/xfs/ext4(默认:ext4)。
  • block_size:以 Kbytes 为单位的块大小(默认值:32)。
  • repl:同步副本数量,以复制因子 1..3(默认值:1)的形式提供。这里需要填写字符串,即,"1" 而不是 1。
  • io_priority:决定是否从更高性能或者较低优先级存储创建卷 high/medium/low(默认值:low)。
  • snap_interval:触发快照的时钟/时间间隔(分钟)。快照是基于与先前快照的增量变化,0 是禁用快照(默认:0)。这里需要填写字符串,即,是 "70" 而不是 70。
  • aggregation_level:指定卷分配到的块数量,0 表示一个非聚合卷(默认:0)。这里需要填写字符串,即,是 "0" 而不是 0。
  • ephemeral:指定卷在卸载后进行清理还是持久化。emptyDir 的使用场景可以将这个值设置为 true,persistent volumes 的使用场景可以将这个值设置为 false (例如 Cassandra 这样的数据库)true/false(默认为 false)。这里需要填写字符串,即,是 "true" 而不是 true。

ScaleIO

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: slow
provisioner: kubernetes.io/scaleio
parameters:
  gateway: https://192.168.99.200:443/api
  system: scaleio
  protectionDomain: pd0
  storagePool: sp1
  storageMode: ThinProvisioned
  secretRef: sio-secret
  readOnly: false
  fsType: xfs
  • provisioner:属性设置为 kubernetes.io/scaleio
  • gateway 到 ScaleIO API 网关的地址(必需)
  • system:ScaleIO 系统的名称(必需)
  • protectionDomain:ScaleIO 保护域的名称(必需)
  • storagePool:卷存储池的名称(必需)
  • storageMode:存储提供模式:ThinProvisioned(默认)或 ThickProvisioned
  • secretRef:对已配置的 Secret 对象的引用(必需)
  • readOnly:指定挂载卷的访问模式(默认为 false)
  • fsType:卷的文件系统(默认是 ext4)

ScaleIO Kubernetes 卷插件需要配置一个 Secret 对象。Secret 必须用 kubernetes.io/scaleio 类型创建,并与引用它的 PVC 所属的名称空间使用相同的值。如下面的命令所示:

kubectl create secret generic sio-secret --type="kubernetes.io/scaleio" \\
  --from-literal=username=sioadmin --from-literal=password=d2NABDNjMA== \\
  --namespace=default

StorageOS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/storageos
parameters:
  pool: default
  description: Kubernetes volume
  fsType: ext4
  adminSecretNamespace: default
  adminSecretName: storageos-secret
  • pool:制备卷的 StorageOS 分布式容量池的名称。如果未指定,则使用通常存在的 default 池。
  • description:指定给动态创建的卷的描述。所有卷描述对于存储类而言都是相同的,但不同的 storage class 可以使用不同的描述,以区分不同的使用场景。默认为 Kubernetes volume。
  • fsType:请求的默认文件系统类型。请注意,在 StorageOS 中用户定义的规则可以覆盖此值。默认为 ext4
  • adminSecretNamespace:API 配置 secret 所在的命名空间。如果设置了 adminSecretName,则是必需的。
  • adminSecretName:用于获取 StorageOS API 凭证的 secret 名称。如果未指定,则将尝试默认值。

StorageOS Kubernetes 卷插件可以使 Secret 对象来指定用于访问 StorageOS API 的端点和凭据。只有当默认值已被更改时,这才是必须的。Secret 必须使用 kubernetes.io/storageos 类型创建,如以下命令:

kubectl create secret generic storageos-secret \\
--type="kubernetes.io/storageos" \\
--from-literal=apiAddress=tcp://localhost:5705 \\
--from-literal=apiUsername=storageos \\
--from-literal=apiPassword=storageos \\
--namespace=default

用于动态制备卷的 Secret 可以在任何名称空间中创建,并通过 adminSecretNamespace 参数引用。预先配置的卷使用的 Secret 必须在与引用它的 PVC 在相同的名称空间中。

本地

FEATURE STATE: Kubernetes v1.14 [stable]

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

本地卷还不支持动态制备,然而还是需要创建 StorageClass 以延迟卷绑定,直到完成 Pod 的调度。这是由 WaitForFirstConsumer 卷绑定模式指定的。

延迟卷绑定使得调度器在为 PersistentVolumeClaim 选择一个合适的 PersistentVolume 时能考虑到所有 Pod 的调度限制。

7 - 动态卷供应

动态卷供应允许按需创建存储卷。如果没有动态供应,集群管理员必须手动地联系他们的云或存储提供商来创建新的存储卷,然后在 Kubernetes 集群创建 PersistentVolume 对象来表示这些卷。动态供应功能消除了集群管理员预先配置存储的需要。相反,它在用户请求时自动供应存储。

背景

动态卷供应的实现基于 storage.k8s.io API 组中的 StorageClass API 对象。集群管理员可以根据需要定义多个 StorageClass 对象,每个对象指定一个卷插件(又名 provisioner),卷插件向卷供应商提供在创建卷时需要的数据卷信息及相关参数。

集群管理员可以在集群中定义和公开多种存储(来自相同或不同的存储系统),每种都具有自定义参数集。该设计也确保终端用户不必担心存储供应的复杂性和细微差别,但仍然能够从多个存储选项中进行选择。

启用动态卷供应

要启用动态供应功能,集群管理员需要为用户预先创建一个或多个 StorageClass 对象。StorageClass 对象定义当动态供应被调用时,哪一个驱动将被使用和哪些参数将被传递给驱动。以下清单创建了一个 StorageClass 存储类 "slow",它提供类似标准磁盘的永久磁盘。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard

以下清单创建了一个 "fast" 存储类,它提供类似 SSD 的永久磁盘。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

使用动态卷供应

用户通过在 PersistentVolumeClaim 中包含存储类来请求动态供应的存储。在 Kubernetes v1.9 之前,这通过 volume.beta.kubernetes.io/storage-class 注解实现。然而,这个注解自 v1.6 起就不被推荐使用了。用户现在能够而且应该使用 PersistentVolumeClaim 对象的 storageClassName 字段。这个字段的值必须能够匹配到集群管理员配置的 StorageClass 名称(见下面)。

例如,要选择 “fast” 存储类,用户将创建如下的 PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

该声明会自动供应一块类似 SSD 的永久磁盘。在删除该声明后,这个卷也会被销毁。

设置默认值的行为

可以在群集上启用动态卷供应,以便在未指定存储类的情况下动态设置所有声明。集群管理员可以通过以下方式启用此行为:

  • 标记一个 StorageClass 为默认;
  • 确保 DefaultStorageClass 准入控制器在 API 服务端被启用。

管理员可以通过向其添加 storageclass.kubernetes.io/is-default-class 注解来将特定的 StorageClass 标记为默认。当集群中存在默认的 StorageClass 并且用户创建了一个未指定 storageClassName 的 PersistentVolumeClaim 时,DefaultStorageClass 准入控制器会自动向其中添加指向默认存储类的 storageClassName 字段。

请注意,群集上最多只能有一个默认存储类,否则无法创建没有明确指定 storageClassName 的 PersistentVolumeClaim。

拓扑感知

在多区域集群中,Pod 可以被分散到多个区域。单区域存储后端应该被供应到 Pod 被调度到的区域。这可以通过设置卷绑定模式来实现。

8 - 卷快照

FEATURE STATE: Kubernetes 1.17 [beta]

在 Kubernetes 中,卷快照是一个存储系统上卷的快照,本文假设你已经熟悉了 Kubernetes 的持久卷。

介绍

与 PersistentVolume 和 PersistentVolumeClaim 两个 API 资源用于给用户和管理员提供卷类似,VolumeSnapshotContent 和 VolumeSnapshot 两个 API 资源用于给用户和管理员创建卷快照。

VolumeSnapshotContent 是一种快照,从管理员已提供的集群中的卷获取。就像持久卷是集群的资源一样,它也是集群中的资源。

VolumeSnapshot 是用户对于卷的快照的请求。它类似于持久卷声明。

VolumeSnapshotClass 允许指定属于 VolumeSnapshot 的不同属性。在从存储系统的相同卷上获取的快照之间,这些属性可能有所不同,因此不能通过使用与 PersistentVolumeClaim 相同的 StorageClass 来表示。

卷快照能力为 Kubernetes 用户提供了一种标准的方式来在指定时间点复制卷的内容,并且不需要创建全新的卷。例如,这一功能使得数据库管理员能够在执行编辑或删除之类的修改之前对数据库执行备份。

当使用该功能时,用户需要注意以下几点:

  • API 对象 VolumeSnapshot,VolumeSnapshotContent 和 VolumeSnapshotClass 是 CRDs,不属于核心 API。
  • VolumeSnapshot 支持仅可用于 CSI 驱动。
  • 作为 VolumeSnapshot 部署过程的一部分,Kubernetes 团队提供了一个部署于控制平面的快照控制器,并且提供了一个叫做 csi-snapshotter 的边车(Sidecar)辅助容器,和 CSI 驱动程序一起部署。快照控制器监视 VolumeSnapshot 和 VolumeSnapshotContent 对象,并且负责创建和删除 VolumeSnapshotContent 对象。边车 csi-snapshotter 监视 VolumeSnapshotContent 对象,并且触发针对 CSI 端点的 CreateSnapshot 和 DeleteSnapshot 的操作。
  • 还有一个验证性质的 Webhook 服务器,可以对快照对象进行更严格的验证。Kubernetes 发行版应将其与快照控制器和 CRD(而非 CSI 驱动程序)一起安装。此服务器应该安装在所有启用了快照功能的 Kubernetes 集群中。
  • CSI 驱动可能实现,也可能没有实现卷快照功能。CSI 驱动可能会使用 csi-snapshotter 来提供对卷快照的支持。详见 CSI 驱动程序文档
  • Kubernetes 负责 CRDs 和快照控制器的安装。

卷快照和卷快照内容的生命周期

VolumeSnapshotContents 是集群中的资源。VolumeSnapshots 是对于这些资源的请求。

VolumeSnapshotContents 和 VolumeSnapshots 之间的交互遵循以下生命周期:

供应卷快照

快照可以通过两种方式进行配置:预配置或动态配置。

预配置

集群管理员创建多个 VolumeSnapshotContents。它们带有存储系统上实际卷快照的详细信息,可以供集群用户使用。它们存在于 Kubernetes API 中,并且能够被使用。

动态的

可以从 PersistentVolumeClaim 中动态获取快照,而不用使用已经存在的快照。在获取快照时,卷快照类指定要用的特定于存储提供程序的参数。

绑定

在预配置和动态配置场景下,快照控制器处理绑定 VolumeSnapshot 对象和其合适的 VolumeSnapshotContent 对象。绑定关系是一对一的。

在预配置快照绑定场景下,VolumeSnapshotContent 对象创建之后,才会和 VolumeSnapshot 进行绑定。

快照源的持久性卷声明保护

这种保护的目的是确保在从系统中获取快照时,不会将正在使用的 PersistentVolumeClaim API 对象从系统中删除(因为这可能会导致数据丢失)。

如果一个 PVC 正在被快照用来作为源进行快照创建,则该 PVC 是使用中的。如果用户删除正作为快照源的 PVC API 对象,则 PVC 对象不会立即被删除掉。相反,PVC 对象的删除将推迟到任何快照不在主动使用它为止。当快照的 Status 中的 ReadyToUse值为 true 时,PVC 将不再用作快照源。

当从 PersistentVolumeClaim 中生成快照时,PersistentVolumeClaim 就在被使用了。如果删除一个作为快照源的 PersistentVolumeClaim 对象,这个 PersistentVolumeClaim 对象不会立即被删除的。相反,删除 PersistentVolumeClaim 对象的动作会被放弃,或者推迟到快照的 Status 为 ReadyToUse时再执行。

删除

删除 VolumeSnapshot 对象触发删除 VolumeSnapshotContent 操作,并且 DeletionPolicy 会紧跟着执行。如果 DeletionPolicy 是 Delete,那么底层存储快照会和 VolumeSnapshotContent 一起被删除。如果 DeletionPolicy 是 Retain,那么底层快照和 VolumeSnapshotContent 都会被保留。

卷快照

每个 VolumeSnapshot 包含一个 spec 和一个状态。

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: new-snapshot-test
spec:
  volumeSnapshotClassName: csi-hostpath-snapclass
  source:
    persistentVolumeClaimName: pvc-test

persistentVolumeClaimName 是 PersistentVolumeClaim 数据源对快照的名称。这个字段是动态配置快照中的必填字段。

卷快照可以通过指定 VolumeSnapshotClass 使用 volumeSnapshotClassName 属性来请求特定类。如果没有设置,那么使用默认类(如果有)。

如下面例子所示,对于预配置的快照,需要给快照指定 volumeSnapshotContentName 来作为源。对于预配置的快照 source 中的volumeSnapshotContentName 字段是必填的。

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: test-snapshot
spec:
  source:
    volumeSnapshotContentName: test-content

每个 VolumeSnapshotContent 对象包含 spec 和 status。在动态配置时,快照通用控制器创建 VolumeSnapshotContent 对象。下面是例子:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: snapcontent-72d9a349-aacd-42d2-a240-d775650d2455
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    volumeHandle: ee0cfb94-f8d4-11e9-b2d8-0242ac110002
  volumeSnapshotClassName: csi-hostpath-snapclass
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default
    uid: 72d9a349-aacd-42d2-a240-d775650d2455

volumeHandle 是存储后端创建卷的唯一标识符,在卷创建期间由 CSI 驱动程序返回。动态设置快照需要此字段。它指出了快照的卷源。

对于预配置快照,你(作为集群管理员)要按如下命令来创建 VolumeSnapshotContent 对象。

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: new-snapshot-content-test
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default

snapshotHandle 是存储后端创建卷的唯一标识符。对于预设置快照,这个字段是必须的。它指定此 VolumeSnapshotContent 表示的存储系统上的 CSI 快照 id。

从快照供应卷

你可以配置一个新卷,该卷预填充了快照中的数据,在持久卷声明对象中使用 dataSource 字段。

9 - 存储容量

存储容量是有限的,并且会因为运行 Pod 的节点不同而变化:网络存储可能并非所有节点都能够访问,或者对于某个节点存储是本地的。

FEATURE STATE: Kubernetes v1.21 [beta]

本页面描述了 Kubernetes 如何跟踪存储容量以及调度程序如何为了余下的尚未挂载的卷使用该信息将 Pod 调度到能够访问到足够存储容量的节点上。如果没有跟踪存储容量,调度程序可能会选择一个没有足够容量来提供卷的节点,并且需要多次调度重试。

容器存储接口(CSI)驱动程序支持跟踪存储容量,并且在安装 CSI 驱动程序时需要启用该功能。

API

这个特性有两个 API 扩展接口:

  • CSIStorageCapacity 对象:这些对象由 CSI 驱动程序在安装驱动程序的命名空间中产生。每个对象都包含一个存储类的容量信息,并定义哪些节点可以访问该存储。
  • CSIDriverSpec.StorageCapacity 字段:设置为 true 时,Kubernetes 调度程序将考虑使用 CSI 驱动程序的卷的存储容量。

调度

如果有以下情况,存储容量信息将会被 Kubernetes 调度程序使用:

  • CSIStorageCapacity 特性门控被设置为 true。
  • Pod 使用的卷还没有被创建。
  • 卷使用引用了 CSI 驱动的 StorageClass,并且使用了 WaitForFirstConsumer 卷绑定模式。
  • 驱动程序的 CSIDriver 对象的 StorageCapacity 被设置为 true。

在这种情况下,调度程序仅考虑将 Pod 调度到有足够存储容量的节点上。这个检测非常简单,仅将卷的大小与 CSIStorageCapacity 对象中列出的容量进行比较,并使用包含该节点的拓扑。

对于具有 Immediate 卷绑定模式的卷,存储驱动程序将决定在何处创建该卷,而不取决于将使用该卷的 Pod。然后,调度程序将 Pod 调度到创建卷后可使用该卷的节点上。

对于 CSI 临时卷,调度总是在不考虑存储容量的情况下进行。这是基于这样的假设:该卷类型仅由节点本地的特殊 CSI 驱动程序使用,并且不需要大量资源。

重新调度

当为带有 WaitForFirstConsumer 的卷的 Pod 来选择节点时,该决定仍然是暂定的。下一步是要求 CSI 存储驱动程序创建卷,并提示该卷在被选择的节点上可用。

因为 Kubernetes 可能会根据已经过时的存储容量信息来选择一个节点,因此可能无法真正创建卷。然后就会重置节点选择,Kubernetes 调度器会再次尝试为 Pod 查找节点。

限制

存储容量跟踪增加了调度器第一次尝试即成功的机会,但是并不能保证这一点,因为调度器必须根据可能过期的信息来进行决策。通常,与没有任何存储容量信息的调度相同的重试机制可以处理调度失败。

当 Pod 使用多个卷时,调度可能会永久失败:一个卷可能已经在拓扑段中创建,而该卷又没有足够的容量来创建另一个卷,要想从中恢复,必须要进行手动干预,比如通过增加存储容量或者删除已经创建的卷。需要进一步工作来自动处理此问题。

开启存储容量跟踪

存储容量跟踪是一个 Beta 特性,从 Kubernetes 1.21 版本起在 Kubernetes 集群中默认被启用。除了在集群中启用此功能特性之外,还要求 CSI 驱动支持此特性。请参阅驱动的文档了解详细信息。

10 - 卷健康监测

FEATURE STATE: Kubernetes v1.21 [alpha]

CSI 卷健康监测支持 CSI 驱动从底层的存储系统着手,探测异常的卷状态,并以事件的形式上报到 PVCs 或 Pods。

卷健康监测

Kubernetes 卷健康监测是 Kubernetes 容器存储接口(CSI)实现的一部分。卷健康监测特性由两个组件实现:外部健康监测控制器和 kubelet。

如果 CSI 驱动器通过控制器的方式支持卷健康监测特性,那么只要在 CSI 卷上监测到异常卷状态,就会在 PersistentVolumeClaim (PVC) 中上报一个事件。

外部健康监测控制器也会监测节点失效事件。如果要启动节点失效监测功能,你可以设置标志 enable-node-watcher 为 true。当外部健康监测器检测到一个节点失效事件,控制器会报送一个事件,该事件会在 PVC 上继续上报,以表明使用此 PVC 的 Pod 正位于一个失效的节点上。

如果 CSI 驱动程序支持节点测的卷健康检测,那当在 CSI 卷上检测到异常卷时,会在使用该 PVC 的每个 Pod 上触发一个事件。

说明: 你需要启用 CSIVolumeHealth 特性门控,才能从节点测使用此特性。

11 - 特定于节点的卷数限制

此页面描述了各个云供应商可关联至一个节点的最大卷数。

谷歌、亚马逊和微软等云供应商通常对可以关联到节点的卷数量进行限制。Kubernetes 需要尊重这些限制。否则,在节点上调度的 Pod 可能会卡住去等待卷的关联。

Kubernetes 的默认限制

The Kubernetes 调度器对关联于一个节点的卷数有默认限制:

云服务
每节点最大卷数
39
16
16

自定义限制

您可以通过设置 KUBE_MAX_PD_VOLS 环境变量的值来设置这些限制,然后再启动调度器。CSI 驱动程序可能具有不同的过程,关于

以上是关于[K8s]Kubernetes-存储(下)的主要内容,如果未能解决你的问题,请参考以下文章

k8s实战系列:3-存储的花样玩法(下)

k8s实战系列:3-存储的花样玩法(下)

k8s实战系列:3-存储的花样玩法(下)

云原生之kubernetes实战kubernetes集群下的存储持久化

云原生 | Kubernetes篇Kubernetes(k8s)临时存储

云原生之kubernetes实战在k8s集群下部署wordpress