在部署更新时重新附加卷声明

Kir*_*ill 4 persistence volumes kubernetes kubectl

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

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-pvc
  labels:
    type: amazonEBS
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
Run Code Online (Sandbox Code Playgroud)

规范中的声明:

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
Run Code Online (Sandbox Code Playgroud)

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

-    image: my.docker.registry/test:1.0
+    image: my.docker.registry/test:1.1
Run Code Online (Sandbox Code Playgroud)

此卷无法挂载到新 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]
Run Code Online (Sandbox Code Playgroud)

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

DVN*_*VNO 12

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

我最近遇到了这个问题,从文档的这一部分来看,这是如何解决这个问题的......

如果您正在运行单实例有状态应用程序:

  • 应该缩放应用程序,也就是说,spec.replicas如果您使用的是Deployment
  • 您应该指示 Kubernetes 不要使用滚动更新,即您应该spec.strategy.typeRecreate您的Deployment

示例Deployment(来自文档):

# 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-claim

以及示例PersistentVolume& PersistentVolumeClaim(来自文档):

# 应用程序/mysql/mysql-pv.yaml

api版本:v1
种类:持久卷
元数据:
  名称:mysql-pv-volume
  标签:
    类型:本地
规格:
  存储类别名称:手册
  容量:
    存储:20Gi
  访问模式:
    - 读写一次
  主机路径:
    路径:“/mnt/数据”

---
api版本:v1
种类:持久卷声明
元数据:
  名称:mysql-pv-claim
规格:
  存储类别名称:手册
  访问模式:
    - 读写一次
  资源:
    要求:
      存储:20Gi

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

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

  • 如果您想要拥有单个持久卷并且不需要扩展您的应用程序,那么这是正确的答案。StatefulSets为每个副本创建一个持久卷,它允许持久性和扩展。 (2认同)

Ric*_*ico 5

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

一个Kubernetes部署有时更好地使用无状态的豆荚。

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

  • 谢谢,我已经用 `StatefulSet` 替换了 `Deployment`,它解决了这个问题。 (2认同)