IT/Kubernets

Pod 시작이 느릴 때, fsGroupChangePolicy 한 줄만 바꿔보자

gfrog 2026. 5. 19. 06:13
반응형

증상

이런 경험 다들 한 번쯤 있을 거다. Pod가 Running까지 가는 데 2-3분, 심하면 5분 넘게 걸린다. 이벤트 찍어봐도 별다른 에러 없고, ImagePull도 끝났고, PV Attach/Mount도 정상 완료. 그런데 컨테이너가 시작을 안 한다. kubectl describe pod 해보면 그냥 조용히 멈춰 있다.

이때 kubelet 로그를 보면 이런 라인이 줄줄이 찍히고 있을 가능성이 높다.

SetVolumeOwnership ... took 142.3s

범인은 fsGroup이다. SecurityContext에 fsGroup: 1000 같은 거 설정해두면, kubelet이 PV를 마운트할 때 그 안의 모든 파일을 chown/chmod로 훑는다. 파일이 10만 개면 10만 번. 그게 NFS나 EFS 같은 네트워크 스토리지면 한 번 당 RTT가 추가되니까 분 단위로 늘어진다.

해결: OnRootMismatch

K8s 1.23부터 stable인 fsGroupChangePolicy: OnRootMismatch를 켜면, 루트 디렉토리의 권한만 확인하고 일치하면 재귀를 건너뛴다. 1.23부터 stable이니까 사실상 모든 현역 클러스터에서 쓸 수 있다.

spec:
  securityContext:
    fsGroup: 1000
    fsGroupChangePolicy: OnRootMismatch

진짜 이게 다다. 같은 fsGroup으로 재마운트되는 케이스(StatefulSet 재시작 등)에서는 루트 권한이 이미 맞으니까 통째로 스킵된다. 우리 팀 케이스에서는 PostgreSQL StatefulSet pod 시작 시간이 3분 → 8초로 줄었다. 데이터 디렉토리에 WAL이랑 파일이 많아서 그동안 그게 다 chown 비용이었던 거다.

그래도 안 빨라지면

OnRootMismatch로 바꿔도 첫 마운트는 어차피 전수 검사를 한 번 거친다. 그게 부담이면 아예 fsGroup 자체를 빼고 이미지 빌드 시점에 권한을 박아두거나, init container에서 chown -R을 백그라운드로 돌리는 우회도 가능. 그리고 CSI 드라이버에 따라 OnRootMismatch가 안 먹는 케이스가 있다 — ceph-csi rbd처럼 setgid 비트 관련 이슈가 보고된 적도 있으니, 본인 환경에서 한 번은 stopwatch 들고 측정해보는 게 안전하다.

kubectl get pod <pod> -o jsonpath='{.status.startTime}'
# vs
kubectl get pod <pod> -o jsonpath='{.status.containerStatuses[0].state.running.startedAt}'

이 둘의 차이가 fsGroup chown에 쓴 시간이라고 보면 대략 맞다.

별거 아닌 한 줄인데, 모르고 있으면 그냥 "스토리지가 느리네" 하고 넘어가기 쉽다. 혹시 비슷한 증상 있으신 분들은 한 번 확인해보시길.

반응형