kubernetes 为什么可以在一个永久卷上设置多个accessMode?

0kjbasz6  于 2023-03-29  发布在  Kubernetes
关注(0)|答案(2)|浏览(172)

例如在以下示例中:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: exmaple-pvc
spec:
  accessModes:
    - ReadOnlyMany
    - ReadWriteMany
  storageClassName: standard
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi

为什么允许这样做?在这种情况下卷的实际行为是什么?只读?读和写?

tyu7yeag

tyu7yeag1#

为了能够完全理解为什么在yaml定义的特定字段中使用某个结构,首先我们需要了解这个特定字段的用途。我们需要问它是做什么的,它在这个特定的kubernetes api-resource中有什么功能。
我很难在PersistentVolumeClaim中找到accessModes的正确解释,我必须承认,我在官方kubernetes文档中找到的内容并没有让我满意:
PersistentVolume可以以资源提供程序支持的任何方式挂载到主机上。如下表所示,提供程序将具有不同的功能,并且每个PV的访问模式都设置为该特定卷支持的特定模式。例如,NFS可以支持多个读/写客户端,但是一个特定的NFSPv可能在服务器上被导出为只读。每个PV都有自己的一组访问模式,描述该特定PV的功能。
幸运的是,这次我在OpenShift文档中找到了关于这个主题的非常好的解释。我们可以在那里阅读:
声明与具有相似访问模式的卷相匹配。唯一的两个匹配条件是访问模式和大小。声明的访问模式代表一个请求。因此,您可能会被授予更多,但绝不会被授予更少。例如,如果声明请求RWO,但唯一可用的卷是NFS PV(RWO+ROX+RWX),则该声明将与NFS匹配,因为它支持RWO。
总是首先尝试直接匹配。卷的模式必须匹配或包含比您请求的模式更多的模式。大小必须大于或等于预期的大小。如果两种类型的卷(如NFS和iSCSI)具有相同的访问模式集,则它们中的任何一种都可以用这些模式匹配声明。卷类型之间没有排序,也无法选择一种类型而不是另一种类型。
具有相同模式的所有卷被分组,然后按大小从小到大排序。绑定器获取具有匹配模式的组,并按大小顺序迭代每个组,直到有一个大小匹配。

现在可能是最重要的部分:
**卷的AccessModes是卷功能的描述符。它们不是强制约束。**存储提供商负责无效使用资源导致的运行时错误。

我强调了这一部分,因为AccessModes很容易被误解。让我们看看这个例子:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: exmaple-pvc-2
spec:
  accessModes:
  - ReadOnlyMany
  storageClassName: standard
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi

我们在PersistentVolumeClaim定义中只指定了ReadOnlyMany访问模式,但这并不意味着它不能在我们的存储提供商支持的其他accessModes中使用。重要的是要理解,我们不能在这里对Pods如何使用所请求的存储设置任何限制。如果我们的存储提供商隐藏在我们的standard存储类后面,也支持ReadWriteOnce,它也将可供使用。

回答你的问题

为什么允许这样做?在这种情况下卷的实际行为是什么?只读?读和写?
它根本没有定义卷的行为。卷将根据其能力(我们没有定义它们,它们是预先强加的,是存储规范的一部分)来行为。换句话说,我们将能够以所有可能的方式在Pods中使用它,其中允许使用它。
假设我们的standard存储预配器,在GKE的情况下恰好是Google Compute Engine Persistent Disk

$ kubectl get storageclass
NAME                 PROVISIONER            AGE
standard (default)   kubernetes.io/gce-pd   10d

目前支持两个AccessModes

  • ReadWriteOnce
  • ReadOnlyMany

因此,我们可以使用所有这些,无论我们在声明中指定了什么,例如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: debian
  template:
    metadata:
      labels:
        app: debian
    spec:
      containers:
      - name: debian
        image: debian
        command: ['sh', '-c', 'sleep 3600']
        volumeMounts:
         - mountPath: "/mnt"
           name: my-volume
           readOnly: true
      volumes:
      - name: my-volume
        persistentVolumeClaim:
          claimName: example-pvc-2
      initContainers:
      - name: init-myservice
        image: busybox
        command: ['sh', '-c', 'echo "Content of my file" > /mnt/my_file']
        volumeMounts:
         - mountPath: "/mnt"
           name: my-volume

在上面的例子中两种功能都被使用。首先,我们的卷被init containerrw模式挂载,init container保存了一些文件,之后它被挂载到main container作为只读文件系统。即使我们在PersistentVolumeClaim中只指定了一种访问模式,我们仍然能够做到这一点:

spec:
  accessModes:
  - ReadOnlyMany

回到你在标题中提出的问题:
为什么可以在一个永久卷上设置多个accessMode?

**答案是:**您根本无法设置它们,因为它们已由存储提供商设置,您只能通过这种方式请求所需的存储、存储必须满足的要求,其中一个要求是存储支持的访问模式。

基本上通过键入:

spec:
  accessModes:
    - ReadOnlyMany
    - ReadWriteOnce

在我们PersistentVolulmeClaim定义中,我们说:

  • “嘿!存储提供商!给予我一个支持这组accessModes的卷。我不在乎它是否支持任何其他卷,如ReadWriteMany,因为我不需要它们。给我一个符合我要求的卷!"*

我相信不需要进一步解释为什么这里使用 an array

osh3o9ms

osh3o9ms2#

一个持久卷可以由不同节点上的多个Pod同时挂载。一个Pod一次只能挂载一种访问模式的持久卷,其他Pod可以挂载同一个访问模式不同的持久卷。但一个Pod只能挂载一种访问模式的持久卷。
对于那些不理解这个问题的人,请参考以下文档:持久卷访问模式

相关问题