Kubernetes

Kubernetesとは

Kubernetes(K8s)は、[[Docker]] などのコンテナを大量に運用するためのオーケストレーションツールです。「あるべき状態」を宣言しておくと、障害時の再起動・負荷に応じた増減・ローリングアップデートを自動で行います。

apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 3        # このアプリを常に3つ動かしておいて、という宣言

初学者向けポイント

  • 宣言的管理 = 「コンテナを3つ起動しろ」ではなく「常に3つある状態を保て」と書く。1つ落ちれば勝手に補充される
  • 宣言を書くマニフェストは [[YAML]]。インデントの深さがそのまま構造になるため、1段ずれても文法エラーにならず別の設定として読まれる
  • 基本単位は Pod(1つ以上のコンテナのまとまり)。Podを Deployment で管理し、Service で通信を振り分ける
  • 小規模なら過剰装備になりがち。まず [[Docker]] 単体やPaaSで十分かを検討するのが現実的

主要な概念

概念役割
Podコンテナの実行単位
DeploymentPodの数と更新方法の管理
ServicePodへのアクセス経路(ロードバランス)
Ingress外部からのHTTP(S)ルーティング

あるべき状態へ近づけ続ける仕組み

Kubernetes の中身は、現状と宣言を比べて差を埋めるループの集まりです。Deployment が管理する Pod を kubectl delete pod で消しても、数秒後に別の名前の Pod が現れます。消したのに増える、と戸惑いますが、宣言した replicas: 3 が守られているだけです。台数を本当に減らすときは、Pod ではなく宣言のほうを書き換えます。宣言を保持して配置先を決めるのがコントロールプレーン、各ノードでコンテナを起動し状態を報告するのが kubelet です。

メモリとCPUの割り当てを決める

資源の指定は初学者が最初に詰まる場所です。

resources:
  requests: { cpu: 200m, memory: 256Mi }  # 配置先を決める見積もり
  limits:   { cpu: 500m, memory: 512Mi }  # 超えてはいけない上限

requests は「置くならこれだけ空きが要る」という予約で、スケジューラは実際の使用量ではなくこの値をもとに空きを判断して配置先を選びます。limits は実行中の上限で、メモリと CPU では超えたときの挙動が違います

  • メモリが上限を超えると OOMKilled で即座に強制終了され、再起動されます。「数時間に1回勝手に再起動する」の典型的な原因です
  • CPU は超えても終了せず、割り当てを絞られて遅くなります。ノードに余裕があるのに応答だけ遅い、分かりにくい症状です

requests を書き忘れると1つのノードへ Pod が詰め込まれ、アクセス増で同居した Pod がまとめて不調になります。

起動直後と停止直前に事故が起きる

コンテナが「動いている」ことと「リクエストを受けられる」ことは別です。Kubernetes は2種類のプローブで区別します。

  • Readiness プローブ — 今リクエストを受けられるか。NGの間は Service の振り分け先から外れる(コンテナは止めない)
  • Liveness プローブ — 生きているか。NGが続くとコンテナを再起動する

取り違えると厄介です。起動に40秒かかるアプリの liveness を「10秒後から5秒間隔」にすると、初期化前に再起動され続け永久に立ち上がりません。

停止時は終了の合図(SIGTERM)が送られ、既定で30秒後に強制終了されます。無視すると処理中のリクエストが切られてエラーになります。合図を受けたら新規受付を止め、処理中を終えてから終了する — [[ロードバランサ]] のコネクションドレインと同じです。

最初に出会うエラーの読み方

kubectl get pods の STATUS 欄の文字列は原因の絞り込みにそのまま使えます。

表示起きていることまず疑う点
Pending配置先が決まらないrequests が大きすぎる、空きが無い
ImagePullBackOffイメージを取得できないタグの綴り、レジストリの認証
CrashLoopBackOff起動しては落ちる繰り返し環境変数や設定の不足
OOMKilledメモリの上限を超えたlimits と実際の使用量

kubectl describe pod <名前> でイベント欄、次に kubectl logs <名前>。再起動後は --previous落ちる直前のログを見ます。

導入するかどうかの判断

マネージドサービスで消えるのはコントロールプレーンの運用までで、マニフェスト設計・資源の見積もり・権限設定は残ります。数個のコンテナを固定台数で動かすだけなら [[サーバーレス・Lambda]] や PaaS で足ります。

次に読む記事の地図

Kubernetes は多くの技術が交わる場所です。近い群から選んでください。

中で動かすものを用意する — コンテナそのものは [[Docker]]、マニフェストに書くイメージの置き場は [[コンテナレジストリとイメージ管理]]。Kubernetes 自身も [[Go]] 製です。

外から中へつなぐ — Service と Ingress の一般論は [[ロードバランサ]]。ヘルスチェックの考え方はプローブに直結します。入口で認証まで担う発展形が [[APIゲートウェイ]]。

台数を増やし、落ちても止めない — なぜ増やすのかは [[スケーリング]]、1台の故障で止めない冗長化は [[高可用性設計]]。自動復旧とオートスケールはその自動化です。

止めずに入れ替える — 本番へ届ける流れは [[CI/CD]]、切り替え方式の比較は [[デプロイ戦略]]、クラスタ自体をコードで用意するのが [[IaC]]。

動き出してから中を見る — Pod は入れ替わるためログインして見る運用は成り立ちません。情報の集め方は [[オブザーバビリティ]]、異常の通知は [[監視とアラート]]。

何を載せ、何を渡すか — サービス群の設計は [[マイクロサービス]]、非同期の連携は [[メッセージキュー]]、鍵の配り方は [[シークレット管理]]、操作範囲を絞るのが [[最小権限の原則]]。

関連技術とのつながり

  • [[Docker]] — Kubernetesが管理する対象のコンテナ
  • [[コンテナレジストリとイメージ管理]] — Podが起動時にイメージを取り出す先
  • [[クラウドコンピューティング]] — マネージドK8s(EKS/GKE/AKSなど)として使うのが主流
  • [[Linux]] — ノード(実行マシン)のOS
  • [[CI/CD]] — デプロイ先としてK8sクラスタを使う構成が多い
Q: コンテナがメモリの limits を超えたときに起きることはどれ?
- [x] OOMKilled で強制終了され、再起動される
- [ ] 割り当てを絞られて動作が遅くなるだけで終了はしない
- [ ] 自動的に limits の値が引き上げられる
解説: メモリ超過は即座の強制終了(OOMKilled)になります。割り当てを絞られて遅くなるのはCPUのほうで、上限を超えても終了はしません。

Q: Deployment が管理している Pod を `kubectl delete pod` で消すとどうなる?
- [ ] その Pod が消えたまま台数が1つ減る
- [x] 宣言した台数を保つため、別の名前の Pod が作られる
- [ ] Deployment ごと削除される
解説: Kubernetes は現状と宣言の差を埋め続けます。台数を減らしたいときは Pod ではなく宣言のほうを書き換えます。

Q: Readiness プローブが NG になった Pod はどうなる?
- [ ] 直ちにコンテナが再起動される
- [x] Service の振り分け先から外れる(コンテナは止まらない)
- [ ] ノードごと別のマシンへ移動する
解説: 受け付けられるかを見るのが Readiness、生きているかを見て再起動するのが Liveness です。役割の取り違えが起動時の事故につながります。