← AWSサービスの内部原理 コース
76. コンテナは隔離されたプロセスである — namespacesが見える世界を分け、cgroupsが資源を配る
コンテナの正体は「特別な箱」ではなく「隔離されて動く普通のプロセス」です。ホストのカーネルを共有しながら、namespacesで見える世界を分け、cgroupsで使える資源を配る——その2つのカーネル機能の役割分担を図で追っていきます。
① コンテナは「隔離されたプロセス」— VMのようにOSを丸ごと積まない
ホストのカーネルLinuxカーネル(1つ)。全員がこれを共有する
それぞれの中身
VMの世界自前カーネルごと積む
ハイパーバイザ+仮想ハードウェアの層を挟むコンテナの世界カーネルはホストから借りる
仮想ハードウェアの層なしゲストOS+アプリOSまるごと1つ=自前のカーネル・ドライバ・アプリ
隔離プロセスA/Bアプリ+依存ファイルだけを同梱した、ただのプロセス
- 公式:「containers are isolated processes for each of your app's components」— コンテナはアプリの各部品ごとの隔離されたプロセス
- VM側:「a VM is an entire operating system with its own kernel, hardware drivers, programs, and applications」— VMは自前のカーネルを持つOSまるごと1つ
- 共有:「If you run multiple containers, they all share the same kernel, allowing you to run more applications on less infrastructure」— 複数コンテナは同じカーネルを共有するので、少ないインフラで多く動かせる
- 既習との接続:OSのプロセス・カーネル・リソース管理という、CS基礎のど真ん中の回。
コンテナはVMのように「カーネルごと」積み替えない。ホストのカーネルを共有した隔離プロセスなので、OSの起動を待たずに立ち上がり、1台にたくさん詰められる。
② namespaces=「見える世界」を分ける
1つのホストOS
アクセスはそのnamespace内に限られる
PIDプロセスIDが1から見える
Network自分のIP・ポートを持つ
Mountファイルシステムの見え方
互いに不可視同じホスト上のプロセスなのに、別コンテナやホストのプロセスを見られない
- 「Docker uses a technology called `namespaces` to provide the isolated workspace called the container.」— Dockerはnamespacesという技術で、コンテナという隔離ワークスペースを提供する
- 「Each aspect of a container runs in a separate namespace and its access is limited to that namespace.」— コンテナの各側面は別々のnamespaceの中で動き、アクセスはそのnamespaceに限られる
- Docker security文書:「Processes running within a container cannot see, and even less affect, processes running in another container, or in the host system.」— コンテナ内のプロセスは、別コンテナやホストのプロセスを見ることも、まして影響を与えることもできない
- 図の3種は代表例。Linuxカーネルのnamespaceは全8種(Cgroup / IPC / Network / Mount / PID / Time / User / UTS)。PIDは「Process IDs」、Networkは「Network devices, stacks, ports」、Mountは「Mount points」を隔離する(man7 `namespaces(7)`)
- 既習との接続:namespacesとcgroupsは、Lambda編で触れた『プロセス分離』の正体そのもの。ただしカーネルは1つを共有したまま——Lambda編のFirecracker microVMは、この共有カーネルすら分けて(=①のVM側に寄せて)他人同士の同居を強くしたもの。
namespacesは「眺め」を分ける仕組み。プロセスID・ネットワーク・マウント(ファイルシステムの見え方)など側面ごとに独立した世界を与えるので、同じホスト上のプロセスなのに互いを見られない。
③ cgroups=「使える資源」を配る
ホストの資源CPU・メモリ
Dockerはこの設定を変更しているだけ
cgroup AコンテナAのmem上限/CPU割合
cgroup BコンテナBのmem上限/CPU割合
cgroup CコンテナCのmem上限/CPU割合
カーネルが計量・制限資源を実際に止めているのはカーネル本体
- 「When you use these settings, Docker modifies the settings for the container's cgroup on the host machine.」— これらの設定を使うと、Dockerはホストマシン上のコンテナのcgroup設定を変更しているだけ
- Docker security文書:「Control Groups are another key component of Linux containers. They implement resource accounting and limiting.」— cgroupsの役目は資源の計量と制限
- 「they do not play a role in preventing one container from accessing or affecting the data and processes of another container」— 隔離役(=namespaces)とは役割が別
- namespaces(②)=見える世界を分ける / cgroups(③)=使える資源を配る——役割が別
cgroupsはnamespacesと対になるもう1つのカーネル機能。namespacesが「見える世界」を分けるのに対し、cgroupsは「使える資源」を配る。Dockerがやっているのはこのcgroupの設定変更にすぎず、資源を止めているのはカーネル本体である。
④ 資源フラグの効き方 — ハード上限・ソフト制限・割合・重み
--memory / -mハード上限(最小6m)
超過分は使えず、メモリ不足になるとカーネルのOOMキラーの対象になる--memory-reservationソフト制限
--memoryより小さく設定。ホスト逼迫を検知した時だけ効く4つともやっていることは
--cpus割合制限。CFS(スケジューラ)設定
--cpus="1.5" = period 100000 / quota 150000--cpu-shares相対的な重み(既定1024)
CPUが取り合いになった時だけ効くcgroup設定の変更止めているのはカーネル本体。Docker自身は魔法を使っていない
- --memory:上限の最小値は「If you set this option, the minimum allowed value is `6m` (6 megabytes).」。OOMについて公式は「if the kernel detects that there isn't enough memory to perform important system functions, it throws an `OOME`, or `Out Of Memory Exception`, and starts killing processes to free up memory」と述べる(※これはメモリ不足時のカーネル一般の挙動を説明した文で、上限超過で即このコンテナのプロセスが殺されると断定した文ではない)
- --memory-reservation:「a soft limit smaller than `--memory` which is activated when Docker detects contention or low memory on the host machine」— 逼迫や低メモリを検知した時だけ効くソフト制限
- --cpus:「If the host machine has two CPUs and you set `--cpus="1.5"`, the container is guaranteed at most one and a half of the CPUs. This is the equivalent of setting `--cpu-period="100000"` and `--cpu-quota="150000"`.」。CFSは「The CFS is the Linux kernel CPU scheduler for normal Linux processes.」(通常のLinuxプロセス用のカーネルCPUスケジューラ)
- --cpu-shares:「the default of 1024 … This is only enforced when CPU cycles are constrained.」— 既定1024の相対的な重み。CPUが取り合いになった時だけ効く
- 既習との接続:--memoryや--cpusで『使いすぎを機械的に止める』この仕組みは、API Gateway編のスロットリングのOS版。あちらはリクエスト数、こちらはCPU・メモリを、待たずに機械的に頭打ちにする。
同じ「制限」でも効き方は4通り。--memoryは超えて使わせない固い上限、--memory-reservationは逼迫時だけ効く柔らかい制限、--cpusはスケジューラで割合を切る、--cpu-sharesは奪い合いになって初めて効く相対的な重み。どれもカーネルのcgroup機能に投げているだけで、Docker自身は魔法を使っていない。
⑤ だから「自分のマシンでは動いた」問題が消える
隔離プロセスnamespacesが見える世界を分ける
依存ファイル一式イメージの中に全部入っている
ホストにライブラリが入っていなくても動く
どこでも同じどのホストに置いても「見える世界」と「持ち物」が同じ
環境差問題の消滅「自分のマシンでは動いたのに」が構造的に消える
- 「Each container has everything it needs to function with no reliance on any pre-installed dependencies on the host machine」— 各コンテナは動くのに必要なものを全部持ち、ホストに事前インストール済みの依存に頼らない
- 「Since containers run in isolation, they have minimal influence on the host and other containers」— 隔離されて動くので、ホストや他コンテナへの影響は最小
namespacesで世界を分け、依存をイメージに同梱して自己完結にする——この2点で、コンテナはどのホストでも同じ「持ち物」と「見え方」で起動する。環境差に由来する「自分の環境では動いた」問題が構造的に消える。