Kubernetes のアーキテクチャを整理する:Control Plane と Node の構成要素
- 公開日
- カテゴリ:Kubernetes
- タグ:Kubernetes,学習メモ

Kubernetes では、人間が「あるべき状態」を宣言し、Kubernetes が現在の状態をそこへ近づけ続ける(この考え方は「Kubernetes(k8s)とは?何を解決する仕組みなのかを整理する」を参照)。
この記事では、その「Kubernetes が」の中身を整理する。クラスタがどんな構成要素でできていて、それぞれが何を担当しているのか、Pod が動き出すまでに誰がどの順で動くのかを見ていく。
この記事で整理すること:
- クラスタの全体像(Control Plane と Node)
- Control Plane のコンポーネント(kube-apiserver、etcd、kube-scheduler、kube-controller-manager)
- Node のコンポーネント(kubelet、container runtime、kube-proxy)と CNI
kubectl applyから Pod が動き出すまでの流れ- Node が落ちたときの動き
コンポーネント同士の関係や処理の流れを図にしたものは「Kubernetes の仕組みを図で整理する」にまとめている。
contents
- クラスタの全体像
- Node
- Control Plane のコンポーネント
- Node のコンポーネント
- CNI とネットワークモデル
- アドオン
- kubectl apply から Pod が動くまで
- Pod は Node 間を移動しない
- Node が落ちたときの流れ
- 用語メモ
- 参考 URL
クラスタの全体像
Kubernetes のクラスタは、Control Plane(コントロールプレーン)と、Pod を動かす1台以上の Node(ノード)でできている。
| 部分 | 役割 |
|---|---|
| Control Plane | クラスタ全体を管理する。スケジューリングのようなクラスタ全体に関わる判断や、イベントの検知と対応を担う |
| Node | Pod(コンテナ)を実際に動かす。Worker Node とも呼ぶ |
┌─ Control Plane ────────────────────────────────────────┐
│ │
│ kube-scheduler kube-controller-manager │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────────────────┐ │
│ │ kube-apiserver │◀──────┼──── kubectl
│ └────────────────────────────────────────────┘ │
│ │ ▲ │
│ ▼ │ │
│ etcd │ │
└───────────────────────────┼────────────────────────────┘
│
┌──────────────┴──────────────┐
│ │
┌─ Node 1 ───┴─────────────┐ ┌─ Node 2 ───┴─────────────┐
│ kubelet │ │ kubelet │
│ kube-proxy │ │ kube-proxy │
│ container runtime │ │ container runtime │
│ [Pod] [Pod] [Pod] │ │ [Pod] [Pod] │
└──────────────────────────┘ └──────────────────────────┘
この図の特徴は、矢印がすべて kube-apiserver に集まっていること。kube-scheduler も kube-controller-manager も、各 Node の kubelet も、人間が使う kubectl も、互いに直接やりとりせず kube-apiserver を経由する。公式ドキュメントでは、この形を「hub-and-spoke」(ハブ・アンド・スポーク)の API パターンと呼んでいる。
Node
Node は、Pod を動かすためのマシン1台。物理サーバーでも仮想マシンでもよい。
- Node も Kubernetes のリソースの一つ。一覧は
kubectl get nodesで確認 - Node の状態を表す condition の一つが
Ready。Trueなら、Node が正常で Pod を受け入れられる状態 - kubelet は、Node ごとの Lease というオブジェクトを既定で10秒ごとに更新する。これが Node の生存を知らせるハートビート
Control Plane のコンポーネントがどこで動くかは、構築方法によって変わる。
- kubeadm のような構築ツールでは、Control Plane のコンポーネントを static Pod として動かす方式が一般的。static Pod は、kubelet が Node 上の決まったディレクトリ(kubeadm では
/etc/kubernetes/manifests)にある定義ファイルを読んで、直接起動する Pod - kubeadm の既定は、セキュリティ上の理由で、Control Plane の Node に通常の Pod を置かない設定
- EKS / GKE / AKS のようなマネージドサービスでは、Control Plane の管理はクラウド事業者の担当
Control Plane のコンポーネント
kube-apiserver
Kubernetes API を公開するサーバー。公式ドキュメントでは、Control Plane のフロントエンド(窓口)と説明されている。
- kubectl での操作も、実体は kube-apiserver への HTTP リクエスト
- リクエストの処理順は、認証 → 認可 → Admission 制御
リクエスト → 認証(誰か?)→ 認可(それをしてよいか?)→ Admission 制御(内容の検証・変更)→ 処理
- etcd へのアクセスは、理想的には kube-apiserver だけに限定(etcd へのアクセスはクラスタの root 権限に等しいため)
- 変更を効率よく検知するための watch の仕組みも提供。クライアントはリソースの変化を購読でき、kube-scheduler やコントローラーが変化を受け取る手段になっている
- インスタンスを増やして負荷を分散できる、水平スケールを前提とした設計
etcd
クラスタの全データを保存する、一貫性と高可用性を備えたキーバリューストア。Deployment や Pod など、あらゆるリソースの定義と状態がここに入る。
- 発音は「エトシーディー」(/ˈɛtsiːdiː/)。名前の意味は "distributed etc directory"(分散された
etcディレクトリ) - 合意アルゴリズムは Raft。更新の確定には、過半数(クォーラム)の合意が必要
- クラスタの全データを持つため、バックアップの計画が必須
etcd は奇数台で組むことが推奨されている。台数と、故障しても動き続けられる台数の関係は次のとおり(etcd の FAQ より)。
| 台数 | 過半数 | 耐えられる故障台数 |
|---|---|---|
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
| 6 | 4 | 2 |
奇数台が推奨される理由は2つ。
- 偶数台にしても、耐えられる故障台数は1台少ない奇数台と同じ(壊れうるマシンだけが増える形)
- ネットワーク分断時に、必ずどちらか一方に過半数が残る構成(4台が2台ずつに分かれると、どちらも過半数に届かない)
kube-scheduler
まだ Node が割り当てられていない Pod を見つけて、動かす Node を選ぶコンポーネント。選び方は2段階になっている。
① フィルタリング: Pod の条件を満たせない Node を候補から外す
(例: Pod が要求する CPU・メモリの空きがない Node)
↓
② スコアリング: 残った Node に点数を付ける
↓
最も点数の高い Node を選び、kube-apiserver に通知する(binding)
(同点の Node が複数あれば、その中からランダムに選ぶ)
- 選ばれた Node は、Pod の
spec.nodeNameに入る - 条件を満たす Node が1台もなければ、Pod はスケジュールされないまま待機
- kube-scheduler の仕事は Node を選ぶところまで。コンテナを起動するのは、選ばれた Node の kubelet
kube-controller-manager
コントローラーを実行するコンポーネント。コントローラーは、今の状態を観察し、あるべき状態との差分を埋める「調整ループ」を回す担当。論理的にはコントローラーごとに別のプロセスだが、複雑さを減らすために1つのバイナリ・1つのプロセスにまとめられている。
主なコントローラーは次のとおり。
| コントローラー | 担当 |
|---|---|
| Deployment コントローラー | Deployment に対応する ReplicaSet を作り、更新時は新旧の ReplicaSet の数を段階的に入れ替える |
| ReplicaSet コントローラー | Pod の数を replicas に合わせる |
| Node コントローラー | Node からの報告が途絶えたら、Node の状態を Unknown にして taint(問題のある Node を示す印)を付ける |
| taint-eviction コントローラー | taint が付いた Node から Pod を退避させる(v1.29 で Node コントローラーから分離) |
| Job コントローラー | 一度きりのタスクを表す Job を見て、完了するまで Pod を動かす |
| EndpointSlice コントローラー | EndpointSlice を作成・更新し、Service と Pod を結びつける |
- コントローラーは、自分で Pod やコンテナを動かさない。たとえば Job コントローラーは kube-apiserver に Pod の作成・削除を依頼するだけで、その先はほかのコンポーネントの担当
- Deployment コントローラーも同様に、ReplicaSet を作るまでが担当。その ReplicaSet を見て Pod を作るのは ReplicaSet コントローラー
cloud-controller-manager
クラウドプロバイダーと連携するためのコンポーネント(オプション)。オンプレミスや、手元の PC の学習環境で動かすクラスタには存在しない。
- Node コントローラー: 応答しなくなった Node の VM が、クラウド側で削除されていないかの確認
- Route コントローラー: クラウドのネットワークへの経路設定
- Service コントローラー: クラウドのロードバランサーの作成・更新・削除
Node のコンポーネント
まず、Node の中にいるものを一覧にすると次のようになる(kubeadm で構築したクラスタの場合)。
Node(マシン1台)
├── OS(Linux カーネル) … kube-proxy が設定した転送ルール(iptables / nftables など)もここに入る
├── kubelet … OS のサービス(systemd)として動く。Pod ではない
├── container runtime … containerd など。Node 上のデーモンとして動く
├── CNI プラグイン … container runtime から呼ばれ、Pod のネットワークを用意する
├── Pod: kube-proxy … DaemonSet として、Node ごとに1つずつ置かれる
├── Pod: アプリ … kube-scheduler がこの Node に割り当てたもの
│ └── コンテナ
└── Pod: etcd / kube-apiserver / kube-scheduler / kube-controller-manager
… Control Plane 用の Node の場合だけ(static Pod)
Node の中身は、Pod を動かすための土台(OS・kubelet・container runtime)と、その上に置かれた Pod の2層になっている。kube-proxy のように、Node のコンポーネントでありながら Pod として動くものもある。DaemonSet は、各 Node に1つずつ Pod を置くためのリソース。
kubelet
各 Node で動くエージェント。Pod の定義(PodSpec)に書かれたコンテナが、動いていて正常な状態であることを保証する。
- Kubernetes が作っていないコンテナは管理対象外
- container runtime とのやりとりは CRI 経由
- kubeadm で構築したクラスタでは、kubelet 自体は Pod ではなく systemd のサービスとして動作
container runtime
コンテナの実行とライフサイクルを管理するソフトウェア。containerd や CRI-O など、CRI(Container Runtime Interface)を実装したものが使える。
- CRI は、kubelet と container runtime の間の通信を定めた gRPC のプロトコル
- kubelet は、CRI のクライアントとして container runtime に接続
kube-proxy
Service の仕組みの一部を実装する、各 Node 上のネットワークプロキシ。Node 上のネットワークルールを管理し、クラスタの内外から Pod へ通信が届くようにする。
- Service の仮想 IP 宛ての通信を捕まえ、Service の裏にいる Pod へ転送するように Node を設定
- OS のパケットフィルタリング層が使える場合はそれを使い、使えない場合は kube-proxy 自身が転送
- Linux で選べるモードは
iptables/ipvs/nftables。既定はiptablesで、将来のバージョンでnftablesに変わる予定 ipvsモードは v1.35 で非推奨になり、v1.40 から既定で無効になる予定- kube-proxy はオプション扱い。Service の転送を自前で実装するネットワークプラグイン(Cilium など)を使う場合は不要
CNI とネットワークモデル
Kubernetes のネットワークモデルでは、次のことが決められている。
- 各 Pod が、クラスタ内で一意の IP アドレスを持つこと
- すべての Pod が、同じ Node にいても別の Node にいても、プロキシや NAT(アドレス変換)なしで直接通信できること
ただし、Kubernetes 本体が実装しているのはこのモデルの一部だけで、Pod のネットワークそのものは外部のコンポーネントに任されている。Linux ではほとんどの container runtime が CNI(Container Network Interface)を使ってネットワークの実装とやりとりするため、こうした実装は CNI プラグインと呼ばれる。
- CNI プラグインの役割は、Pod への IP アドレスの割り当てと、Pod 同士の通信の実現
- CNI プラグインを読み込んで使うのは container runtime
- 代表例は Calico、Cilium、Flannel など
CNI プラグインと kube-proxy の役割分担は次のとおり。
| 担当 | |
|---|---|
| CNI プラグイン | Pod に IP を割り当て、Pod と Pod を直接つなぐ |
| kube-proxy | Service 宛ての通信を、Service の裏にいる Pod へ届ける |
コンテナの実行(CRI)やネットワーク(CNI)のように、Kubernetes が API や約束事だけを定め、実装を外部のコンポーネントに任せている部分もある。
アドオン
Control Plane と Node のコンポーネントに加えて、クラスタの機能を拡張するアドオンがある。アドオンは DaemonSet や Deployment などの Kubernetes のリソースとして動き、kube-system という名前空間に置かれる。
| アドオン | 役割 |
|---|---|
| DNS | クラスタ内の名前解決。厳密には必須ではないが、すべてのクラスタが持つべきとされている |
| Web UI(Dashboard) | Web 画面からのクラスタ管理 |
| Container Resource Monitoring | コンテナのメトリクスの収集と保存 |
| Cluster-level Logging | コンテナのログを、検索できる中央のストアに保存 |
kubectl apply から Pod が動くまで
replicas: 3 の Deployment を kubectl apply したときの流れは次のとおり。
kubectl apply -f deployment.yaml
│
│ ① kube-apiserver が認証・認可・Admission 制御を通し、Deployment を etcd に保存
│ ② Deployment コントローラーが新しい Deployment を検知し、ReplicaSet を作る
│ ③ ReplicaSet コントローラーが「Pod が 0/3」を検知し、Pod のオブジェクトを3つ作る
│ (etcd に定義が保存されただけで、まだコンテナは動いていない。Node も未定)
│ ④ kube-scheduler が Node 未定の Pod を検知し、Node を選んで割り当てる
│ ⑤ 割り当てられた Node の kubelet が、自分の Node に来た Pod を検知する
▼
kubelet ──CRI──▶ container runtime: イメージを取得して、コンテナを起動
└──CNI──▶ CNI プラグイン: Pod に IP を割り当てる
│
│ ⑥ kubelet が Pod の状態(Running など)を kube-apiserver に報告し、etcd に保存される
▼
kubectl get pods で Running が見える
この流れから、次の点が読み取れる。
- どのコンポーネントも、相手に直接命令しない。kube-apiserver を通じて変化を受け取り、自分の担当範囲の差分を埋める形
- 「Pod のオブジェクトを作る」ことと「コンテナを起動する」ことは別の仕事。前者は ReplicaSet コントローラー(Control Plane)、後者は kubelet(Node)の担当
- 例外として、
kubectl logsでのログ取得、実行中の Pod への接続(attach)、ポートフォワードでは、kube-apiserver から kubelet に接続
同じ流れをシーケンス図にしたものは「Kubernetes の仕組みを図で整理する」にある。
Pod は Node 間を移動しない
Node が落ちると、そこにいた Pod の代わりが別の Node で動き出す。ただし、これは Pod の移動ではない。Pod がスケジュールされるのは一生に一度だけで、同じ Pod が別の Node に移ることはない。
公式ドキュメントでは、同じ Pod(UID で識別される)が別の Node に「再スケジュール」されることはなく、ほぼ同じ内容の新しい Pod に置き換えられる、と説明されている。
Node 1 が落ちる前:
Node 1: [api-abc(IP 10.244.1.5)]
Node 2: [api-def(IP 10.244.2.7)]
Node 1 が落ちた後:
Node 1: 停止。api-abc は削除される
Node 2: [api-def(IP 10.244.2.7)] [api-xyz(IP 10.244.2.9)] ← 新しく作られた別の Pod
(Pod の名前と IP は説明用に簡略化したもの)
- 新しい Pod は UID が別物で、IP アドレスも新しく割り当てられる
- Deployment などを使わずに Pod を単体で作ると、Node が落ちても代わりを作る担当がいない。そのため、Pod はコントローラー経由で管理するのが一般的
- 作り直されるたびに Pod の IP アドレスは変わる。Pod の IP に頼らない安定した宛先を用意する仕組みが Service
Node が落ちたときの流れ
コンテナがクラッシュしただけなら、Pod は削除されず、Kubernetes がそのコンテナの再起動を試みる。一方、Node そのものが落ちた場合は、次の流れで Pod が別の Node に作り直される(時間はいずれも既定値)。
kubelet のハートビート(Lease の更新)が途絶える
↓ 50 秒
Node コントローラーが Node の Ready を Unknown にし、unreachable の taint を付ける
↓ 5 分
taint-eviction コントローラーが、その Node の Pod を退避(削除)する
↓
ReplicaSet コントローラーが Pod の不足を検知し、新しい Pod を作る
↓
kube-scheduler が、正常な Node に新しい Pod を割り当てる
- 50 秒は、kube-controller-manager の
node-monitor-grace-periodの既定値 - 5 分は、Pod に自動で付く
tolerationSeconds=300(taint を許容する時間)によるもの。Pod ごとに変更も可能 - 通信が途絶えただけで Node 自体が動いている場合は、削除の決定が kubelet に届くまで、Pod がその Node で動き続けることもある
用語メモ
| 用語 | 読み方 | 意味 |
|---|---|---|
| Control Plane | コントロールプレーン | クラスタ全体を管理する部分 |
| kube-apiserver | キューブ・エーピーアイサーバー | Kubernetes API を公開するサーバー |
| etcd | エトシーディー | クラスタの全データを保存するキーバリューストア |
| kube-scheduler | キューブ・スケジューラー | Pod を動かす Node を選ぶ |
| kube-controller-manager | キューブ・コントローラー・マネージャー | コントローラーを実行する |
| kubelet | キューブレット | 各 Node で動くエージェント |
| kube-proxy | キューブ・プロキシ | Service の転送ルールを Node に設定する |
| CNI | シーエヌアイ | Container Network Interface |
| taint | テイント | Node に付ける、Pod の配置や退避に関わる印 |
| Quorum | クォーラム | 更新の確定に必要な過半数 |
まとめ
- Kubernetes のクラスタは、クラスタ全体を管理する Control Plane と、Pod を動かす Node で構成
- コンポーネント同士のやりとりはすべて kube-apiserver 経由で、クラスタの全データは etcd に保存
- Pod を置く Node の選択は kube-scheduler、調整ループは kube-controller-manager のコントローラーの担当
- Node では kubelet が container runtime を通じてコンテナを動かし、kube-proxy が Service の転送、CNI プラグインが Pod のネットワークを担当
- Pod は Node 間を移動せず、Node が落ちると別の Node に新しい Pod が作られる仕組み
参考 URL
- [official] Kubernetesのコンポーネント | Kubernetes
- [official] クラスターのアーキテクチャ | Kubernetes
- [official] Nodes | Kubernetes
- [official] Node Status | Kubernetes
- [official] コントローラー | Kubernetes
- [official] ノードとコントロールプレーン間の通信 | Kubernetes
- [official] Kubernetes APIへのアクセスコントロール | Kubernetes
- [official] Kubernetesのスケジューラー | Kubernetes
- [official] Taints and Tolerations | Kubernetes
- [official] Podのライフサイクル | Kubernetes
- [official] コンテナランタイムインターフェース(CRI) | Kubernetes
- [official] Virtual IPs and Service Proxies | Kubernetes
- [official] Service、負荷分散とネットワーク | Kubernetes
- [official] ネットワークプラグイン | Kubernetes
- [official] Kubernetes向けetcdクラスターの運用 | Kubernetes
- [official] kubeadmを使用したクラスターの作成 | Kubernetes
- [official] Implementation details | Kubernetes
- [official] FAQ | etcd

