Postgres initdb 실패 — 볼륨 루트의 lost+found
쿠버네티스에 Postgres 를 올리면서 데이터 디렉토리에 EBS 볼륨을 PVC 로 붙였는데,
파드가 뜨자마자 CrashLoopBackOff 로 돌기 시작했습니다. 이미지를 의심하고
권한을 의심했지만 둘 다 아니었습니다.
증상 — “디렉토리가 안 비었다”며 멈추는 initdb
로그는 명확했습니다.
initdb: error: directory "/var/lib/postgresql/data" exists but is not empty
It contains a lost+found directory, perhaps due to it being a mount point.
initdb 는 데이터 디렉토리가 완전히 비어 있어야 초기화를 시작합니다.
그런데 그 디렉토리가 안 비었다고 합니다. 방금 만든 빈 볼륨입니다.
원인 — 데이터 디렉토리에 직접 마운트한 EBS
EBS 볼륨을 /var/lib/postgresql/data 에 바로 마운트한 게 문제였습니다.
ext4 로 포맷된 볼륨을 마운트하면, 파일시스템이 최상위에 lost+found 디렉토리를
자동으로 만듭니다. fsck 가 복구한 조각을 넣어두는 표준 디렉토리라, 사용자가 만든 게
아니어도 항상 있습니다. initdb 입장에선 데이터 디렉토리 안에 정체불명의
디렉토리가 하나 있는 거라, “안 비었다” 며 거부합니다.
Postgres 만의 얘기도 아니라서, 볼륨 루트에 데이터 디렉토리를 그대로 얹는 DB 는 다 같은 데서 걸립니다.
해결 — 마운트 지점 아래 하위 디렉토리를 데이터 디렉토리로
마운트 지점 자체를 데이터 디렉토리로 쓰지 말고, 그 아래 하위 디렉토리를
쓰면 됩니다. Postgres 는 PGDATA 로 지정합니다.
PGDATA=/var/lib/postgresql/data/pgdata
lost+found 는 마운트 지점(.../data)에 생기고, initdb 는 그 아래
pgdata 를 보는데 거긴 비어 있으니 통과합니다. 마운트는 루트에, 데이터는 한
칸 아래. 이 한 칸이 핵심입니다.
옛 ReplicaSet이 파드를 계속 재생성
고치고 나서도 옛날 스펙의 파드가 자꾸 다시 떴습니다. 이전 ReplicaSet 이 남아 파드를 계속 재생성하고 있었습니다. 루프를 끊으려면 그 ReplicaSet 을 직접 0 으로 내려야 했습니다.
kubectl scale rs <old-rs> --replicas=0
데이터 디렉토리는 마운트 지점 한 칸 아래
“빈 볼륨인데 안 비었다” 는 에러를 보면 lost+found 를 의심합니다. ext4·xfs
같은 파일시스템이 마운트 지점에 자동으로 만드는 디렉토리라, 마운트 지점을
그대로 데이터 디렉토리로 쓰는 순간 “비어 있어야 한다” 는 검사와 부딪힙니다.
DB 를 볼륨에 얹을 땐 마운트 지점 한 칸 아래를 데이터 디렉토리로 두는 게
안전합니다.
댓글 0