Kubernetes:如何将自动缩放 pod 的 accessModes 更改为 ReadOnlyMany?

Posted

技术标签:

【中文标题】Kubernetes:如何将自动缩放 pod 的 accessModes 更改为 ReadOnlyMany?【英文标题】:Kubernetes: how to change accessModes of auto scaled pod to ReadOnlyMany? 【发布时间】:2017-11-09 23:57:36 【问题描述】:

我正在尝试 HPA:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

PV:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: api-orientdb-pv
  labels:
    app: api-orientdb
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: api-orientdb- .Values.cluster.name | default "testing" 
    fsType: ext4

PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: api-orientdb-pv-claim
  labels:
    app: api
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      app: api-orientdb
  storageClassName: ""

HPA:

Name:                           api-orientdb-deployment
Namespace:                      default
Labels:                         <none>
Annotations:                        <none>
CreationTimestamp:                  Thu, 08 Jun 2017 10:37:06 +0700
Reference:                      Deployment/api-orientdb-deployment
Metrics:                        ( current / target )
  resource cpu on pods  (as a percentage of request):   17% (8m) / 10%
Min replicas:                       1
Max replicas:                       2
Events:                         <none>

并且已经创建了新的 pod:

NAME                                       READY     STATUS    RESTARTS   AGE
api-orientdb-deployment-2506639415-n8nbt   1/1       Running   0          7h
api-orientdb-deployment-2506639415-x8nvm   1/1       Running   0          6h

如您所见,我使用的是gcePersistentDisk,它不支持ReadWriteMany 访问模式。

新创建的 pod 也将卷挂载为rw 模式:

Name:        api-orientdb-deployment-2506639415-x8nvm
Containers:
    Mounts:
      /orientdb/databases from api-orientdb-persistent-storage (rw)
Volumes:
  api-orientdb-persistent-storage:
    Type:   PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  api-orientdb-pv-claim
    ReadOnly:   false

问题:在这种情况下它是如何工作的?有没有办法将主要 pod (n8nbt) 配置为使用具有ReadWriteOnce 访问模式的 PV,而所有其他缩放的 pod (x8nvm) 应该是 ReadOnlyMany?如何自动完成?

我能想到的唯一方法是创建另一个 PVC 挂载同一个磁盘但使用不同的accessModes,但接下来的问题是:如何配置新扩展的 pod 以使用该 PVC?


2017 年 6 月 9 日星期五 11:29:34 ICT

我发现了一些东西:没有什么可以确保新扩展的 pod 将在与第一个 pod 相同的节点上运行。所以,如果 volume 插件不支持ReadWriteMany 并且缩放的 Pod 在另一个节点上运行,它将无法挂载:

无法在节点上附加卷“api-orientdb-pv” “gke-testing-default-pool-7711f782-4p6f”与:googleapi:错误 400: 磁盘资源 'projects/xx/zones/us-central1-a/disks/api-orientdb-testing' 是 已经被使用 'projects/xx/zones/us-central1-a/instances/gke-testing-default-pool-7711f782-h7xv'

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes

重要!一个卷一次只能使用一种访问模式安装,即使它支持多种访问模式。例如,单个节点可以将 GCEPersistentDisk 挂载为 ReadWriteOnce,也可以将多个节点挂载为 ReadOnlyMany,但不能同时挂载。

如果是这样,确保HPA工作的唯一方法是ReadWriteMany访问模式必须被卷插件支持?


2017 年 6 月 9 日星期五 14:28:30 ICT

如果您只希望一个 Pod 能够写入,则创建两个 Deployment。一个带有副本:1,另一个带有自动缩放器(并且其中包含 readOnly: true)

好的。

请注意,如果任何 Pod 正在读写访问 GCE PD,则该 GCE PD 只能由单个节点挂载。

那么我必须使用label selectors 来确保所有 pod 最终都在同一个节点上,对吧?

你的问题我不清楚

让我解释一下:在自动缩放的情况下,假设通过使用标签选择器,我可以确保新缩放的 pod 最终在同一个节点上,但是由于卷安装为rw,它是否会破坏 GCE PD我们有 2 个 pod 将一个卷挂载为 rw

首先,一般来说,如果您有一个具有副本的部署:1 您不会同时运行 2 个 Pod(大部分时间!!)

我知道。

另一方面,如果 PVC 指定 ReadWriteOnce,那么在第一个 Pod 被调度后,任何其他 Pod 都需要在同一个节点上调度或根本不被调度(最常见的情况是:节点)

如果是 HPA,则不会。请参阅我上面的更新了解更多详情。

如果出于任何原因,您确实有 2 个 Pod 访问同一个挂载 readWrite,那么它将完全取决于应用程序会发生什么,而不是特定于 kubernetes

让我困惑的主要是:

ReadWriteOnce – 卷可以被单个节点以读写方式挂载

好的,节点,而不是 pod。但是在自动缩放的情况下,如果 2 个 pod 在同一个节点上运行,并且都将卷挂载为rw,那么 GCE PD 是否支持它?如果是这样,它是如何工作的?

【问题讨论】:

【参考方案1】:

它按预期工作。 ReadWriteOnce 中的 Once 是指可以使用 PVC 的 Node 的数量,而不是 Pod 的数量(HPA 或无 HPA)。

如果您只希望一个 Pod 能够写入,则创建两个 Deployment。一个带有replicas: 1,另一个带有自动缩放器(其中有readOnly: true)。请注意,如果任何 Pod 正在读写 GCE PD,则只能由单个节点挂载。

【讨论】:

那么,如果 2 个客户端同时请求写入 db 会发生什么?一个必须等​​待另一个先完成? 你的问题我不清楚,但我还是尽量回复。首先,一般来说,如果您有一个带有replicas: 1 的部署,您将不会同时运行 2 个 Pod(大部分时间!!)。另一方面,如果 PVC 指定 ReadWriteOnce,那么在第一个 Pod 被调度之后,任何其他 Pod 都需要在同一个节点上调度或根本不被调度(最常见的情况:节点上没有足够的资源)。如果出于任何原因,您确实有 2 个 Pod 访问同一个挂载 readWrite,那么它将完全取决于应用程序会发生什么,而不是特定于 kubernetes 是的,现在清楚多了。在这种情况下,GCE PD 是连接到您的 GCE 实例(Kubernetes 节点)的块设备。我假设您正在使用 ext4 或类似的东西。您不能多次挂载 ext4 readWrite,因此第一个期望是,如果多个 Pod 设法同时挂载它,那将是灾难性的。 但是 Kubernetes 只挂载一次 GCE PD。在同一节点上运行的所有 Pod 都使用 bind 挂载来“镜像”该单个挂载点。现在这从文件系统的角度解决了多访问问题,但是应用程序如何处理这是另一个问题 沙盒一次只能定位(附加)到一个游乐场(节点)(使其成为 ReadWriteOnce)。一个沙盒支持多个孩子(Pod/容器)同时在其中玩耍,但孩子们是否互相容忍则是另一回事。例如,他们可能想玩同一粒沙子。好孩子可以共享同一个沙箱,甚至可以合作(锁定)【参考方案2】:

我认为我们可以使用 StatefulSet 以便每个副本都有自己的 PV。

https://cloud.google.com/kubernetes-engine/docs/concepts/persistent-volumes#deployments_vs_statefulsets

不建议使用 ReadWriteOnce 卷进行具有一个副本的部署。这是因为默认部署策略将在重新创建第一个 Pod 之前创建第二个 Pod。由于 ReadWriteOnce 卷已在使用中,第二个 Pod 无法启动,部署可能会陷入死锁,并且由于第二个 Pod 尚未启动,因此不会删除第一个 Pod。相反,请使用带有 ReadWriteOnce 卷的 StatefulSet。

StatefulSets 是部署有状态应用程序的推荐方法,每个副本需要一个唯一的卷。通过将 StatefulSets 与 Persistent Volume Claim 模板一起使用,您可以让应用程序自动扩展,并使用与每个副本 Pod 关联的唯一 Persistent Volume Claims。

【讨论】:

以上是关于Kubernetes:如何将自动缩放 pod 的 accessModes 更改为 ReadOnlyMany?的主要内容,如果未能解决你的问题,请参考以下文章

同时自动缩放卷和 Pod (Kubernetes)

在 Kubernetes 中,如何根据队列的大小进行自动缩放?

如何在 GKE 自动驾驶仪中基于自定义指标实现水平自动缩放

[kubernetes] HPA实现自动水平伸缩POD

Pub Sub 数据关联与 Pod 自动缩放

如何根据 EKS 中的平均内存使用量自动扩展 Kubernetes Pod?