Kubernetes 解体新書Part 1 Kubernetes の全体像

コンテナとは何か

同じアプリでも、コンテナの中と外では見えるものが違います。プロセス、ファイル、メモリの具体例で仕組みを見ていきます。

  • L1 Web ターミナル
  • 更新 2026年10月6日

同じサーバーで、Web サイトのアプリとデータベースを動かしたい。 でも、設定ファイルが混ざったり、片方がメモリを使い切ったりすると困ります。

コンテナは、こうしたアプリにそれぞれの実行環境を用意するための仕組みです。 アプリごとにファイルや見えるプロセスを分け、使えるメモリなどにも上限を付けられます。 この章では「何が分かれていて、何が共通なのか」を、図と具体例で見ていきます。

GOAL この章のゴール

  • コンテナの中と外で、見えるプロセスが違う理由を説明できる
  • 「見える範囲を分ける」と「使える量を制限する」を区別できる
  • コンテナと VM の違いを、カーネルを共有するかどうかで説明できる

アプリは、サーバーの上で動いている

まず、動いているプログラムのことを プロセス と呼びます。 Web サーバーの nginx も、起動するとプロセスになります。

nginx をコンテナで動かしても、サーバーの上でプロセスが動くことは同じです。 変わるのは、そのプロセスから見えるファイルや、ほかのプロセスの範囲です。 コンテナを動かしている側のマシンを ホスト と呼びます。

たとえば、コンテナの中でプロセス一覧を見ると、nginx とその仲間だけが並びます。 ホストで同じ一覧を見ると、その nginx に加えて、ほかのアプリも並びます。 同じマシンで動いていても、見る場所によって一覧が違うのです。

namespace: 見える世界を分ける

下の図で、左右の nginx: master process を探してみてください。 左では番号が 4231、右では 1 です。 これは別々の nginx ではなく、同じプロセスを、コンテナの外と中から見たものです。 この番号を PID (プロセス ID) と呼びます。

同じ nginx を、ホストから見た場合とコンテナの中から見た場合左はホストの PID 空間。PID 1 は systemd、PID 4210 が containerd-shim、PID 4231 が nginx。右はコンテナの PID namespace。同じ nginx が PID 1 に見え、ホスト側の sshd などは見えない。ホストから見た psPID CMD1 /sbin/init (systemd)812 /usr/bin/containerd901 /usr/bin/kubelet4210 containerd-shim-runc-v24231 nginx: master process4260 nginx: worker process5102 sshd: ubuntu [priv]コンテナ内の nginx も一覧に出てくる。コンテナの中から見た psPID CMD1 nginx: master process7 nginx: worker process12 ps同じ nginx でも、ここでは PID 1。worker などには別の番号が付く。ホスト側の sshd などはこの一覧には出てこない。
図 1左はホスト、右はコンテナの中。nginx は同じプロセスでも、見る場所によって番号が違う。番号は説明用の例。

右の一覧には、左にある sshd などのプロセスが出てきません。 コンテナの中から見える範囲を分けているからです。 このように、プロセスから見える範囲を分ける Linux の仕組みが namespaceネームスペースプロセスの一覧やネットワークなど、プロセスから見える範囲を種類ごとに分ける Linux の仕組み。用語集で見る です。 プロセスの番号と見える範囲を分けるものは、PID namespace と呼びます。 新しい PID namespace で最初に起動したプロセスには、内側で 1 番が付きます。 図の nginx のように、その後に増えたプロセスには別の番号が付きます。

分けられるのはプロセスだけではありません。 たとえば network namespace でネットワークを分けると、別々のコンテナがそれぞれ内側で同じ 80 番ポートを使えます。 ポートは通信の受け口の番号です。 別のネットワークに分かれているので、番号が同じでも取り合いになりません。

namespace にはほかにも種類がありますが、まずは「プロセスやネットワークの見える範囲を分けられる」と押さえれば、この先を読めます。 どの範囲を分けるかは設定次第で、複数のコンテナが同じ namespace を共有することもあります。

ファイル: 同じ /etc でも、中身は別

プロセスの一覧が分かれていても、設定ファイルまで共通だと困ります。 そこで、コンテナにはアプリ用のファイル一式を用意します。 アプリ本体やライブラリなどを配布用にまとめたものが コンテナイメージ です。

Linux のファイルは、/ という一番上のディレクトリからたどります。 これを ルートディレクトリ と呼びます。 コンテナでは、イメージから用意したファイル一式を、この / の下に見せます。 だから、ホストとコンテナの両方に /etc があっても、通常は別のディレクトリを指します。

この準備には、ファイルシステムの接続状態を分ける mount namespace や、ルートを入れ替える pivot_root などが使われます。 ホスト自身の / をコンテナのものに置き換えるわけではありません。 実際の手順は Part 3 の「コンテナを手で作る」 で試します。

cgroups: メモリや CPU の使いすぎを防ぐ

次は、アプリがメモリをどんどん使ってしまう場面です。 ほかのアプリが見えなくても、同じホストのメモリを使っていることは変わりません。 プロセスの一覧を分けただけでは、メモリの使いすぎは防げません。

そこで「このコンテナのメモリはここまで」と上限を設定します。 プロセスをグループにまとめ、CPU やメモリなどの使用量を管理する仕組みが cgroupsシーグループスプロセスをグループにまとめ、CPU やメモリなどの使用量を制限・監視する Linux の仕組み。用語集で見る です。

上限に達したときの動きは、資源によって違います。

  • CPU: 一定時間内に使える CPU 時間を使い切ると、次の期間まで実行が待たされます。
  • メモリ: 上限に達し、不要なメモリを回収しても足りないと、グループ内のプロセスが終了させられることがあります。これがメモリ不足による OOM (Out Of Memory) の一例です。

namespace は「見える範囲」、cgroups は「使える量」を担当します。 コンテナを起動しただけで必ず適切な上限が付くわけではないので、使える量は別途設定します。

VM との違い: カーネルを共有する

ここまでで、プロセス、ファイル、使える量を分けられることが分かりました。 では、コンテナごとに OS も丸ごと起動しているのでしょうか。

通常の Linux コンテナでは、OS の中核である カーネル をホストと共有します。 カーネルは、メモリを管理したり、ファイルやネットワークへのアクセスを処理したりする部分です。 コンテナの中のアプリがファイルを開くときも、ホストのカーネルが処理します。

VM (仮想マシン) は、それぞれが自分のカーネルを起動します。 図では、カーネルの段がいくつあるかを見てください。

VM とコンテナの違い: VM はゲストカーネルを持ち、コンテナはホストのカーネルを共有する左が VM のスタック (ハードウェア、ホスト OS、ハイパーバイザー、ゲストカーネル、アプリ)。右がコンテナのスタック (ハードウェア、ホストカーネル、containerd と runc、アプリ)。コンテナにはゲストカーネルの層が無い。VMハードウェアホスト OS + ハイパーバイザーKVM などゲストカーネルVM ごとに 1 つライブラリ + アプリコンテナハードウェアホストカーネル (Linux)全コンテナで共有containerd + runcnamespace / cgroups を設定して execライブラリ + アプリただのプロセスアプリの syscall はゲストカーネルが受ける起動はゲスト OS のブートアプリの syscall はホストカーネルが直接受ける起動はプロセスの起動
図 2VM はそれぞれにカーネルを持つ。通常の Linux コンテナはホストのカーネルを共有する。
ファイル一式が分かれていても、カーネルまで別とは限らない。
観点VM通常の Linux コンテナ
カーネルVM ごとに起動するホストと共有する
アプリを動かす準備OS とアプリを起動する実行環境を用意してアプリを起動する
OS の選択VM ごとに別の OS を選べるホストのカーネルで動くアプリを使う

コンテナは、カーネルを毎回起動する必要がないぶん、起動やメモリ使用量の負担を抑えやすくなります。 ただし、共有しているカーネルの不具合が、複数のコンテナに影響する可能性もあります。 より強く分離する gVisor や Kata Containers などの選択肢は、Part 3 の「分離のレベル」 で扱います。

イメージ: 共通のファイルを再利用する

コンテナイメージには、アプリを動かすためのファイルが入っています。 たとえば、同じ Linux のファイル一式を土台にして、Web アプリ用とバッチ処理用のイメージを作れます。 そのたびに土台を丸ごと保存すると、同じファイルが重複します。

そこでイメージは、ファイルの追加・変更・削除を 層 (レイヤー) として持ちます。 同じ保存先に共通の層があれば、それを再利用できます。 docker pull でダウンロード済みの層が飛ばされるのも、このためです。

イメージは tar の層の積み重ね。Dockerfile の各行が 1 層になり、実行時には OverlayFS で 1 つのディレクトリに見せる左に Dockerfile の 3 行、中央に対応する 3 つの読み取り専用レイヤーと書き込み用の upper、右に merged として見える 1 つのルート。DockerfileFROM ubuntu:24.04RUN apt install nginxCOPY site/ /var/www/レイヤー (各層は tar、内容のハッシュで識別)sha256:a1… (ubuntu)sha256:b7… (+nginx)sha256:c3… (+site/)upperdir: 実行中の書き込みlowerdir: 読み取り専用、他のイメージと共有OverlayFSコンテナの / (merged)/bin /lib /etc/usr/sbin/nginx/var/www/index.html書くと upperdir に copy-up消すと upperdir に whiteout同じ base を使う 100 コンテナでも、ディスク上の ubuntu 層は 1 つ。これが「軽い」理由。
図 3イメージの層は読み取り専用。コンテナでの変更は、そのコンテナ用の書き込み層に保存する。

実行時には、イメージの層にコンテナごとの書き込み層を重ねます。 この重ね合わせによく使われるのが OverlayFSオーバーレイエフエス複数のディレクトリを重ね、1 つのディレクトリに見せる Linux のファイルシステム。用語集で見る です。 アプリからは、層を意識せず普通のファイルとして読み書きできます。

コンテナの中でファイルを変更しても、元のイメージは変わりません。 そのコンテナを削除すると、書き込み層も失われます。 残したいデータをボリュームに保存するのは、このためです。

試す: ホスト側からコンテナを見つける

ここで、自分専用のハンズオン環境を使って確かめます。 探すのは、コンテナの中のアプリが、ホストのプロセス一覧にも出てくることです。

Kubernetes がコンテナを動かすマシンを ノードノードKubernetes がコンテナを動かすマシン。物理マシンの場合も VM の場合もある。用語集で見る と呼びます。 これらのマシンと、それらを管理する仕組みをまとめて クラスタクラスタKubernetes でアプリを動かすノードと、それらを管理する仕組みの集まり。用語集で見る と呼びます。 ノードの名前と台数は、kubectl get nodes で確認できます。

  1. 画面下の Web ターミナルを開き、環境に接続します。
  2. 次のコマンドを実行します。ノードの中に一時的な作業場を作り、プロセス一覧を表示します。
  3. 出力の中に、coredns や cilium-agent などのアプリ名を探します。番号や並びは環境によって変わります。
ノード上のコンテナのプロセスをホスト側から見る
kubectl debug node/$(kubectl get node -o jsonpath='{.items[0].metadata.name}') -it --profile=sysadmin \
  --image=busybox:1.37 -- chroot /host \
  sh -c 'ps -eo pid,ppid,comm --forest | grep -A2 containerd-shim | head -20'

出力例

 1204     1 containerd-shim-runc-v2
 1250  1204   \_ pause
 1290  1204   \_ coredns
--
 1320     1 containerd-shim-runc-v2
 1366  1320   \_ pause
 1402  1320   \_ cilium-agent

containerd-shim は、コンテナの実行を支えるプロセスです。 細かな親子関係は後の章で扱います。 今は、コンテナ内で動くアプリを、ホスト側の一覧でも見つけられたことを確認できれば十分です。

終わったら、一時的な作業場を削除します。

デバッグ用の作業場を消す
kubectl delete pods -l app.kubernetes.io/managed-by=kubectl-debug

ふりかえり

Q図の nginx が、ホストでは PID 4231、コンテナ内では PID 1 でした。なぜでしょう?

同じプロセスでも、ホストとコンテナ内では別の番号で見えます。コンテナ内のすべてのプロセスが 1 番になるわけではありません。

Qコンテナのメモリ使用量に上限を付けるのは、どの仕組み?

cgroups が使える量を管理します。namespace で見えるプロセスを分けても、それだけではメモリの上限は付きません。

Q通常の Linux コンテナ同士が共有しているのはどれ?

アプリ用のファイルや書き込み層が別でも、カーネルは共有します。VM はそれぞれにカーネルを持ちます。

参考