解決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),就不會有這個問題了.