目次
1 章

Kubernetes とは

なぜコンテナオーケストレーターが必要なのか。Docker / docker-compose まで触れてきた読者を出発点に、単一コンテナツールの5つの限界、宣言型 desired state + reconcile loop モデル、control plane / worker node の全体像、本書の範囲までを整理します。

本書の最初の章です。次の第2章から本格的に手を動かせるコマンドを扱います。本章ではコードを書く前に、なぜ Kubernetes なのか、本書が他の入門書とどう違うのか、そして第1章から第31章までの流れを整理します。

続いて出てくる4部 EKS 実戦、5部 運用・デバッグ・コスト、6部 フルスタックキャップストーンまでも、すべて本章の最後の節「本書が扱う範囲」の中に入っています。ですから本章は単なる「1部1章」を超えた道案内の役割を担います。ゆっくり追ってください。

Docker まで触れてきた読者へ #

本書は Docker / docker-compose まで手に馴染んだ読者を出発点に置きます。単一コンテナをビルドして起動し、データを保存する流れに慣れているなら、本章は自然に次の問いから始まります。

コンテナ1台は起動できる。それなら、コンテナ100台を、しかも死んだら自動で復活させ、トラフィックに応じて増やしたり減らしたりしながらどう運用するのか?

この問いに対する事実上の標準解答が Kubernetes (K8s) です。本章はその問いがなぜ自然なのか、そして K8s がどんなモデルでその問いに答えるのかを整理します。

Docker しか知らずに入ってきた方なら、本章を読み終えたあと 付録A docker-compose から k8s へ を先に開くと役立ちます。付録A は docker-compose.yml の各キーが k8s のどのリソースに対応するのかをマッピング表で整理した章です。本文が進むにつれて何度も見返すことになるはずです。

docker run だけでは足りなくなる瞬間 #

Docker の1コンテナ運用の代表例はこんな形です。

1コンテナ — Docker 段階の終わり
docker run -d --name myapp \
  --restart unless-stopped \
  -p 127.0.0.1:8000:8000 \
  -v myapp-data:/app/data \
  ghcr.io/curtis/myapp:1.0.0

ホスト1台にコンテナ1つ、または Compose で同じホストに web + db + cache をまとめる程度まではこれで十分です。しかしトラフィックが増え、無停止デプロイが求められ、サーバー1台が死んでもサービスは生きていなければならない段階が来ると、同じツールでは解決できない問題が出てきます。

1) ノード1台が死ぬとサービスも一緒に死にます。 docker run で起動したコンテナはそのホストに縛られています。ホストが再起動されたりディスクが壊れたりすると、コンテナを別のマシンに移す標準的な方法がありません。人が新しいマシンに SSH で入って同じコマンドを打ち直さなければなりません。

2) コンテナが死んだときの自動復旧が弱いです。 --restart unless-stopped は同じホストの中でだけ通用します。ホスト自体が生きていれば docker デーモンがコンテナを再起動しますが、ホストが死ぬとそこまでです。そして「プロセスは生きているのに応答できない」といった部分障害は捕まえられません。

3) インスタンス数をトラフィックに合わせて調節する作業がすべて手動です。 普段は2台で十分な API サーバーをキャンペーン時間の間だけ10台に増やすには、誰かが新しいマシンを用意し、同じイメージを取得して同じコマンドを10回実行したうえで、前段のロードバランサ設定まで手で変えなければなりません。終わったらまた減らします。手作業が多く必要です。

4) 無停止デプロイ (ローリングアップデート) を自分で組まなければなりません。 v1.0.0 から v1.1.0 へ移すとき、10台のうち1台ずつ新バージョンに置き換えながら、ヘルスチェックを通過したコンテナだけにトラフィックを送る流れは手で組むのが難しいです。失敗時の自動ロールバックまで含めるとさらに複雑です。

5) 設定・秘密の値・サービスディスカバリに標準がありません。 DB 接続情報を環境変数で渡さなければならないのですが、環境 (staging / prod) ごとに異なる値を安全に注入する標準的な方法が docker の基本ツールにはありません。コンテナ A がコンテナ B をどんな名前で見つけるか (サービスディスカバリ) も自分で決めなければなりません。

この5つが単一ホスト・単一コンテナ向けツールの限界です。そしてこの限界を解くのが コンテナオーケストレーター の役割です。

コンテナオーケストレーターが解く問題 #

上の5項目を一行に抽象化するとこうです。

複数のマシンを一塊 (クラスタ) にまとめ、「どんな形で動くべきか」だけを宣言すれば、システムが勝手にその形を維持してくれます。

これを呼ぶ名前が 宣言型 desired statereconcile loop (合わせ込みループ) です。

  • 宣言型 (declarative) — 「どう作るか (how)」ではなく 「何であるべきか (what)」 だけを書きます。例: 「myapp コンテナ3つが常に起動していなければならない」。
  • reconcile loop — システムが絶えず 現在の状態 (actual state) と 望む状態 (desired state) を比較し、差があればその差を縮める方向に動きます。コンテナ1つが死んで2つになったら、システムが勝手に1つ追加で起動して再び3つに合わせます。
reconcile loop の図
   ┌──────────────────┐         ┌──────────────────┐
   │  desired state   │         │   actual state   │
   │  "myapp 3 replicas"│ ◀───▶  │  現在起動中の2個 │
   └──────────────────┘ compare └──────────────────┘
                  │                       │
                  └────────┬──────────────┘
                    ┌─────────────┐
                    │  controller │  → 差 → "もう1個起動せよ"
                    └─────────────┘

このモデルが K8s の核心となる発想です。人は「こうなっていなければならない」だけを宣言し、その宣言を守り続ける作業はシステムが行います。ノードが1つ死んでも、新バージョンを段階的に転がしても、トラフィックに応じて5つを8つに増やしても — すべて同じモデルで解決できます。

本書では第4章 Deployment と ReplicaSet で reconcile loop が実際のリソースの上でどう動作するのかを直接見て、第18章 CRD と Operator パターン で同じモデルをユーザー定義リソースに拡張する方法を扱います。

Kubernetes はどこから来たのか #

このモデルは K8s が最初に作ったものではありません。Google が社内で10年以上運用していた Borg というクラスタ管理システムがその根です。Google の検索・Gmail・マップといったサービスは Borg の上で運用され、その経験を基に次世代システムである Omega が生まれました。その後、その発想をオープンソースとして再実装したものが Kubernetes です。

おおまかな流れは次の通りです。

  • 2014年6月 — Google が Kubernetes の初期バージョンをオープンソースとして公開しました。
  • 2015年7月 — Kubernetes 1.0 がリリースされ、同じ時点で CNCF (Cloud Native Computing Foundation) が発足し、K8s が最初のプロジェクトとして寄贈されました。
  • それ以降 — 主要なクラウド事業者 (AWS EKS、GCP GKE、Azure AKS) がすべてマネージド K8s を提供したことで、事実上コンテナオーケストレーションの標準になりました。

「Kubernetes」はギリシャ語で舵取り (helmsman) を意味します。略語の K8s は K と s の間の8文字を縮めて書いたものです。両方の表記はよく混ぜて使われ、同じ対象を指します。

本書は執筆時点を基準に Kubernetes 1.32 を標準に置きます。一部の deprecated API と新規 GA 機能が登場するたびに該当章で明示します。

K8s クラスタの全体像 #

K8s クラスタは2種類のノードで構成されます — control planeworker node です。

K8s クラスタ — コンポーネントを一目で
                ┌───────────────────────────────────┐
                │           Control Plane            │
                │                                    │
   kubectl ───▶ │   kube-apiserver  ◀──────┐         │
                │        │                 │         │
                │        ▼                 │         │
                │       etcd               │         │
                │                          │         │
                │   kube-scheduler  ───────┤         │
                │   kube-controller-manager ─┤       │
                │   cloud-controller-manager ┘       │
                └────────────┬───────────────────────┘
        ┌────────────────────┼────────────────────┐
        ▼                    ▼                    ▼
 ┌────────────────┐  ┌────────────────┐  ┌────────────────┐
 │  Worker Node 1 │  │  Worker Node 2 │  │  Worker Node 3 │
 │                │  │                │  │                │
 │   kubelet      │  │   kubelet      │  │   kubelet      │
 │   kube-proxy   │  │   kube-proxy   │  │   kube-proxy   │
 │   containerd   │  │   containerd   │  │   containerd   │
 │                │  │                │  │                │
 │   ┌──────┐     │  │   ┌──────┐     │  │   ┌──────┐     │
 │   │ Pod  │ ... │  │   │ Pod  │ ... │  │   │ Pod  │ ... │
 │   └──────┘     │  │   └──────┘     │  │   └──────┘     │
 └────────────────┘  └────────────────┘  └────────────────┘

Control plane — クラスタの脳 #

control plane はクラスタの desired state を受け取って保管し、その状態が実際に維持されるよう決定を下す部分です。

  • kube-apiserver — クラスタの正門。kubectl をはじめとするすべてのツールはこの API サーバーに REST でリクエストを送ります。認証・認可・検証を経たうえで結果を etcd に記録します。
  • etcd — クラスタのすべての状態 (どの Pod がどこにあるべきか、どの Service が定義されているか など) を保管する分散キー・バリューストア。クラスタの単一の信頼できる情報源 (source of truth) です。
  • kube-scheduler — 新しく作られた Pod に「どの worker node に行くか」を決めてあげます。ノードの利用可能リソース、ラベル、制約条件を見て決定します。
  • kube-controller-manager — 複数のコントローラを1つのプロセスにまとめて動かします。上で見た reconcile loop を実際に実行する主体です。例: ReplicaSet コントローラは「Pod 3つが起動していなければならない」という宣言と実際に起動している数を絶えず比較します。
  • cloud-controller-manager — クラウド (AWS / GCP / Azure など) の上に乗ったクラスタで、そのクラウドのロードバランサ・ディスク・ノードといったリソースを K8s リソースへ対応づけてくれます。自前のデータセンターに乗せたクラスタにはないことがあります。

Worker node — 仕事をする場所 #

worker node は実際にコンテナが実行されるマシンです。普通はノード1台に次の3つがインストールされています。

  • kubelet — ノードのエージェント。apiserver から「このノードにこの Pod を起動せよ」という指示を受け、コンテナランタイムに実際の実行を要求します。コンテナのヘルスを見守り、状態を再び apiserver に報告する作業も行います。
  • kube-proxy — ノードのネットワークルール (iptables / IPVS など) を管理し、Service (第5章) の仮想 IP が実際の Pod に届くようにします。
  • コンテナランタイム — 実際にコンテナを実行する層。現在の標準は containerd で、CRI-O もよく使われます。かつて K8s が docker デーモンを直接使っていたアダプタ (dockershim) は Kubernetes 1.24 (2022) から 削除されました。ですから「K8s が docker を使う」という言い方はもう正確ではありません。K8s は OCI 互換ランタイムを使い、docker が作ったイメージ (OCI イメージ) はそのまま動作します。

流れを一度に #

kubectl apply -f deployment.yaml を打った瞬間に起きることを縮めるとこうです。

  1. kubectl が apiserver に「この Deployment があるべきだ」というリクエストを送ります。
  2. apiserver が認証・検証後、その事実を etcd に記録します。
  3. controller-manager の中の Deployment コントローラが「Pod 3つがさらに必要だ」と判断して Pod オブジェクトを3つ作ります。
  4. scheduler がその Pod それぞれにノードを割り当てます。
  5. 該当ノードの kubelet がその情報を見て containerd にコンテナの実行を指示します。
  6. kubelet が結果を再び apiserver に報告し、ユーザーは kubectl get pods でその状態を確認できます。

全体が apiserver を経て etcd に書き込まれた desired state を、各コンポーネントが自分の領域で reconcile する という1つのパターンで流れます。本書では第3章 kubectl と最初の Pod で上の流れを直接手で追ってみます。

核心リソースを一表で #

K8s で人が扱う単位は コンテナではなくリソース (resource, object) です。Pod、Deployment、Service といった名前です。次の章から1つずつ深く扱いますが、あらかじめ一表で形をつかんでおきます。

リソース一行定義扱う章
Podコンテナ1個または一緒に動作する数個をまとめた K8s の最小実行単位。IP を共有する第3章
ReplicaSet「この Pod テンプレートが N 個起動していなければならない」を保証第4章
DeploymentReplicaSet の上でローリングアップデート・ロールバックを扱う上位リソース。人が最もよく触る単位第4章
Service複数の Pod の前段に安定した仮想 IP / DNS 名を付けてくれるネットワーク抽象第5章
ConfigMap設定値 (環境変数、設定ファイル) をコードと分離して注入第6章
Secret秘密の値 (パスワード、トークン、証明書) を分離して注入。base64 エンコード + アクセス制御第6章
Namespaceクラスタ内部の論理区画。権限・リソース上限・名前衝突を分離第7章

この7つを手に馴染ませれば、日常的に扱う作業のかなりの部分を処理できます。より深いリソース (StatefulSet、PV / PVC、Ingress、RBAC、CRD など) は2部 ~ 3部で続けて扱います。

Docker Compose と何が違うのか #

Docker まで触れてきた読者に最初に思い浮かぶ比較対象は Docker Compose です。Compose も YAML 1ファイルに複数のコンテナを宣言的に定義するという点で K8s と似ているからです。しかし両者は解く問題の範囲が異なります。

Docker ComposeKubernetes
扱う範囲単一ホスト の中のマルチコンテナ複数ノード (クラスタ) の上のコンテナのまとまり
自己復旧同じホストでの再起動程度ノードが死んでも別のノードへ自動移転
スケーリング--scale で手動desired state で宣言 → 自動維持、オートスケーリング可能
無停止デプロイ自分で組まなければならないDeployment のローリングアップデートが標準
設定 / 秘密.envsecrets 程度ConfigMap / Secret が一級リソース
適した場所ローカル開発、単一サーバー運用複数マシン上の運用 / 本格的な SLA 環境

Compose は単一ホストの開発・運用を単純にするツールで、K8s はその限界を超える運用環境で使われます。両者は競合関係というより 異なる段階の問題 を解きます。ローカル開発は今でも Compose が軽く、本番運用は K8s またはそのマネージドサービスが自然です。

この表の各行が k8s リソースへどう移されるかについての詳しいマッピングは 付録A docker-compose から k8s へ に整理されています。Docker / docker-compose のメンタルモデルに慣れている方は、本文を読みながら付録A をそばに置いておくと、各章の新しいリソースが Compose のどのキーに対応するのかを素早くつかめます。

本書が扱う範囲 #

K8s は広いテーマです。本書の32章でどこまで扱うかをあらかじめ決めておきます。

扱う内容
1部Kubernetes をはじめる — Pod・Deployment・Service・ConfigMap / Secret・Namespace1 ~ 7
2部ワークロードと運用 — StatefulSet・PV / PVC・Ingress・resources・ヘルスチェック・オートスケーリング・RBAC8 ~ 14
3部深さ — CNI・RBAC の深層・Admission Controller・CRD / Operator・可観測性・GitOps15 ~ 20
4部EKS 実戦 — クラスタセットアップ・アプリ配備の骨格・RDS 連携・CI / CD・モニタリング・運用チェックリスト21 ~ 26
5部運用・デバッグ・コスト — kubectl デバッグ・コスト最適化・シークレット運用・アップグレード戦略27 ~ 30
6部総合実習 — フルスタックアプリ EKS 配備 (Next.js + FastAPI + RDS + GitOps + 可観測性)31
付録docker-compose から k8s へ — マッピング表 + よく詰まる7つの差A

本書をすべて終えたあとには次のことが手に入ります。

  • Pod / Deployment / Service / ConfigMap / Secret / Namespace で小さなアプリを K8s 流に配備できます。
  • StatefulSet・PV / PVC・Ingress・ヘルスチェック・オートスケーリング・RBAC まで、ワークロード運用の一連の流れを身につけられます。
  • Prometheus / Grafana / Loki / OpenTelemetry で可観測性を、ArgoCD / Flux で GitOps を導入できます。
  • AWS EKS 上に本番ワークロードの一連の流れ (クラスタセットアップ・アプリ配備・DB 連携・CI / CD・モニタリング・運用チェックリスト) を運用できます。
  • CrashLoopBackOff・OOMKilled・ImagePullBackOff・Pending といったよくある障害を診断できます。
  • Karpenter + Spot + bin packing でクラスタコストを最適化できます。
  • シークレットを sealed-secrets・external-secrets・IRSA パターンで運用できます。
  • コントロールプレーンとノードのアップグレードサイクルを安全にたどれます。
  • modern-react の Next.js アプリと modern-python の FastAPI アプリを1つの EKS クラスタに配備できます。

扱わない部分は次のように整理しておきます。

テーマ場所
Helm チャート作成法の深さ・ArgoCD ApplicationSet パターン・Cilium eBPF データプレーンの深さ後続の K8s 深掘り本
マルチクラスタフェデレーション・サービスメッシュ (Istio / Linkerd)後続の K8s 深掘り本
EKS 以外の他のマネージド (GKE / AKS) ごとの差別途の付録または別冊
Kubernetes へのコントリビューション・kubelet 内部・etcd 運用の深さ別の本

本書は「使い方」までの範囲です。「作り方」の領域は後続の K8s 深掘り本で扱います。

練習問題 #

  1. ご自身が現在運用している、または知っている Docker / docker-compose 環境で、§「docker run だけでは足りなくなる瞬間」の5つの限界のうちどの項目に最初にぶつかる可能性が高いかを一段落で書いておいてください。本書を読み終えたあと再び見たとき、その項目が K8s のどのリソースやパターンで解消されるのかを確認するのに使います。
  2. kubectl apply -f deployment.yaml の流れの6ステップを見ずに書いてみてください。詰まるステップがあれば、control plane の5つのコンポーネント (apiserver・etcd・scheduler・controller-manager・cloud-controller-manager) のうち誰がそのステップを担当するのかを併せてメモしておいてください。第4章 Deployment と ReplicaSet で同じ流れを直接手で追っていくことになります。
  3. ご自身がすでに知っている docker-compose 構成 (小さな web + db のような) を1つ選び、本章 §「Docker Compose と何が違うのか」の表の各行がその構成にどう適用されるかを一行ずつメモしておいてください。付録A docker-compose から k8s へ を読むときの出発点になります。

一行まとめ: Kubernetes は複数のマシンを1つのクラスタにまとめ、desired state + reconcile loop モデルでコンテナを運用する事実上の標準です。クラスタは control plane + worker node に分かれ、人が扱う単位は Pod / Deployment / Service / ConfigMap / Secret / Namespace といったリソースです。Docker Compose は単一ホスト、Kubernetes は複数ノードを扱います。

次の章 #

次の 第2章 ローカル環境 では、minikube / kind / Docker Desktop k8s の3つのローカルクラスタオプションのうちどれをどんな場合に選ぶか、kubectl のインストールと最初のコンテキスト切り替え、そして kubectl get nodes で最初のクラスタを確認する手順までを扱います。ローカルクラスタを用意したあと 第3章 kubectl と最初の Pod へ進みます。

X