마운트는 됐는데 파드 안에서 Permission denied 가 나거나 디렉터리 내용이 보이지 않는 경우다. Kubernetes 는 볼륨의 소유권을 임의로 바꾸지 않고, 컨테이너 프로세스는 이미지에 정의된 UID 로 돈다. 스토리지에 기록된 UID·GID 와 컨테이너의 UID·GID 가 다르면 그대로 막힌다.
파드에 fsGroup 을 주면 kubelet 이 볼륨의 그룹 소유권을 그 GID 로 바꾸고 g+rwx 를 준다. 컨테이너 프로세스에는 그 GID 가 보조 그룹으로 붙는다.
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: app
image: example/app:1.0
volumeMounts:
- name: data
mountPath: /data
POSIX 권한을 지원하는 볼륨에서만 동작한다. 볼륨이 크면 소유권 변경에 시간이 걸려 파드 기동이 느려지므로, 한 번만 맞추면 되는 경우 fsGroupChangePolicy: OnRootMismatch 를 함께 준다. NFS 는 kubelet 이 소유권을 바꾸지 못하는 경우가 많아 fsGroup 이 듣지 않는다.
프로세스의 UID·GID 를 지정할 뿐, 이미 존재하는 파일의 권한은 바뀌지 않는다. 볼륨이 root:root 로 되어 있으면 runAsUser: 1000 을 줘도 여전히 쓸 수 없다. 스토리지 쪽 소유권을 함께 맞춰야 의미가 있다.
가장 확실한 방법이다. root 로 도는 init 컨테이너에서 소유권을 바꾸고 본 컨테이너는 비특권으로 띄운다.
initContainers:
- name: fix-permission
image: busybox:1.36
command: ["sh", "-c", "chown -R 1000:1000 /data"]
securityContext:
runAsUser: 0
volumeMounts:
- name: data
mountPath: /data
파일 수가 많으면 오래 걸리고, root 로 도는 컨테이너를 막는 정책이 있는 클러스터에서는 쓸 수 없다.
NFS 에서 가장 흔한 착각이 "777 을 줬는데 왜 안 되느냐" 다. NFS 는 권한 비트와 함께 소유자 UID·GID 숫자를 그대로 주고받는다. 서버에서 ls 로 보면 정상인데 파드 안에서는 다음처럼 보이는 경우가 그것이다.
d--------- 1 1035 users 178 Dec 18 04:56 viya_admin
디렉터리는 UID 1035 소유인데 컨테이너는 UID 1001 로 돌고 있다. 서버에서 chmod 777 을 해도 root squash 가 걸려 있으면 그 변경이 서버에 반영되지 않거나, 반영돼도 클라이언트가 보는 소유자는 그대로다.
정리하면 순서는 이렇다.
kubectl exec -- id.0775 면 충분하다. 상위 디렉터리는 통과만 하면 되므로 0755 로 둔다.# NFS 서버
chown -R 1001:1001 /volume1/data/app
chmod -R 0775 /volume1/data/app
chmod 0755 /volume1/data # 상위는 접근만
상위 경로까지 777 로 여는 것은 해결이 아니라 문제를 가리는 것이다. 누가 썼는지 추적할 수 없게 되고, 나중에 권한을 정상화하기 어려워진다.
export 옵션도 본다. 초기화 과정에서 root 로 쓰기가 필요한 제품은 no_root_squash 가 필요하다. 반대로 보안상 root squash 를 유지해야 한다면 애플리케이션이 root 를 쓰지 않도록 구성하고 UID 를 맞추는 쪽으로 간다.
/volume1/data 10.0.0.0/16(rw,sync,no_subtree_check,no_root_squash)
공개 이미지 상당수가 특정 UID 로 실행되도록 만들어져 있다. Jupyter 계열 이미지는 jovyan(UID 1000, GID 100), Nexus 는 UID 200 처럼 정해져 있다. 호스트 디렉터리를 바인드 마운트하거나 NFS 를 붙일 때는 그 UID 에 맞춰 준다.
WARNING: no write access to /home/jovyan.
Try starting the container with group 'users' (100)
chown -R 1000:100 ./notebooks
이미지가 쓰는 UID 는 docker run --rm <이미지> id 로 확인한다.
kubectl exec -it <파드> -- id
kubectl exec -it <파드> -- ls -ln /data
kubectl exec -it <파드> -- touch /data/test
ls -ln 으로 이름 대신 숫자를 봐야 한다. 컨테이너 안에 그 UID 의 계정이 없으면 이름이 엉뚱하게 표시되기 때문이다.