【问题标题】:Migrate from Deployment to StatefulSet without losing persistent volume access从 Deployment 迁移到 StatefulSet 而不会丢失持久卷访问
【发布时间】:2019-12-21 13:02:01
【问题描述】:

在得知我们应该使用 StatefulSet 而不是 Deployment 以便能够将相同的持久卷附加到多个 pod,尤其是不同节点上的 pod 之后,我尝试相应地更改我们的配置。

但是,即使在卷声明中使用与以前相同的名称时,它似乎是在创建一个全新的卷而不是使用我们现有的卷,因此应用程序在以 StatefulSet 运行时无法访问现有数据.

这是我们当前Deployment 配置的音量声明部分:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitea-server-data
  labels:
    app: gitea
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

这会导致使用相同名称的声明。

这是StatefulSet的模板:

  volumeClaimTemplates:
    - metadata:
        name: gitea-server-data
        labels:
          app: gitea
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 20Gi

这会为每个 pod 生成新的声明,每个声明带有 pod 名称和 ID,例如gitea-server-data-gitea-server-0.

新的声明现在使用新卷而不是现有卷。所以我尝试明确指定现有卷,如下所示:

  volumeClaimTemplates:
    - metadata:
        name: gitea-server-data
        labels:
          app: gitea
      spec:
        accessModes:
          - ReadWriteOnce
        volumeName: pvc-c87ff507-fd77-11e8-9a7b-420101234567
        resources:
          requests:
            storage: 20Gi

但是,这会导致 pod 无法被调度并且新的声明被无限期地“等待”:

pod 有未绑定的即时 PersistentVolumeClaims(重复次数)

所以问题是:我们如何迁移卷声明以允许我们使用现有的持久卷并从新的StatefulSet 而不是当前的Deployment 访问当前的应用程序数据?

(如果相关,我们在 GKE 上使用 Kubernetes。)

【问题讨论】:

    标签: kubernetes google-kubernetes-engine


    【解决方案1】:

    好的,所以我花了很多时间尝试各种不同的配置,直到最终了解到 GCE 永久磁盘根本不支持 ReadWriteMany

    GKE docs 竭尽全力从未明确提及您实际上无法在多个 pod/节点上挂载任何普通 GKE 持久卷。

    显然,在 pod 之间获取共享文件存储的唯一方法是部署您自己的 NFS/Gluster/etc。或者掏出一大笔钱和use Google Cloud Filestore,它有一个 GKE 存储类,并且确实可以安装在多个 Pod 上。

    很遗憾,这不是该应用程序的选项,因为 Filestore 的定价从 1TB 的最低容量开始,每月高达 0.20 美元/GB,这意味着可用的最便宜选项的费用约为每月 205 美元。我们目前每月支付大约 60 美元,这将使我们的账单增加三倍以上,只是为了让滚动部署没有错误。

    【讨论】:

      【解决方案2】:

      在 StatefulSet 中,当你尝试使用 PVC 来存储数据时,实际上是使用 volumeClaimTemplates 来定义你的 PVC,例如:

      volumeClaimTemplates:
          - metadata:
              name: gitea-server-data
              labels:
                app: gitea
            spec:
              accessModes:
                - ReadWriteOnce
              resources:
                requests:
                  storage: 20Gi
      

      在这种情况下,可能会发生以下情况:

      • 如果 StatefulSet 名称是 gitea-server 并且副本是 1 那么 StatefulSet 的唯一 pod 将使用名为 gitea-server-data-gitea-server-0 的 PVC(如果集群中已经存在)或创建一个名为 gitea-server-data-gitea-server-0 的新 PVC(如果集群中不存在)。
      • 如果 StatefulSet 名称是 gitea-server 并且副本是 2 那么 StatefulSet 的两个 Pod 将分别使用名为 gitea-server-data-gitea-server-0gitea-server-data-gitea-server-1 的 PVC(如果集群中已经存在)或创建名为 gitea-server-data-gitea-server-0gitea-server-data-gitea-server-1 的新 PVC(如果集群中不存在)和以此类推。

      一般情况下,在 StatefulSet 中,生成的 PVC 名称遵循约定:

      <volumeClaimTemplates name>-<StatefulSet name>-<Pod ordinal>
      

      现在,如果您创建一个名为 gitea-server-data-gitea-server-0 的 PVC,其他内容如下所示:

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: gitea-server-data
        labels:
          app: gitea
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 20Gi
      

      那么在创建 PVC 之后,如果您尝试使用副本 1 和上面在 volumeClaimTemplates 中定义的配置创建 StatefulSet,那么 SatefulSet 将使用这个 PVC(gitea-server-data-gitea-server-0)。

      您还可以通过将字段spec.accessmodes 指定为ReadWriteMany 来将此PVC 用于其他工作负载(如部署)。

      【讨论】:

        猜你喜欢
        • 2021-11-12
        • 1970-01-01
        • 1970-01-01
        • 2016-08-04
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2021-03-06
        • 1970-01-01
        相关资源
        最近更新 更多