イメージがホームを埋めるとき
一言でいうと
rootless podmanのイメージは、~/.local/share/containers/storageに積まれます。ホームパーティションが小さければ、graph rootを移すことが最初の運用作業になります。
なぜ必要なのか
サーバーのパーティション設計が、こうなっていることはよくあります。
/ 50G
/home 20G <- rootless podman 의 이미지가 여기 쌓인다
/data 2T <- 정작 큰 디스크는 여기
CUDAイメージは、1つで8GBあります。2つ3つ取得しただけで、ホームが埋まります。そして、ホームが埋まると、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はもうそれを見ません。選択肢は2つです。
- もう一度取得します: インターネットがあれば、最も単純です。
- 移します:
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は、イメージ・コンテナ・ボリュームが、それぞれどれだけ使っているかを見せてくれます。整理する対象を選ぶときの、最初のコマンドです。
rootlessでストレージが問題を起こす理由
rootless podman固有のストレージの問題は、大半がユーザー名前空間とファイルの所有権から生じます。原理を知れば、症状がすぐ読み取れます。
コンテナ内の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は専用のラベルです。
残ったものを、定期的に片付けます。rootlessはユーザーのホームの下に積まれるので、ホームパーティションが埋まりやすいです。一時的なイメージと、停止したコンテナ、使われていないボリュームを、一緒に見ます。
podman system df
podman system prune --volumes --filter until=168h
現場での姿
GPUノードで特によく経験します。CUDAのベースイメージが数GBあるので、いくつか取得しただけで、ホームが埋まります。そのため、GPUサーバーの標準設定には、graphrootをデータディスクへ送る項目が、最初から入っていることが多いです。
NFSホームにgraphrootを置いてはいけません。overlay系のドライバーが正しく動作せず、ファイルロックの問題で、おかしな失敗が起きます。必ずローカルディスクである必要があります。
古いパスを削除せず、ディスクを2倍使ってしまう場合があります。移したあと、検証まで終えたら、古いパスを片付ける必要があります。ただし、podman system resetは、現在設定されているストアを削除するので、古いパスの整理には使えません。
次のラボですること
podsterのgraph rootを新しいパスに移し、新しいストアが空であることを確認したあと、イメージアーカイブをloadして埋め、podman infoで最終検証します。