pod 挂载 ceph pvc 更新,pod不释放,新pod无法挂载
解决pvc无法mount的问题
Normal Scheduled <unknown> default-scheduler Successfully assigned senyint/fms-server-5ccc948568-fgzbx to node4 Warning FailedAttachVolume 3m32s attachdetach-controller Multi-Attach error for volume "pvc-65a5f731-42bd-47d3-9e4b-3f3c7c0a4e43" Volume is already used by pod(s) fms-server-55bb4f6ff7-l5xk7 Warning FailedMount 89s kubelet, node4 Unable to attach or mount volumes: unmounted volumes=[senyintdatafile], unattached volumes=[logs senyintdatafile default-token-227x7]: timed out waiting for the condition
查看pvc
[root@master1 ~]# kubectl get pvc -n senyint NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE remote-fmsserver-hdd-pvc Bound pvc-65a5f731-42bd-47d3-9e4b-3f3c7c0a4e43 200Gi RWO ceph-rbd-provisioner 78m
查看pv信息
[root@master1 ~]# kubectl describe pv pvc-65a5f731-42bd-47d3-9e4b-3f3c7c0a4e43 -n senyint Name: pvc-65a5f731-42bd-47d3-9e4b-3f3c7c0a4e43 Labels: <none> Annotations: kubernetes.io/createdby: rbd-dynamic-provisioner pv.kubernetes.io/bound-by-controller: yes pv.kubernetes.io/provisioned-by: kubernetes.io/rbd Finalizers: [kubernetes.io/pv-protection] StorageClass: ceph-rbd-provisioner Status: Bound Claim: senyint/remote-fmsserver-hdd-pvc Reclaim Policy: Delete Access Modes: RWO VolumeMode: Filesystem Capacity: 200Gi Node Affinity: <none> Message: Source: Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime) CephMonitors: [192.168.200.11:6789 192.168.200.12:6789 192.168.200.13:6789] RBDImage: kubernetes-dynamic-pvc-f6d69818-7265-4038-8f7b-f2eb6d5b9b9e FSType: RBDPool: databasedata RadosUser: admin Keyring: /etc/ceph/keyring SecretRef: &SecretReference{Name:ceph-secret-admin,Namespace:,} ReadOnly: false Events: <none>
用ceph的相关命令查一下该rbd镜像现在被哪个node节点使用了:
[root@master1 ~]# rbd info databasedata/kubernetes-dynamic-pvc-f6d69818-7265-4038-8f7b-f2eb6d5b9b9e rbd image 'kubernetes-dynamic-pvc-f6d69818-7265-4038-8f7b-f2eb6d5b9b9e': size 200 GB in 51200 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.100986b8b4567 format: 2 features: layering flags:
这里将上面的block_name_prefix属性值拿出来,将rbd_data修改为rbd_header即可
根源分析
首先回顾一下k8s里volume的挂载过程:
- provision,卷分配成功,这个操作由
PVController
完成 - attach,卷挂载在对应worker node,这个操作为
AttachDetachController
完成 - mount,卷挂载为文件系统并且映射给对应Pod,这个操作为
VolumeManager
完成
k8s里volume的卸载过程跟上述场景完全相反:
- umount,卷已经和对应worker node解除映射,且已经从文件系统umount
- detach,卷已经从worker node卸载
- recycle,卷被回收
pod的迁移会导致原来的pod从其node节点删除,这时AttachDetachController
没有成为将rbd从原来的node节点detach。后面多次尝试却无法重现问题,猜测是当时由于某些原因AttachDetachController
执行detach
操作失败了,可能是强制删除pod导致的,所以删除pod时还是要慎用—force —grace-period=0
选项。
问题二
问题描述
还是上述那个场景,这次对deployment作了一次滚动更新,这时k8s会新创建一个pod,尝试挂载volume,但这次原来那个node节点上pod仍处于Running状态,因而其使用volume是正常的。
问题解决
这次很容易解决,直接删除旧的pod就可以了:
$ kubectl delete pod xxxx
根源分析
很明显,滚动更新时产生多了一个pod,为什么会这样了,我们看一下deployment里的滚动更新策略:
$ kubectl get deployment xxxx -o yaml ... deploySpec: replicas: 1 ... strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: volumes: - name: data persistentVolumeClaim: claimName: data-vol ... $ kubectl get pvc data-vol -o yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: data-vol spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi storageClassName: rbd
可以看到这里默认配置的滚动更新参数为maxSurge=1,也即允许比desired的pod数目多1个。而pvc又是ReadWriteOnce的访问模式,因此滚动更新时会产生多一个pod,而ReadWriteOnce的访问模式又不允许两个pod挂载同一个volume。 因此这里有几个的解决方案: 使用ReadWriteMany访问模式的pvc 将maxSurge设置为0,避免在更新过程中产生多余的pod 将deployment改为statefulset,statefulset对应的pod与pvc是一一绑定的,在更新过程中不会产生多余的pod
方法二:重启
使用cephfs的方式:
出现这个问题的一个重要原因是ceph-rbd只能支持单读写(RWO).而cephfs支持多读写(RWX),就不会有这个问题了.