重新附加有关部署更新的批量声明

时间:2018-10-17 06:01:19

标签: kubernetes persistence kubectl volumes

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

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似乎无法将该卷从一个容器重新连接到另一个容器。如何正确处理?当旧版本停止时,我需要此卷上的数据以供新版本的部署使用。

3 个答案:

答案 0 :(得分:1)

这里的问题是EBS卷是ReadWriteOnce,只能安装到单个Pod,因此,当您滚动更新时,旧Pod会容纳该卷。为此,您要么必须使用StatefulSet,要么可以使用任何ReadWriteMany PV类型。

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

您始终可以使用蛮力方法,这种方法会强制删除保存该卷的容器。确保将Reclaim Policy设置为Retain

答案 1 :(得分:0)

不确定,RollingUpdate是否可以解决问题。根据{{​​3}},由于“滚动更新”是更新容器图像的安全方法。我想,K8也可以处理PV / PVC。

答案 2 :(得分:0)

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

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

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

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

示例Deployment(来自docs):

# application/mysql/mysql-deployment.yaml

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

示例PersistentVolumePersistentVolumeClaim(来自docs):

# application/mysql/mysql-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

这里显而易见的基本问题是,滚动更新将不起作用,因为在任何时候最多只能运行一个pod。将spec.strategy.type设置为Recreate会告诉Kubernetes在部署新Pod之前先停止正在运行的Pod,因此即使有最少的停机时间,也可能会有一些停机时间。

如果您需要群集的有状态应用程序,则可以使用已经提到的StatefulSet作为控制器类型或将ReadWriteMany作为存储类型。