When Images Fill Up Your Home Directory
한국어 원문으로 표시합니다.
한 줄 요약
rootless podman 의 이미지는 ~/.local/share/containers/storage 에 쌓인다. 홈 파티션이 작으면 graph root 를 옮기는 것이 첫 번째 운영 작업이 된다.
왜 이게 필요했나
서버 파티션 설계가 이런 경우가 흔하다.
/ 50G
/home 20G <- rootless podman 의 이미지가 여기 쌓인다
/data 2T <- 정작 큰 디스크는 여기
CUDA 이미지 하나가 8GB 다. 두어 개만 받아도 홈이 찬다. 그리고 홈이 차면 podman 뿐 아니라 그 사용자의 모든 작업이 멈춘다.
어떻게 동작하나
무엇을 옮기나
| 항목 | 기본 경로(rootless) | 옮겨야 하나 |
|---|---|---|
graphroot |
~/.local/share/containers/storage |
그렇다. 이미지·컨테이너 레이어 |
runroot |
/run/user/<uid>/containers |
아니다. tmpfs 가 맞다 |
| 볼륨 | <graphroot>/volumes |
graphroot 를 옮기면 따라간다 |
| 설정 | ~/.config/containers |
아니다. 작다 |
절차
# 1. 현재 상태 확인
podman info --format '{{.Store.GraphRoot}}'
du -sh ~/.local/share/containers/storage
# 2. 새 경로 준비 (소유자가 그 사용자여야 한다)
sudo mkdir -p /srv/podman/podster
sudo chown podster:podster /srv/podman/podster
sudo chmod 700 /srv/podman/podster
# 3. 설정 변경
# ~/.config/containers/storage.conf
# [storage]
# graphroot = "/srv/podman/podster"
# 4. 검증
podman info --format '{{.Store.GraphRoot}}'
podman images
중요한 것은 3번 이후 새 스토어가 비어 있다는 사실이다. 기존 이미지는 옛 경로에 그대로 남아 있고 podman 은 더 이상 그것을 보지 않는다. 선택지는 둘이다.
- 다시 받는다 — 인터넷이 있으면 가장 단순하다.
- 옮긴다 —
podman save로 tar 를 만들고 새 스토어에서podman load. 또는 디렉터리를 통째로 복사(cp -a또는rsync -aHAX). 통째 복사는 SELinux 라벨과 하드 링크를 보존해야 하므로 옵션을 정확히 줘야 한다.
폐쇄망이라면 후자밖에 없다. 그리고 옛 경로를 지우기 전에 반드시 새 경로에서 podman images 가 기대한 목록을 보여 주는지 확인한다.
시스템 전역으로 정하기
여러 사용자에게 같은 정책을 적용하려면 /etc/containers/storage.conf 에 쓴다. 다만 rootless 사용자의 개인 설정이 이를 덮어쓰므로, 표준화가 목적이라면 개인 설정 파일을 배포하거나 홈 스켈레톤(/etc/skel)에 넣는다.
확인 명령
podman info --format '{{.Store.GraphRoot}}'
podman info --format '{{.Store.RunRoot}}'
podman info --format '{{.Store.GraphDriverName}}'
podman system df
podman system df 는 이미지·컨테이너·볼륨이 각각 얼마나 쓰는지 보여 준다. 정리 대상을 고를 때 첫 명령이다.
루트리스에서 저장소가 말썽을 부리는 이유
루트리스 포드만의 저장소 문제는 대부분 사용자 이름공간과 파일 소유권에서 나온다. 원리를 알면 증상이 바로 읽힌다.
컨테이너 안의 UID 는 호스트에서 다른 숫자다. /etc/subuid 에 적힌 범위만큼
밀린다. 컨테이너 안의 root(0)이 호스트에서는 내 UID 이고, 컨테이너 안의 1000은
호스트에서 subuid 시작 + 999 다. 그래서 호스트에서 그 파일을 보면 소유자가
아주 큰 숫자로 보인다.
grep "^$USER:" /etc/subuid /etc/subgid
podman unshare cat /proc/self/uid_map
호스트 디렉터리를 마운트하면 권한이 안 맞는다. 내가 만든 파일은 호스트에서
내 소유인데, 컨테이너 안에서는 nobody 로 보인다. 소유권을 옮기려면 그
이름공간 안에서 chown 해야 한다.
podman unshare chown -R 1000:1000 ./data
podman unshare 없이 sudo chown 하면 호스트 기준으로만 맞고 컨테이너에서는
여전히 틀린다.
graph root 를 옮길 때 걸리는 것들. 새 위치가 다른 파일 시스템이면
overlay 를 지원하는지 먼저 본다. NFS 위에서는 overlay 가 안 되고, 그때는
vfs 로 떨어지면서 디스크 사용량이 몇 배로 늘고 느려진다.
podman info --format '{{.Store.GraphRoot}} {{.Store.GraphDriverName}}'
SELinux 가 붙은 배포판에서는 라벨을 붙여야 한다. 볼륨 마운트에 :Z 를 안
붙이면 컨테이너가 읽지 못한다. :z 는 공유, :Z 는 전용 라벨이다.
남은 것을 정기적으로 치운다. 루트리스는 사용자 홈 아래에 쌓이므로 홈 파티션이 차기 쉽다. 임시 이미지와 멈춘 컨테이너, 쓰이지 않는 볼륨을 함께 본다.
podman system df
podman system prune --volumes --filter until=168h
현장에서 만나는 모습
GPU 노드에서 특히 자주 겪는다. CUDA 베이스 이미지가 수 GB 라 몇 개만 받아도 홈이 찬다. 그래서 GPU 서버 표준 설정에는 graphroot 를 데이터 디스크로 보내는 항목이 아예 들어 있는 경우가 많다.
NFS 홈에 graphroot 를 두면 안 된다. overlay 계열 드라이버가 제대로 동작하지 않고, 파일 잠금 문제로 이상한 실패가 난다. 반드시 로컬 디스크여야 한다.
옛 경로를 안 지워 디스크를 두 배로 쓰는 경우. 옮긴 뒤 검증까지 마쳤으면 옛 경로를 정리해야 한다. 다만 podman system reset 은 현재 설정된 스토어를 지우므로 옛 경로 정리에는 쓸 수 없다.
다음 실습에서 할 것
podster 의 graph root 를 새 경로로 옮기고, 새 스토어가 비어 있음을 확인한 뒤, 이미지 아카이브를 load 해서 채우고, podman info 로 최종 검증한다.