具有存储容量跟踪的临时卷:类固醇上的 EmptyDir

具有存储容量跟踪的临时卷:类固醇上的 EmptyDir

有些应用程序也需要存储数据,但他们对重启后不会保存数据这一事实感到非常满意。

例如,缓存服务受到 RAM 的限制,但也可以将很少使用的数据移动到比 RAM 慢的存储中,对整体性能影响很小。 其他应用程序需要注意文件中可能存在一些只读输入,例如设置或密钥。

Kubernetes 已经有几种类型 短暂的卷,但它们的功能仅限于 K8s 中实现的功能。

短暂的 CSI 卷 允许使用 CSI 驱动程序扩展 Kubernetes,以提供对轻量级本地卷的支持。 这样就可以使用 任意结构:设置、秘密、识别数据、变量等。 必须修改 CSI 驱动程序才能支持此 Kubernetes 功能,因为假定常规标准化驱动程序将不起作用 - 但假定此类卷可以在为 pod 选择的任何节点上使用。

对于消耗大量主机资源的卷或仅在某些主机上可用的存储来说,这可能是一个问题。 这就是为什么 Kubernetes 1.19 引入了两个新的 alpha 测试卷功能,它们在概念上类似于 EmptyDir 卷:

  • 通用临时卷;

  • CSI 存储容量跟踪。

新方法的优点:

  • 存储可以是本地的或通过网络连接的;

  • 卷可以具有应用程序不能超过的指定大小;

  • 与任何支持持久卷配置并(支持容量跟踪)实现调用的 CSI 驱动程序配合使用 GetCapacity;

  • 卷可能有一些初始数据,具体取决于驱动程序和设置;

  • 支持卷的所有标准操作(创建快照、调整大小等);

  • 卷可以与任何接受模块或卷规范的应用程序控制器一起使用;

  • Kubernetes 调度程序会自行选择合适的节点,因此不再需要预配和配置调度程序扩展或修改 Webhook。

应用选项

因此,通用临时卷适用于以下用例:

持久内存作为 memcached RAM 的替代品

memcached 的最新版本 增加了支持 使用持久内存(Intel Optane等, 约译者)而不是常规 RAM。 通过应用程序控制器部署 memcached 时,您可以使用通用临时卷来请求使用 CSI 驱动程序从 PMEM 分配给定大小的卷,例如 PMEM-CSI.

LVM 本地存储作为工作区

处理大于 RAM 的数据的应用程序可能需要具有 Kubernetes 的常规 EmptyDir 卷无法提供的大小或性能指标的本地存储。 例如,为了这个目的,写了 拓扑LVM.

数据卷的只读访问

在以下情况下,分配卷可能会导致创建完整卷:

这些卷可以以只读模式安装。

怎么开动这个

通用临时卷

通用临时卷的一个关键特征是新的卷源, EphemeralVolumeSource,包含创建卷请求(历史上称为持久卷请求,PVC)的所有字段。 新控制器在 kube-controller-manager 查看创建此类卷源的 pod,然后为这些 pod 创建 PVC。 对于 CSI 驱动程序,此请求看起来与其他请求相同,因此这里不需要特殊支持。

只要此类 PVC 存在,就可以像卷上的任何其他请求一样使用它们。 特别是,在复制卷或从卷创建快照时,它们可以被引用为数据源。 PVC 对象还包含卷的当前状态。

自动创建的 PVC 的名称是预定义的:它们是 pod 名称和卷名称的组合,并用连字符分隔。 预定义的名称使与 PVC 的交互变得更加容易,因为如果您知道 pod 名称和卷名称,则无需查找它。 缺点是该名称可能已被使用,这是由 Kubernetes 检测到的,因此 pod 无法启动。

为了确保卷与 Pod 一起删除,控制器向所有者下的卷发出请求。 当 Pod 被删除时,标准垃圾收集机制就会起作用,它会删除请求和卷。

存储驱动程序通过存储类的正常机制来匹配请求。 尽管具有立即绑定和后期绑定的类(又名 WaitForFirstConsumer)受支持,对于临时卷,使用它是有意义的 WaitForFirstConsumer,那么调度器在选择节点时可以同时考虑节点使用情况和存储可用性。 这里出现了一个新功能。

存储容量跟踪

通常,调度程序不知道 CSI 驱动程序将在何处创建卷。 调度程序也无法直接联系驱动程序来请求此信息。 因此,调度程序会轮询节点,直到找到可以访问卷的节点(后期绑定)或将位置选择完全留给驱动程序(立即绑定)。

API CSIStorageCapacity处于 alpha 阶段,允许将必要的数据存储在 etcd 中,以便调度程序可用。 与通用临时卷的支持不同,部署驱动程序时,必须启用存储容量跟踪: external-provisioner 应通过正常方式发布从驱动程序收到的容量信息 GetCapacity.

如果调度程序需要为具有使用后期绑定的未绑定卷的 Pod 选择节点,并且驱动程序在部署期间通过设置标志启用了此功能 CSIDriver.storageCapacity,那么没有足够存储容量的节点将被自动丢弃。 这适用于通用临时卷和持久卷,但不适用于 CSI 临时卷,因为 Kubernetes 无法读取它们的参数。

与往常一样,立即链接的卷是在调度 Pod 之前创建的,并且它们的位置由存储驱动程序选择,因此在配置时 external-provisioner 默认情况下,会跳过具有立即绑定的存储类,因为无论如何都不会使用此数据。

由于 kubernetes 调度程序被迫使用可能过时的信息,因此无法保证在创建卷时在每种情况下容量都可用,但在不重试的情况下创建卷的可能性仍然会增加。

注: 您可以获得更详细的信息,以及安全地“猫站练习”,并且在完全无法理解的情况下,在强化课程中获得合格的技术支持帮助 - Kubernetes 基地 将于 28 月 30 日至 XNUMX 日举行,对于更高级的专家 Kubernetes Mega 14 月 16 日至 XNUMX 日。

安全

CSI存储容量

CSIStorageCapacity 对象驻留在命名空间中;在其自己的命名空间中推出每个 CSI 驱动程序时,建议限制对该空间中的 CSIStorageCapacity 的 RBAC 权限,因为数据的来源显而易见。 无论如何,Kubernetes 不会检查这一点,通常驱动程序会放在同一个命名空间中,因此最终驱动程序应该能够工作并且不会发布错误的数据(这就是我的卡失败的地方, 约。 译者根据一个大胡子笑话改编)

通用临时卷

如果用户有权(直接或间接)创建 pod,那么即使他们无权在卷上创建请求,他们也将能够创建通用临时卷。 这是因为 RBAC 权限检查应用于创建 PVC 的控制器,而不是用户。 这是要添加的主要更改 到您的帐户,然后在群集上启用此功能,其中不受信任的用户不应有权创建卷。

例子

自己 PMEM-CSI 包含在 QEMU 虚拟机内运行 Kubernetes 1.19 集群所需的所有更改,并具有 alpha 阶段的所有功能。 驱动程序代码没有改变,只是部署发生了变化。

在合适的机器上(Linux,普通用户可以使用 码头工人, 看 这里 详细信息)这些命令将启动集群并安装 PMEM-CSI 驱动程序:

git clone --branch=kubernetes-1-19-blog-post https://github.com/intel/pmem-csi.git
cd pmem-csi
export TEST_KUBERNETES_VERSION=1.19 TEST_FEATURE_GATES=CSIStorageCapacity=true,GenericEphemeralVolume=true TEST_PMEM_REGISTRY=intel
make start && echo && test/setup-deployment.sh

一切正常后,输出将包含使用说明:

The test cluster is ready. Log in with [...]/pmem-csi/_work/pmem-govm/ssh.0, run
kubectl once logged in.  Alternatively, use kubectl directly with the
following env variable:
   KUBECONFIG=[...]/pmem-csi/_work/pmem-govm/kube.config

secret/pmem-csi-registry-secrets created
secret/pmem-csi-node-secrets created
serviceaccount/pmem-csi-controller created
...
To try out the pmem-csi driver ephemeral volumes:
   cat deploy/kubernetes-1.19/pmem-app-ephemeral.yaml |
   [...]/pmem-csi/_work/pmem-govm/ssh.0 kubectl create -f -

CSIStorageCapacity 对象不适合人类读取,因此需要进行一些处理。 Golang 模板过滤器将显示存储类别,此示例将显示名称、拓扑和容量:

$ kubectl get 
        -o go-template='{{range .items}}{{if eq .storageClassName "pmem-csi-sc-late-binding"}}{{.metadata.name}} {{.nodeTopology.matchLabels}} {{.capacity}}
{{end}}{{end}}' 
        csistoragecapacities
csisc-2js6n map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker2] 30716Mi
csisc-sqdnt map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker1] 30716Mi
csisc-ws4bv map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker3] 30716Mi

单个对象具有以下内容:

$ kubectl describe csistoragecapacities/csisc-6cw8j
Name:         csisc-sqdnt
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  storage.k8s.io/v1alpha1
Capacity:     30716Mi
Kind:         CSIStorageCapacity
Metadata:
  Creation Timestamp:  2020-08-11T15:41:03Z
  Generate Name:       csisc-
  Managed Fields:
    ...
  Owner References:
    API Version:     apps/v1
    Controller:      true
    Kind:            StatefulSet
    Name:            pmem-csi-controller
    UID:             590237f9-1eb4-4208-b37b-5f7eab4597d1
  Resource Version:  2994
  Self Link:         /apis/storage.k8s.io/v1alpha1/namespaces/default/csistoragecapacities/csisc-sqdnt
  UID:               da36215b-3b9d-404a-a4c7-3f1c3502ab13
Node Topology:
  Match Labels:
    pmem-csi.intel.com/node:  pmem-csi-pmem-govm-worker1
Storage Class Name:           pmem-csi-sc-late-binding
Events:                       <none>

让我们尝试创建一个具有单个通用临时卷的演示应用程序。 文件内容 pmem-app-ephemeral.yaml:

# This example Pod definition demonstrates
# how to use generic ephemeral inline volumes
# with a PMEM-CSI storage class.
kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app-inline-volume
spec:
  containers:
    - name: my-frontend
      image: intel/pmem-csi-driver-test:v0.7.14
      command: [ "sleep", "100000" ]
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-volume
  volumes:
  - name: my-csi-volume
    ephemeral:
      volumeClaimTemplate:
        spec:
          accessModes:
          - ReadWriteOnce
          resources:
            requests:
              storage: 4Gi
          storageClassName: pmem-csi-sc-late-binding

创建完成后,如上面的说明所示,我们现在有了一个额外的 pod 和 PVC:

$ kubectl get pods/my-csi-app-inline-volume -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP          NODE                         NOMINATED NODE   READINESS GATES
my-csi-app-inline-volume   1/1     Running   0          6m58s   10.36.0.2   pmem-csi-pmem-govm-worker1   <none>           <none>
$ kubectl get pvc/my-csi-app-inline-volume-my-csi-volume
NAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS               AGE
my-csi-app-inline-volume-my-csi-volume   Bound    pvc-c11eb7ab-a4fa-46fe-b515-b366be908823   4Gi        RWO            pmem-csi-sc-late-binding   9m21s

PVC 所有者 - 下:

$ kubectl get -o yaml pvc/my-csi-app-inline-volume-my-csi-volume
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    volume.beta.kubernetes.io/storage-provisioner: pmem-csi.intel.com
    volume.kubernetes.io/selected-node: pmem-csi-pmem-govm-worker1
  creationTimestamp: "2020-08-11T15:44:57Z"
  finalizers:
  - kubernetes.io/pvc-protection
  managedFields:
    ...
  name: my-csi-app-inline-volume-my-csi-volume
  namespace: default
  ownerReferences:
  - apiVersion: v1
    blockOwnerDeletion: true
    controller: true
    kind: Pod
    name: my-csi-app-inline-volume
    uid: 75c925bf-ca8e-441a-ac67-f190b7a2265f
...

预计更新信息为 pmem-csi-pmem-govm-worker1:

csisc-2js6n map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker2] 30716Mi
csisc-sqdnt map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker1] 26620Mi
csisc-ws4bv map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker3] 30716Mi

如果另一个应用程序需要超过26620Mi,调度程序将不会考虑 pmem-csi-pmem-govm-worker1 任何状况之下。

接下来是什么?

这两个功能仍在开发中。 在 alpha 测试期间打开了多个应用程序。 改进提案链接记录了进入测试阶段需要完成的工作,以及已经考虑和拒绝的替代方案:

来源: habr.com

添加评论