在部署更新时重新附加卷声明
Re-attach volume claim on deployment update
我正在使用持久卷声明在容器中存储数据:
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 似乎无法将此卷从一个容器重新附加到另一个容器。如何正确处理?当旧版本停止时,我需要卷上的这些数据供新版本的部署使用。
不确定,RollingUpdate
可能会解决问题。根据 docs,"Rolling Update" 是更新容器镜像的安全方式。我假设,K8s 也可以处理 PV/PVC。
这里的问题是 EBS 卷是 ReadWriteOnce
并且只能安装到单个 pod,因此当您进行滚动更新时,旧 pod 会保留该卷。为此,您要么必须使用 StatefulSet
or you can use any of the ReadWriteMany
PV 类型。
A Kubernetes Deployment 有时更好地用于无状态 pods。
您始终可以采用蛮力方法,强制删除持有该卷的 pod。确保 Reclaim Policy
设置为 Retain
。
根据您在问题中提供的上下文,我无法判断您的意图是运行一个单实例有状态应用程序,还是集群 有状态应用程序。
我最近 运行 遇到了这个问题,从 this section in the docs 开始,这里是解决这个问题的方法...
如果您运行正在使用单个实例有状态应用程序:
- 您应该不缩放应用程序,也就是说,如果您使用
Deployment
[=,请将 spec.replicas
的默认值保留为 1 54=]
- 您应该指示 Kubernetes 不 使用滚动更新,也就是说,您应该在
Deployment
[ 中将 spec.strategy.type
设置为 Recreate
样本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
和示例 PersistentVolume
& PersistentVolumeClaim
(来自 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 运行ning。将 spec.strategy.type
设置为 Recreate
告诉 Kubernetes 在部署新 pod 之前停止 运行ning pod,因此可能会有一些停机时间,即使是最小的。
如果您需要集群有状态应用程序,那么使用已经提到的 StatefulSet
作为控制器类型或 ReadWriteMany
作为存储类型可能是要走的路。
我正在使用持久卷声明在容器中存储数据:
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 似乎无法将此卷从一个容器重新附加到另一个容器。如何正确处理?当旧版本停止时,我需要卷上的这些数据供新版本的部署使用。
不确定,RollingUpdate
可能会解决问题。根据 docs,"Rolling Update" 是更新容器镜像的安全方式。我假设,K8s 也可以处理 PV/PVC。
这里的问题是 EBS 卷是 ReadWriteOnce
并且只能安装到单个 pod,因此当您进行滚动更新时,旧 pod 会保留该卷。为此,您要么必须使用 StatefulSet
or you can use any of the ReadWriteMany
PV 类型。
A Kubernetes Deployment 有时更好地用于无状态 pods。
您始终可以采用蛮力方法,强制删除持有该卷的 pod。确保 Reclaim Policy
设置为 Retain
。
根据您在问题中提供的上下文,我无法判断您的意图是运行一个单实例有状态应用程序,还是集群 有状态应用程序。
我最近 运行 遇到了这个问题,从 this section in the docs 开始,这里是解决这个问题的方法...
如果您运行正在使用单个实例有状态应用程序:
- 您应该不缩放应用程序,也就是说,如果您使用
Deployment
[=,请将spec.replicas
的默认值保留为 1 54=] - 您应该指示 Kubernetes 不 使用滚动更新,也就是说,您应该在
Deployment
[ 中将spec.strategy.type
设置为Recreate
样本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
和示例 PersistentVolume
& PersistentVolumeClaim
(来自 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 运行ning。将 spec.strategy.type
设置为 Recreate
告诉 Kubernetes 在部署新 pod 之前停止 运行ning pod,因此可能会有一些停机时间,即使是最小的。
如果您需要集群有状态应用程序,那么使用已经提到的 StatefulSet
作为控制器类型或 ReadWriteMany
作为存储类型可能是要走的路。