Namespace と cgroup
Linux コンテナの基盤技術で、プロセスの隔離とリソース制限を実現するカーネル機能
Namespace と cgroup とは
Namespace と cgroup は、Linux カーネルの機能で、Docker や Kubernetes のコンテナ技術の基盤である。Namespace がプロセスの隔離 (何が見えるか) を、cgroup がリソースの制限 (どれだけ使えるか) を担当する。
2 つは独立した仕組みで、片方だけでは コンテナ にならない。Namespace だけを切ったプロセスは、自分専用のプロセス表やネットワークを持ちながらホストの CPU とメモリを無制限に食える。cgroup だけを付けたプロセスは、使用量は抑えられてもホストの全プロセスが見え、同じファイルシステムを触れる。コンテナランタイムは両方を同時に設定し、そのうえでカーネル自体はホストと共有したままにする。このカーネル共有が、起動の速さと、カーネルの脆弱性が隔離を突き抜けるリスクの両方の理由になっている。
Namespace (隔離)
Namespace は種類ごとに独立していて、必要なものだけを個別に切れる。2026 年 8 月時点で 8 種類あり、最後に追加された Time namespace は Linux 5.6 からである。コンテナランタイムは通常この多くをまとめて切るが、--net=host のようにあえて 1 種類だけホストと共有する運用もある。
| Namespace | 隔離対象 | 効果 |
|---|---|---|
| PID | プロセス ID | コンテナ内のプロセスが PID 1 から始まる |
| Network | ネットワーク | コンテナごとに独立した IP アドレス |
| Mount | ファイルシステム | コンテナごとに独立したファイルシステム |
| UTS | ホスト名 | コンテナごとに独立したホスト名 |
| IPC | プロセス間通信 | コンテナ間の IPC を隔離 |
| User | ユーザー ID | コンテナ内の root がホストの非 root |
| Cgroup | cgroup 階層のルート | コンテナ内から見える cgroup のルートを付け替える |
| Time | 起動時刻・単調時刻 | CLOCK_MONOTONIC と CLOCK_BOOTTIME をコンテナごとにずらせる |
ホスト OS:
PID 1 (systemd)
PID 100 (dockerd)
PID 200 (コンテナ A のプロセス) ← コンテナ内では PID 1 に見える
PID 300 (コンテナ B のプロセス) ← コンテナ内では PID 1 に見える
PID namespace の PID 1 には特別扱いがある。同じ namespace の他のプロセスから送った signal は、PID 1 側でハンドラーを登録しているものしか届かない。祖先の namespace から送る場合も同じ制限がかかり、例外は SIGKILL と SIGSTOP だけである。この仕様のため、SIGTERM を自分で処理しないプロセスをコンテナのメインプロセスに置くと、docker stop や Pod 削除で送られる SIGTERM が黙って捨てられ、猶予時間が切れてから SIGKILL で落ちる。graceful shutdown が効かない典型的な原因がこれで、シェルスクリプト経由で起動して PID 1 がシェルになっている構成で起きやすい。逆に PID 1 が終了すると、カーネルはその namespace の全プロセスを SIGKILL で終了させる。
User namespace はコンテナ内の root をホストの非 root へ写す仕組みだが、有効かどうかは実行環境次第である。Docker Engine では daemon に userns-remap を設定して初めて有効になり、設定すれば全コンテナが user namespace 有効で起動する。設定していない環境ではコンテナ内の root がホストから見ても UID 0 のままなので、マウントしたホストディレクトリを root 権限で書き換えられてしまう。
cgroup (リソース制限)
cgroup には v1 と v2 があり、階層の構造が違う。v1 はコントローラー (cpu、memory など) ごとに別々の階層を持てたため、同じプロセスが資源別に別のグループへ属せた。v2 は階層を 1 本に統一し、親の cgroup.subtree_control でどのコントローラーを子へ委譲するかを選ぶ形に変わった。v2 には内部プロセス禁止の制約もあり、子へ資源を分配するグループ自身はプロセスを持てない (プロセスは常に葉に置く。ルートだけは例外)。どちらが動いているかは /sys/fs/cgroup を見れば分かり、v2 なら cgroup.controllers が置かれている。
| リソース | 制限内容 | Kubernetes での設定 |
|---|---|---|
| CPU | CPU 使用率の上限 | resources.limits.cpu |
| メモリ | メモリ使用量の上限 | resources.limits.memory |
| I/O | ディスク I/O の帯域 | Pod の指定項目には無く、ノード側の設定で絞る |
| PID | プロセス数の上限 | Pod では指定できず、kubelet の podPidsLimit で決まる |
# Kubernetes での設定
containers:
- name: app
resources:
requests:
cpu: 100m # 最低保証: 0.1 CPU
memory: 128Mi # 最低保証: 128 MB
limits:
cpu: 500m # 上限: 0.5 CPU
memory: 512Mi # 上限: 512 MB (超過で OOMKill)
requests と limits は cgroup への写り方が違う。limits は kubelet がコンテナの cgroup に上限として書き込み、カーネルが強制する。requests はスケジューラーがノードを選ぶための予約値で上限ではなく、ノードに余裕があれば requests を超えて使える。
強制のされ方も CPU とメモリで非対称である。CPU の上限はスロットリングで実現され、上限に近づくとカーネルが CPU の割り当てを絞るだけでプロセスは殺されない。cgroup v2 の cpu.max は「1 周期あたりに使える時間」という形式で、既定の周期は 100 ミリ秒である。cpu: 500m は 100 ミリ秒ごとに 50 ミリ秒しか走れないという意味なので、平均使用率が低くても一瞬だけ CPU を欲しがる処理は待たされ、レイテンシの裾が伸びる。一方メモリは絞って引き延ばすことができないため、上限に達すると強制終了になる。CPU 上限は遅くなるだけ、メモリ上限は落ちる、と覚えておくと障害時の切り分けが早い。
VM との比較
コンテナと VM の差は、どの層で線を引くかに尽きる。コンテナはカーネルを共有したまま namespace で見え方を変えるので、起動は新しいプロセスを作るのと同じ速さで済む。VM はゲスト OS ごとカーネルを持つため、起動のたびにカーネルの初期化を通る。以下の表はその帰結である。
| 観点 | コンテナ (Namespace + cgroup) | VM (ハイパーバイザー) |
|---|---|---|
| 隔離レベル | プロセスレベル (カーネル共有) | ハードウェアレベル (カーネル独立) |
| 起動時間 | ミリ秒 | 秒〜分 |
| オーバーヘッド | 小さい | 大きい (ゲスト OS) |
| セキュリティ | 中程度 (カーネル共有) | 高い (完全隔離) |
OOMKill
コンテナがメモリ上限に達し、回収できるメモリも無くなると、カーネルはその cgroup の中で OOM killer を動かす。犠牲者は cgroup 内から選ばれるので、必ずメインプロセスが落ちるとは限らない。子プロセスだけが殺された場合、コンテナは動き続け、Pod の状態も OOMKilled にならないまま一部の機能だけが壊れる。終了コード 137 は 128 + 9 (SIGKILL) で、自分で終了したのではなく外部から強制終了されたことを示す。
kubectl describe pod myapp
# ...
# Last State: Terminated
# Reason: OOMKilled
# Exit Code: 137
Lambda との関係
Lambda の実行環境は、AWS が Lambda と Fargate のために開発した VMM である Firecracker の microVM 単位で隔離される。KVM を使う軽量 VM なので、隔離の境界はカーネルを共有するコンテナよりも VM 側に寄っている。MemorySize は 128 MB から 10,240 MB の範囲で指定し、CPU の割り当ては設定したメモリ量に比例する。1,769 MB でちょうど 1 vCPU 相当になるため、CPU 律速の処理はメモリを増やすと速くなり、実行時間が縮んで料金まで下がることがある。CPU とメモリを cgroup で別々に絞る Kubernetes と違い、1 つのつまみで両方が動く点が設計上の分かれ目になる。
運用で問われるのは、どの namespace をあえてホストと共有しているか、そしてどの上限がスロットリングでどの上限が強制終了なのか、の 2 点である。カーネル側の挙動まで踏み込んだ解説は関連書籍が詳しい。
この記事は役に立ちましたか?
関連用語
コンテナ
アプリケーションとその依存関係をパッケージ化し、環境に依存しない一貫した実行環境を提供する仮想化技術
Pod
Kubernetes の最小デプロイ単位で、1 つ以上のコンテナをまとめて管理するリソース
Dockerfile
Docker イメージのビルド手順を記述するテキストファイルで、アプリケーションの実行環境を再現可能にする
Kubernetes Namespace
Kubernetes クラスター内の API リソースを論理的に分離し、権限とリソース枠の適用単位を切る仕組み。ノードとカーネルは共有されるためセキュリティ境界にはならない
Namespace 分離
Kubernetes の Namespace を使ってリソース、ネットワーク、権限を論理的に分離するマルチテナント戦略
サイドカーパターン
メインコンテナと同じ Pod に補助コンテナを並べ、ネットワークと Volume を共有して横断的関心事を分離する設計パターン
関連する記事
技術書の知識を定着させる間隔反復法 - 読んだのに忘れる問題を解決する
技術書を読んでも内容を忘れてしまう原因を認知科学の観点から分析し、間隔反復法を使って知識を長期記憶に定着させる具体的な方法を紹介します。
Linux 本ガイド - コマンドライン / しくみ / 性能の 3 層で選ぶ技術書
Linux を学ぶ技術書の選び方を 3 層 (コマンドラインの操作 → カーネルのしくみ → 性能と運用) で整理。新しい Linux の教科書や [試して理解] Linux のしくみなどの定番書の使い分けと、学ぶ順番を解説します。
技術書の読書ノート術 - 付箋 / マーカー / デジタルの使い分け
技術書を読むときのノートの取り方を比較します。付箋派、マーカー派、デジタルノート派、それぞれの長所と短所を実体験をもとに紹介します。