多くの人はKubernetesの学び方を間違えている。Pod、Deployment、Service、Ingress、ConfigMap、Secret、HPA — これらを用語集のように暗記する。
それは逆だ。Kubernetesのすべての概念は、前の概念だけでは足りなかったから存在する。リストじゃない。本番環境で物が壊れていく物語だ。
Podはコンテナを実行する。シンプル。クリーン。完了。
クラッシュするまでは。誰もリスタートしない。ただ消える。本番環境では、それは許されない。
DeploymentはPodを監視する。1つ死んだら、もう1つ作る。3つ動かしたければ、3つ維持する。10にスケールしたければ、コマンド1つでできる。
Podは本番環境に脆すぎた。Deploymentがそれを解決した。
でも新しい問題が出る。Podはリスタートのたびに新しいIPを取得する。アプリで3つのPodが動いている。別のサービスがそれらと通信する必要がある。どのIPを使う?常に変わる。
Serviceはアプリに1つの安定したIPアドレスを与える。IPではなくラベルでPodを見つける。Podが死んで新しいIPで戻ってきてもServiceは気にしない。常に見つける。ヘルシーなPod全体にトラフィックを自動的にロードバランスもする。
Podには不安定なIPがあった。Serviceがそれを解決した。
でもアプリはインターネットからアクセス可能である必要がある。LoadBalancer Serviceを使うと、クラウドの実際のロードバランサー(AWS ALB、Azure LB、GCP LB)が作成される。パブリックエンドポイントが得られる。完璧に動く。
10のサービスができるまでは。10のロードバランサー。それぞれ毎月コストがかかる。トラフィックがほぼないものが6つあっても、クラウドの請求書は気にしない。
ロードバランサーは1つ。すべてのサービスがその後ろにある。Ingressはルールに基づいてトラフィックをルーティングする。/apiへのリクエストはAPIサービスへ。/dashboardへのリクエストはフロントエンドへ。1つのエントリーポイント。スマートなルーティング。請求書にはクラウドロードバランサーが1つだけ。
ただしIngressはルールの集合に過ぎない。それを実行する何か — Nginx、Traefik、AWS Load Balancer Controller — が必要だ。コントローラーのないIngressは、誰も読まない設定ファイルでしかない。
アプリには設定が必要だ。データベースURL。APIキー。環境名。フィーチャーフラグ。自然なことをする — コンテナの中にハードコードする。
ローカルでは動く。ステージングにデプロイ — データベースURLが違う。本番にデプロイ — APIキーが違う。設定が変わるたびにイメージをリビルドして修正する。
ConfigMapは設定をコンテナの外に保持する。ランタイムにPodに注入する。ConfigMapを変更して再デプロイ。イメージは変わらない。同じイメージがdev、staging、productionで異なる設定で動く。
でもデータベースのパスワードがConfigMapに入っている。ConfigMapは暗号化されていない。基本的なkubectlアクセスがあれば誰でも読める。これはミスじゃない — セキュリティインシデントだ。
Secretは機密データを別のアクセス制御で保持する。パスワード、トークン、証明書、APIキー。アプリはランタイムにそれらを読む。イメージはそれらを見ない。
トラフィックが増え始める。手動スケーリングが破綻する。ある日は100ユーザー、ある日は10,000。3つのPodで動いている。忙しい日には3つすべてが限界。ユーザーはレスポンスの遅延を感じる。
HPA(Horizontal Pod Autoscaler) はPodを継続的に監視する。CPUが70%を超えた?Podを追加する。トラフィックが減った?スケールダウンする。最小と最大を定義すれば、Kubernetesが残りをやる。
でもHPAはトラフィックスパイク時にPodを追加し、ノードが満杯になる。新しいPodはPending状態のまま。キャパシティがないのでスケジュールできない。
Cluster Autoscaler(EKSではKarpenter)はPending状態のPodを監視する。キャパシティ不足 — 自動的に新しいノードを追加。負荷が下がり、ノードが十分活用されていない — 自動的に削除。実際に必要なコンピュートにだけ支払う。
HPAがPodをスケールした。Karpenterがノードをスケールした。一緒にクラスターを真にエラスティックにする。
すべてがスケーリングしている。Podが立ち上がっている。ノードが追加されている。1つのPodが本来使うべきでない4GBのメモリを消費し始める。Kubernetesには誰も伝えていない。消費し続ける。そのノードの他のすべてのPodがスターブする。それらのPodが障害を起こし始める。カスケードが始まる。
RequestsはPodがスケジュールされるために必要な最小値をKubernetesに伝える。LimitsはPodが消費を許される最大値をKubernetesに伝える。クラスターは予測可能に動く。すべてのPodが必要なものを得る。それ以上はなし。
各概念は前の概念だけでは足りなかったから存在する:
これがKubernetesを暗記するのをやめ、理解し始める方法だ。すべての概念は本番環境の傷跡だ。
用語集を暗記するな。障害を理解しろ。
— blanho
Cloudflareは「あのCDN会社」からフルクラウドプラットフォームになった。ほとんどのスタートアップはまずそっちを見るべき。
APIゲートウェイは外部のカオスを処理する。サービスメッシュは内部のカオスを処理する。
ある時点から、評判がどこまで行けるかを決める。そして重要な評判を築くには何年もかかる。