【问题标题】:Re-attach volume claim on deployment update在部署更新时重新附加卷声明
【发布时间】:2019-03-21 17:41:45
【问题描述】:

我正在使用持久卷声明将数据存储在容器中:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-pvc
  labels:
    type: amazonEBS
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

规范中的声明:

spec:
  volumes:
  - name: test-data-vol
    persistentVolumeClaim:
      claimName: test-pvc
  containers:
  - name: test
    image: my.docker.registry/test:1.0
    volumeMounts:
    - mountPath: /var/data
      name: test-data-vol

当我第一次启动它时,该卷已正确安装。但是当我尝试更新容器图像时:

-    image: my.docker.registry/test:1.0
+    image: my.docker.registry/test:1.1

此卷无法挂载到新 pod:

# kubectl get pods
test-7655b79cb6-cgn5r       0/1     ContainerCreating   0          3m
test-bf6498559-42vvb        1/1     Running             0          11m

# kubectl describe test-7655b79cb6-cgn5r
Events:
  Type     Reason                 Age   From                                                  Message
  ----     ------                 ----  ----                                                  -------
  Normal   Scheduled              3m5s  default-scheduler                                     Successfully assigned test-7655b79cb6-cgn5r to ip-*-*-*-*.us-west-2.compute.internal
  Warning  FailedAttachVolume     3m5s  attachdetach-controller                               Multi-Attach error for volume "pvc-2312eb4c-c270-11e8-8d4e-065333a7774e" Volume is already exclusively attached to one node and can't be attached to another
  Normal   SuccessfulMountVolume  3m4s  kubelet, ip-*-*-*-*.us-west-2.compute.internal  MountVolume.SetUp succeeded for volume "default-token-x82km"
  Warning  FailedMount            62s   kubelet, ip-*-*-*-*.us-west-2.compute.internal  Unable to mount volumes for pod "test-7655b79cb6-cgn5r(fab0862c-d1cf-11e8-8d4e-065333a7774e)": timeout expired waiting for volumes to attach/mount for pod "test-7655b79cb6-cgn5r". list of unattached/unmounted volumes=[test-data-vol]

似乎 Kubernetes 无法将此卷从一个容器重新附加到另一个容器。如何正确处理?当旧版本停止时,我需要这些卷数据供新版本部署使用。

【问题讨论】:

    标签: kubernetes persistence kubectl volumes


    【解决方案1】:

    这里的问题是 EBS 卷是 ReadWriteOnce 并且只能安装到单个 pod,因此当您进行滚动更新时,旧 pod 会保存该卷。为此,您必须使用 StatefulSet 或使用任何 ReadWriteMany PV 类型。

    Kubernetes Deployment 有时更适合用于无状态 Pod。

    您始终可以使用蛮力方法,强制删除持有该卷的 pod。确保 Reclaim Policy 设置为 Retain

    【讨论】:

    • 谢谢,我已经用StatefulSet 替换了Deployment,它解决了这个问题。
    【解决方案2】:

    根据您在问题中提供的上下文,我无法判断您的意图是运行单实例有状态应用程序还是集群有状态应用程序。

    我最近遇到了这个问题,来自this section in the docs,这是解决这个问题的方法...

    如果您运行的是单实例有状态应用:

    • 您应该缩放应用程序,也就是说,如果您使用的是 Deployment,请将 spec.replicas 的默认值保留为 1
    • 您应该指示 Kubernetes 使用滚动更新,也就是说,您应该在 Deployment 中将 spec.strategy.type 设置为 Recreate

    示例Deployment(来自docs):

    #application/mysql/mysql-deployment.yaml apiVersion: apps/v1 # 对于 1.9.0 之前的版本使用 apps/v1beta2 种类:部署 元数据: 名称:mysql 规格: 选择器: 匹配标签: 应用程序:mysql 策略: 类型:重新创建 模板: 元数据: 标签: 应用程序:mysql 规格: 容器: - 图片:mysql:5.6 名称:mysql 环境: # 在实际使用中使用secret - 名称:MYSQL_ROOT_PASSWORD 值:密码 端口: - 容器端口:3306 名称:mysql 卷装: - 名称:mysql-持久存储 挂载路径:/var/lib/mysql 卷: - 名称:mysql-持久存储 持久卷声明: 声明名称:mysql-pv-声明

    还有样本PersistentVolume & PersistentVolumeClaim(来自docs):

    #application/mysql/mysql-pv.yaml api版本:v1 种类:持久卷 元数据: 名称:mysql-pv-volume 标签: 类型:本地 规格: storageClassName:手动 容量: 存储:20Gi 访问模式: - 读写一次 主机路径: 路径:“/mnt/数据” --- api版本:v1 种类:PersistentVolumeClaim 元数据: 名称:mysql-pv-claim 规格: storageClassName:手动 访问模式: - 读写一次 资源: 要求: 存储:20Gi

    这里明显的潜在问题是滚动更新将不起作用,因为任何时候都不能有超过一个 Pod 运行。将 spec.strategy.type 设置为 Recreate 会告诉 Kubernetes 在部署新的 Pod 之前停止正在运行的 Pod,因此可能会有一些停机时间,即使很短。

    如果您需要集群状态应用程序,那么使用已经提到的StatefulSet 作为控制器类型或使用ReadWriteMany 作为存储类型可能是可行的方法。

    【讨论】:

    • 如果您想拥有一个持久卷并且不需要扩展您的应用程序,这是正确的答案。 StatefulSets 为每个副本创建一个持久化卷,它允许持久化和扩展。
    【解决方案3】:

    不确定,RollingUpdate 可能会解决问题。根据docs,由于“滚动更新”是更新容器图像的安全方式。我想,K8s 也可以处理 PV/PVC。

    【讨论】:

      猜你喜欢
      • 2018-04-27
      • 2020-05-28
      • 1970-01-01
      • 2022-01-22
      • 2022-01-23
      • 2018-09-04
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多