Rook-Ceph 의 CephFS StorageClass 로 만든 PVC 가 Pending 에서 움직이지 않는 상황을 위에서 아래로 갈라낸 기록이다. PVC 이벤트만 보면 언제나 ExternalProvisioning: waiting for a volume to be created 하나뿐이라 원인이 드러나지 않으므로, StorageClass → CSI 프로비저너 → CephFilesystem → MDS → OSD 순으로 내려가면서 확인해야 한다.
StorageClass 가 가리키는 대상이 실재하는지부터 본다. fsName 과 pool 이 실제 CephFilesystem 및 pool 이름과 정확히 같아야 한다.
kubectl describe sc <STORAGE_CLASS>
kubectl -n rook-ceph get cephfilesystem
CephFilesystem 의 PHASE 가 Ready 여야 한다. Progressing 에서 오래 머무르면 MDS 가 active 로 못 올라온 것이다.
CSI 프로비저너 파드를 찾는다. Rook 버전에 따라 파드 이름이 달라서 레이블 셀렉터가 맞지 않는 경우가 흔하다. -l app=csi-cephfsplugin-provisioner 로 아무것도 안 잡히면 이름으로 직접 찾는다.
kubectl -n rook-ceph get pod | grep -i cephfs
kubectl -n rook-ceph logs <CSI_CTRLPLUGIN_POD> -c csi-provisioner --tail=200
여기 로그가 실제 실패 사유를 담고 있다. 대부분 이 한 줄에서 끝난다.
CephFS CSI 드라이버는 각 PVC 를 파일시스템 안의 subvolume 으로 만들고, 그 subvolume 들을 csi 라는 subvolumegroup 아래에 모은다. 이 그룹이 없으면 프로비저닝이 진행되지 않는다. Rook 이 자동으로 만들지만, 파일시스템을 손으로 만들었거나 지웠다 다시 만든 뒤에는 빠져 있을 수 있다.
Ceph CLI 는 호스트에 없다. 반드시 toolbox 파드를 거친다.
kubectl -n rook-ceph get pod | grep tools
kubectl -n rook-ceph exec -it <TOOLS_POD> -- ceph fs subvolumegroup ls <FS_NAME>
출력이 비어 있으면 만든다.
kubectl -n rook-ceph exec -it <TOOLS_POD> -- ceph fs subvolumegroup create <FS_NAME> csi
mgr 파드 안에서 ceph 를 직접 실행하면 인증 방식이 맞지 않아 다음으로 막힌다. 이때도 toolbox 를 쓴다.
monclient(hunting): handle_auth_bad_method server allowed_methods [2] but i only support [2,1]
toolbox 파드를 한 번 거치면 평소 쓰던 명령을 그대로 쓸 수 있다.
TOOLS=$(kubectl -n rook-ceph get pod -l app=rook-ceph-tools -o jsonpath='{.items[0].metadata.name}')
kubectl -n rook-ceph exec "$TOOLS" -- ceph -s
kubectl -n rook-ceph exec "$TOOLS" -- ceph health detail
kubectl -n rook-ceph exec "$TOOLS" -- ceph mds stat
kubectl -n rook-ceph exec "$TOOLS" -- ceph fs ls
kubectl -n rook-ceph exec "$TOOLS" -- ceph osd stat
kubectl -n rook-ceph exec "$TOOLS" -- ceph osd pool ls
kubectl -n rook-ceph exec "$TOOLS" -- ceph osd df
Rook CR 은 사라졌는데 Ceph 안에는 파일시스템이 남아 있는 상태가 생긴다. kubectl delete cephfilesystem 이 NotFound 를 내는데 ceph fs ls 에는 보이는 경우다. ceph mds stat 에 1 failed 같은 표시가 남아 클러스터 전체가 HEALTH_ERR 이 되기도 한다.
Rook CR 을 먼저 지우고, 그다음 Ceph 쪽을 지우는 순서를 지킨다. 반대로 하면 Rook 이 다시 만들어 놓는다.
kubectl -n rook-ceph delete cephfilesystem <FS_NAME>
kubectl -n rook-ceph exec "$TOOLS" -- ceph fs fail <FS_NAME>
kubectl -n rook-ceph exec "$TOOLS" -- ceph fs rm <FS_NAME> --yes-i-really-mean-it
ceph fs rm 은 pool 을 지우지 않는다. 남은 metadata pool 과 data pool 을 따로 지운다.
kubectl -n rook-ceph exec "$TOOLS" -- ceph osd pool ls
kubectl -n rook-ceph exec "$TOOLS" -- \
ceph osd pool delete <POOL> <POOL> --yes-i-really-really-mean-it
pool 삭제가 거부되면 mon 의 mon_allow_pool_delete 가 꺼져 있는 것이다. Rook 이 배포한 클러스터에서는 CephCluster CR 의 cephConfig 로 켠다.
파일시스템을 다시 만든 뒤에는 csi subvolumegroup 을 잊지 말고 만들고, StorageClass 의 fsName 과 pool 을 새 이름으로 맞춘다. 이름이 바뀌면 기존 StorageClass 는 그대로 두면 안 된다 — StorageClass 는 불변 필드가 많아 수정이 아니라 삭제 후 재생성이다.
위 정리를 모두 마치고 cephfs-main 을 새로 만들어 MDS 가 up:active 로 올라온 뒤에도 PVC 는 Pending 에 머물렀다. 이 시점의 관측은 다음과 같았다.
CSI 컨트롤러와 노드 플러그인은 모두 Running 이었고 CephFS 자체는 논리적으로 정상이었다. 그러나 ceph fs subvolumegroup ls 와 ceph osd perf 같은 명령이 응답 없이 멈췄고, ceph health detail 에는 BLUESTORE_SLOW_OP_ALERT 가 특정 OSD 에 대해 떠 있었다. 메타데이터 연산이 블록되는 바람에 CSI 의 subvolume 생성 요청이 타임아웃까지 대기하는 형태였다.
즉 Kubernetes 나 CSI 가 아니라 스토리지 백엔드의 IO 지연이 원인으로 지목된 채 대화가 끝났다. 다음에 확인해야 할 것은 ceph osd df 의 편중, 해당 OSD 가 올라간 노드의 디스크 지연과 IO 대기, 그리고 OSD 재시작 또는 리밸런싱으로 증상이 사라지는지 여부다. 이 인과 관계는 직접 확인되지 않았다 (확인 필요).