テックカリキュラム

Chapter 5:Kubernetes内部構造・コンテナオーケストレーション高度設計

本章では、Kubernetesを単なる「コンテナを動かすツール」としてではなく、 分散システム、宣言的API、Control Loop、Scheduler、Service Discovery、 Software Defined Networking、分散ストレージ、障害検知などを統合した コンテナオーケストレーション基盤として理解する。

Pod、Deployment、Serviceといったリソースの使い方だけではなく、 API Server、etcd、Scheduler、Controller Manager、kubelet、 Container Runtime、CNI、CSIなどの内部コンポーネントが どのように協調してクラスタ状態を維持しているのかを学ぶ。

本章のゴールは、 「Podが起動しない」「通信できない」「再起動を繰り返す」 「特定Nodeだけ異常に負荷が高い」といった問題を、 Kubernetes内部構造から体系的に解析できるようになることである。


1. Kubernetesは何を解決するのか

コンテナを数個動かすだけであれば、 単一ホスト上でも管理できる。

しかし数百・数千のコンテナを複数サーバへ配置すると、 以下の問題が発生する。

  • どのサーバへコンテナを配置するか
  • 障害コンテナをどう再起動するか
  • サーバ障害時にどう再配置するか
  • サービス間通信をどう管理するか
  • 負荷に応じてどうスケールするか
  • 設定情報やSecretをどう配布するか
  • ストレージをどう割り当てるか
  • ローリングアップデートをどう実現するか

Kubernetesはこれらをクラスタ全体で管理する。


                Kubernetes Cluster

        +----------------------------+
        |        Control Plane       |
        +----------------------------+
                    |
         -----------------------
         |          |          |
         v          v          v
      Node A      Node B      Node C
      Pod Pod     Pod Pod     Pod Pod

2. Control PlaneとWorker Node

Kubernetesクラスタは大きくControl PlaneとWorker Nodeに分かれる。

■ Control Plane

クラスタ全体のDesired Stateを管理する。

  • kube-apiserver
  • etcd
  • kube-scheduler
  • kube-controller-manager

■ Worker Node

実際にWorkloadを実行する。

  • kubelet
  • Container Runtime
  • ネットワーク関連コンポーネント
  • Pod

Control Plane
      |
      |
      v
+------------------+
|   Worker Node    |
|                  |
| kubelet          |
| Runtime          |
|                  |
| Pod A   Pod B    |
+------------------+

3. kube-apiserver

kube-apiserverは、 Kubernetes Control Planeの中心となるコンポーネントである。


kubectl
   |
   v
API Server
   |
   +------> etcd
   |
   +------> Scheduler
   |
   +------> Controllers
   |
   +------> kubelet

Kubernetesの各コンポーネントは、 基本的にAPI Serverを通じてクラスタ状態を読み書きする。

API Serverでは以下の処理が関係する。

  • Authentication
  • Authorization
  • Admission Control
  • API Validation
  • Resource Version管理
  • etcdへの永続化

Kubernetesを理解する上では、 API Serverが単なるkubectlの受付窓口ではなく、 クラスタ状態変更の中心点であることが重要となる。


4. etcd

etcdはKubernetesクラスタの状態を保存する分散Key-Value Storeである。

以下のような情報が保存される。

  • Pod
  • Deployment
  • Service
  • ConfigMap
  • Secret
  • Node情報
  • クラスタ設定

API Server
    |
    v
+-------------------+
|       etcd        |
|                   |
| Cluster State     |
| Desired State     |
| Metadata          |
+-------------------+

etcdは分散Consensusを利用して状態を管理する。

そのため前章までに学んだ以下の概念が、 Kubernetes内部でも直接関係する。

  • Leader Election
  • Quorum
  • Consensus
  • Replication
  • Network Partition

5. Kubernetesの宣言的モデル

Kubernetesでは、 「コンテナを3個起動する」という命令ではなく、 「3個存在してほしい」というDesired Stateを宣言する。


spec:
  replicas: 3

現在2Podしか存在しなければ、 KubernetesはDesired Stateとの差分を検出する。


Desired State = 3 Pods

Current State = 2 Pods

        ↓

Difference = 1 Pod

        ↓

Create Pod

        ↓

Current State = 3 Pods

このDesired StateとCurrent Stateの差を継続的に修正する考え方が、 Kubernetesの中心思想である。


6. Reconciliation Loop

Kubernetes Controllerは、 Desired StateとCurrent Stateを継続的に比較する。


Observe Current State
        |
        v
Compare Desired State
        |
        v
Difference?
   /         \
 YES          NO
  |            |
  v            |
Take Action    |
  |            |
  +------------+
        |
        v
Repeat

この処理をReconciliation LoopまたはControl Loopという。

Kubernetesでは一度の命令で状態を完成させるのではなく、 継続的な収束によってDesired Stateへ近づける。

これは分散システムにおけるEventual Convergenceの考え方とも密接に関係する。


7. Controller Manager

kube-controller-managerでは、 複数のControllerがクラスタ状態を監視する。

代表的なControllerには以下がある。

  • Deployment Controller
  • ReplicaSet Controller
  • Node Controller
  • Job Controller
  • Endpoint関連Controller

例えばReplicaSet Controllerは、 指定されたReplica数と実際のPod数を比較する。


Desired Replicas = 5

Current Pods = 4

        ↓

ReplicaSet Controller

        ↓

Create 1 Pod

各Controllerが自分の担当するResource状態を収束させることで、 クラスタ全体が維持される。


8. Deployment・ReplicaSet・Podの関係

Deploymentを作成すると、 内部ではReplicaSetが管理され、 ReplicaSetがPodを管理する。


Deployment
    |
    v
ReplicaSet
    |
    +------> Pod A
    |
    +------> Pod B
    |
    +------> Pod C

Deploymentは主に以下を管理する。

  • Replica数
  • Rolling Update
  • Rollback
  • Pod Template

Podを直接大量に作成するのではなく、 上位Controllerを通じて管理することが基本となる。


9. Podは「コンテナ」ではない

PodはKubernetesにおける最小のScheduling Unitである。

1つのPodには複数Containerを配置できる。


Pod
+---------------------------+
|                           |
| Application Container     |
|                           |
| Sidecar Container         |
|                           |
+---------------------------+

Shared:
- Network Namespace
- IP Address
- Volumes

同一Pod内のContainerはNetwork Namespaceを共有するため、 localhost経由で通信できる。

Podを単なるContainerの別名として理解すると、 Kubernetesの設計を誤りやすい。


10. Sidecar Pattern

同一Pod内へ補助Containerを配置する設計をSidecar Patternという。


Pod
+---------------------------+
|                           |
| Application               |
|      |                    |
|      v                    |
| Sidecar                   |
|                           |
+---------------------------+

Sidecarには以下の用途がある。

  • Proxy
  • ログ転送
  • 監視
  • 設定同期
  • セキュリティ補助

ただしSidecarを増やすと、 PodごとのCPU・Memory消費や運用複雑性も増加する。


11. Pod作成時に内部で何が起きるのか

Podを作成したときの内部処理を追跡する。


kubectl apply
      |
      v
API Server
      |
      v
etcd
      |
      v
Scheduler
      |
      v
Node Selected
      |
      v
kubelet
      |
      v
Container Runtime
      |
      v
Container Start
  1. ManifestをAPI Serverへ送信する
  2. 認証・認可・Admission処理が実行される
  3. Resourceがetcdへ保存される
  4. Schedulerが未配置Podを検出する
  5. 適切なNodeを選択する
  6. 対象NodeのkubeletがPodを検出する
  7. Container RuntimeへContainer作成を依頼する
  8. ネットワークを構成する
  9. VolumeをMountする
  10. Containerを起動する
  11. StatusがAPI Serverへ報告される

Pod起動障害では、 この処理のどこで停止しているのかを特定することが重要となる。


12. kube-scheduler

Schedulerは、 未配置PodをどのNodeへ配置するか決定する。


Pending Pod
    |
    v
Scheduler
    |
    +------ Node A
    |
    +------ Node B
    |
    +------ Node C
            |
            v
       Best Candidate

Schedulingでは概念的に、 配置不可能なNodeを除外した後、 候補Nodeを評価して配置先を決定する。

■ Filtering

Podを配置できないNodeを除外する。

■ Scoring

配置可能なNodeを評価し、 適切なNodeを選択する。


13. Resource RequestsとLimits

KubernetesではPodごとにCPU・MemoryのRequestsとLimitsを設定できる。


resources:
  requests:
    cpu: "500m"
    memory: "512Mi"
  limits:
    cpu: "1"
    memory: "1Gi"

■ Requests

SchedulerがNode配置を判断するときに重要となるリソース要求量である。

■ Limits

Containerが利用できるリソース量の上限を制御する。

Requestsを実際の利用量より極端に大きくすると、 クラスタ全体に余裕があるように見えてもPodを配置できない場合がある。

逆にRequestsが小さすぎると、 多数Podが同じNodeへ配置されて実際の負荷が集中する可能性がある。


14. CPU LimitとThrottling

CPU Limitを超えてCPUを利用しようとしたContainerは、 CPU使用を制限される。


Application wants:

CPU ███████████████████

Limit:

CPU ██████████

        ↓

Throttling

この状態をCPU Throttlingという。

CPU使用率がLimit付近に張り付いていなくても、 短時間のBurstが抑制されることでLatencyが悪化する場合がある。

「Node CPUには余裕があるのにPodが遅い」という場合、 CPU Throttlingを確認する必要がある。


15. Memory LimitとOOMKill

ContainerがMemory Limitを超えると、 OOM(Out Of Memory)によって終了する場合がある。


Memory Usage
     |
     |      Limit
     |--------X
     |        |
     |        v
     |     OOMKill

KubernetesではPodの状態やContainerの終了理由から OOMKilledを確認できる。


kubectl describe pod <pod-name>

OOMKillが発生した場合には、 単純にMemory Limitを増加するだけでなく、 Memory Leak、Heap Size、Cache、Concurrencyなども調査する必要がある。


16. QoS Class

KubernetesではRequestsとLimitsの設定に応じて、 PodへQoS Classが割り当てられる。

  • Guaranteed
  • Burstable
  • BestEffort

NodeのMemoryが逼迫した場合など、 Podの退避・終了判断にQoSが関係する。

重要Workloadでは、 単にLimitを設定するだけではなく、 Node障害時・Memory Pressure時にどのPodを守るのかまで考える必要がある。


17. kubelet

kubeletは各Worker Node上で動作し、 Node上のPodをDesired Stateへ近づける役割を持つ。


API Server
    |
    v
kubelet
    |
    +------> Container Runtime
    |
    +------> Volume
    |
    +------> Health Check
    |
    +------> Pod Status

kubeletはSchedulerではない。

Schedulerが「どのNodeへ配置するか」を決定し、 kubeletが「そのNode上で実際にPodを動作させる」。


18. Container RuntimeとCRI

Kubernetes自身が直接Linux Containerを作成しているわけではない。

kubeletはCRI(Container Runtime Interface)を通じて、 Container Runtimeへ処理を依頼する。


kubelet
   |
   | CRI
   v
Container Runtime
   |
   v
OCI Runtime
   |
   v
Linux Kernel

Container RuntimeとKubernetesを疎結合にすることで、 標準インターフェースを通じてRuntimeを利用できる。


19. ContainerとLinux Namespace

Container Isolationは、 Linux KernelのNamespaceなどによって実現される。

代表的なNamespaceには以下がある。

  • PID Namespace
  • Network Namespace
  • Mount Namespace
  • UTS Namespace
  • IPC Namespace
  • User Namespace

Containerは完全な独立OSではなく、 同じLinux Kernelを共有しながらリソースを分離している。


20. cgroupsとリソース制御

CPUやMemoryなどのリソース制御には、 Linuxのcgroupsが利用される。


Linux Host
    |
    +------ cgroup A
    |        CPU
    |        Memory
    |
    +------ cgroup B
             CPU
             Memory

KubernetesのRequests / Limitsを深く理解するためには、 最終的にLinux KernelのResource Controlへ到達することが重要である。


21. Kubernetes Networking Model

Kubernetesでは基本的に各Podが独自IPアドレスを持つ。


Node A

Pod A
10.10.1.10

Pod B
10.10.1.11


Node B

Pod C
10.10.2.10

異なるNode上のPod同士でも通信できるネットワークを構成する必要がある。

このPod Networkの実装にはCNIが関係する。


22. CNI

CNI(Container Network Interface)は、 Container Networkを構成するための標準仕様である。


Pod Creation
     |
     v
kubelet
     |
     v
Container Runtime
     |
     v
CNI Plugin
     |
     +------ Network Interface
     |
     +------ IP Address
     |
     +------ Routing

CNI実装によって具体的なネットワーク方式は異なる。

Pod間通信障害では、 アプリケーションだけではなく以下まで確認する必要がある。

  • Pod IP
  • Network Namespace
  • Route
  • Interface
  • CNI状態
  • Network Policy

23. Service

Podは再作成されるとIPアドレスが変化する可能性がある。

そのためPod IPへ直接依存すると、 安定したサービス通信を実現しにくい。

ServiceはPod集合に対する安定したアクセス先を提供する。


Client
   |
   v
Service
   |
   +------> Pod A
   |
   +------> Pod B
   |
   +------> Pod C

ServiceはLabel Selectorなどを利用して、 対象Podを関連付ける。


24. Service DiscoveryとDNS

Kubernetesクラスタ内部では、 Service名を利用した名前解決が可能である。


Application

http://payment-service

        |
        v

Cluster DNS

        |
        v

Service

        |
        v

Pod

サービス間通信障害では、 TCP接続だけでなくCluster DNSも重要な調査対象となる。

大量の名前解決やDNS障害によって、 アプリケーションLatencyが悪化することもある。


25. EndpointSlice

Serviceが実際に通信を転送するPod群は、 EndpointSliceなどによって管理される。


Service
   |
   v
EndpointSlice
   |
   +------> Pod A IP
   |
   +------> Pod B IP
   |
   +------> Pod C IP

Serviceが存在していても、 Endpointが存在しなければバックエンドへ通信できない。

そのためService障害では以下を確認する。

  • Service Selector
  • Pod Label
  • Pod Ready状態
  • EndpointSlice
  • Target Port

26. kube-proxyとService通信

KubernetesのService通信では、 環境によってkube-proxyがServiceの仮想IPとバックエンドPod間の転送ルールを管理する。


Client Pod
    |
    v
Service IP
    |
    v
Packet Processing
    |
    +------> Pod A
    |
    +------> Pod B

実装方式によってiptablesやIPVSなどが利用される。

さらに一部のネットワーク実装では、 eBPFを利用してService処理を実装する場合もある。


27. NetworkPolicy

NetworkPolicyは、 Pod間通信を制御するための仕組みである。


Frontend
   |
   | ALLOW
   v
Backend
   |
   | ALLOW
   v
Database


Unknown Pod
   |
   X DENY
   |
Database

NetworkPolicyを利用することで、 クラスタ内部でも必要な通信だけを許可する設計が可能になる。

ただし実際のPolicy Enforcementは、 利用しているネットワーク実装の対応状況にも依存する。


28. Ingressと外部トラフィック

外部からHTTP / HTTPS通信をクラスタ内部へルーティングする場合、 Ingressなどの仕組みが利用される。


Internet
   |
   v
External Load Balancer
   |
   v
Ingress Controller
   |
   v
Service
   |
   v
Pods

Ingress Resourceはルーティングルールを宣言し、 Ingress Controllerが実際の通信処理を担う。

外部アクセス障害では、 IngressだけでなくLoad Balancer、DNS、TLS、Service、Endpoint、Podまで End-to-Endで確認する必要がある。


29. Liveness Probe

Liveness Probeは、 Containerが正常に生存しているかを確認する。

一定回数Probeに失敗すると、 kubeletがContainerを再起動する場合がある。


Application
    |
Liveness Probe
    |
    +---- Success → Continue
    |
    +---- Failure → Restart

Liveness Probeへ重いDB Queryなどを設定すると、 一時的な依存先障害によって大量Podが再起動する危険がある。

Livenessは「このプロセスを再起動しなければ復旧できないか」 という観点で設計する必要がある。


30. Readiness Probe

Readiness Probeは、 Podがトラフィックを受け取れる状態かを判定する。


Pod
 |
Readiness
 |
 +---- Ready
 |       |
 |       v
 |    Service Traffic
 |
 +---- Not Ready
         |
         X
      Traffic

Readinessに失敗したPodは、 通常Serviceの通信対象から外される。

LivenessとReadinessは目的が異なるため、 同じProbeを無条件に設定するべきではない。


31. Startup Probe

起動に時間がかかるApplicationでは、 Startup Probeを利用できる。


Container Start
      |
      v
Startup Probe
      |
      +---- Waiting
      |
      +---- Success
               |
               v
        Liveness / Readiness

Startup Probeによって、 起動途中のApplicationがLiveness Probeによって繰り返しKillされる問題を防止できる。


32. CrashLoopBackOff

Containerが起動後すぐに終了し続けると、 CrashLoopBackOff状態になる場合がある。


Start
  |
  v
Crash
  |
  v
Restart
  |
  v
Crash
  |
  v
Backoff
  |
  v
Restart

調査では以下を確認する。


kubectl describe pod <pod-name>

kubectl logs <pod-name>

kubectl logs <pod-name> --previous

特に–previousを利用すると、 直前に終了したContainerのログを確認できる場合がある。

■ 代表的原因

  • Application Error
  • 設定ミス
  • Secret不足
  • Dependency接続失敗
  • OOMKilled
  • Liveness Probe失敗

33. Pending Pod

PodがPendingのまま起動しない場合、 Container以前の問題である可能性がある。

■ 代表的原因

  • CPU Requestsを満たすNodeがない
  • Memory Requestsを満たすNodeがない
  • Node Selector条件を満たせない
  • Affinity条件を満たせない
  • Taint / Tolerationが一致しない
  • Persistent Volumeを割り当てられない
  • Scheduler制約

この場合Application Logを確認しても、 Container自体がまだ起動していないため原因を発見できない。


34. Node SelectorとNode Affinity

特定条件を持つNodeへPodを配置したい場合、 Node SelectorやNode Affinityを利用できる。


Node A
disk=ssd

Node B
disk=hdd

Pod
requires disk=ssd

        ↓

      Node A

Affinityを利用すると、 より柔軟なScheduling条件を定義できる。

ただし条件を厳しくしすぎると、 クラスタに空きリソースが存在していてもPodを配置できなくなる。


35. Pod AffinityとAnti-Affinity

Pod同士の位置関係を制御することもできる。

■ Pod Affinity

関連するPodを近いTopologyへ配置する。

■ Pod Anti-Affinity

同じ種類のPodを異なるNodeなどへ分散する。


Node A
  Web Pod 1

Node B
  Web Pod 2

Node C
  Web Pod 3

高可用性を目的とする場合、 Replicaを同じNodeへ集中させない設計が重要となる。


36. TaintsとTolerations

Taintは、 特定Nodeへ通常Podを配置しないための制約として利用される。


Node
Taint = dedicated=gpu

        X

Normal Pod


GPU Pod
Toleration = dedicated=gpu

        ↓

      Node

専用Nodeや特殊Workloadの分離などに利用できる。


37. Topology Spread Constraints

高可用性を考える場合、 Podを複数のTopologyへ分散させる必要がある。


Zone A
Pod 1
Pod 2

Zone B
Pod 3
Pod 4

Zone C
Pod 5
Pod 6

同一Nodeだけでなく、 Rack・ZoneなどのFailure Domainを意識して配置することが重要となる。

Replica数だけ増やしても、 すべて同じFailure Domainへ配置されていれば障害耐性は向上しない。


38. Rolling Update

Deploymentでは、 サービスを継続しながら新Versionへ段階的に更新できる。


Old Version

v1 v1 v1 v1

      ↓

v2 v1 v1 v1

      ↓

v2 v2 v1 v1

      ↓

v2 v2 v2 v1

      ↓

v2 v2 v2 v2

Rolling Updateでは以下の値が重要となる。

  • maxUnavailable
  • maxSurge
  • Readiness Probe
  • Termination Grace Period

新VersionがReadyになる前に旧Versionを大量停止すると、 サービス容量が不足する可能性がある。


39. Graceful Shutdown

Pod終了時には、 実行中リクエストを安全に完了させる必要がある。


Pod Termination
      |
      v
SIGTERM
      |
      v
Stop Accepting New Requests
      |
      v
Finish In-Flight Requests
      |
      v
Process Exit

Graceful Shutdownを実装していない場合、 Rolling Updateだけでユーザーリクエストが失敗する可能性がある。

Application・Readiness・Load Balancing・Termination処理を一体として設計する必要がある。


40. PodDisruptionBudget

計画的なPod停止時に、 同時に停止してよいPod数を制御するためPodDisruptionBudgetを利用できる。


Replicas = 5

Minimum Available = 4

        ↓

At most 1 Pod disrupted

Node Maintenanceなどによって、 複数Replicaが同時に停止するリスクを抑制できる。

ただしPDBはあらゆる障害からPod数を保証する仕組みではなく、 主にVoluntary Disruptionを制御するための仕組みである。


41. ConfigMapとSecret

Application設定をContainer Imageへ直接埋め込まず、 ConfigMapやSecretとして分離できる。


ConfigMap
    |
    +------> Pod

Secret
    |
    +------> Pod

■ ConfigMap

一般的な設定情報を管理する。

■ Secret

Password、Token、Certificateなどの機密情報を扱う。

ただしSecret Resourceを利用しただけで、 すべての機密情報保護要件が自動的に満たされるわけではない。

RBAC、保存時暗号化、アクセス制御、Rotation、監査なども含めて設計する必要がある。


42. RBAC

Kubernetes APIへのアクセス制御にはRBACが利用される。


Subject
   |
   v
Role / ClusterRole
   |
   v
Permissions
   |
   v
Kubernetes Resources

代表的なResourceには以下がある。

  • Role
  • ClusterRole
  • RoleBinding
  • ClusterRoleBinding

権限はLeast Privilegeを原則として設計する。

Application用ServiceAccountへ 不要なクラスタ管理権限を与えることは避ける。


43. ServiceAccount

Pod内のWorkloadがKubernetes APIへアクセスする場合、 ServiceAccountが利用される。


Pod
 |
 v
ServiceAccount
 |
 v
RBAC
 |
 v
API Server

Workloadごとに必要な権限を分離し、 共通の強力なServiceAccountを使い回さないことが重要となる。


44. Persistent Volume

Podのローカルファイルシステムだけにデータを保存すると、 Pod再作成時にデータを失う可能性がある。

永続ストレージを扱うためにPersistent Volumeが利用される。


Pod
 |
 v
PVC
 |
 v
PV
 |
 v
Storage
  • PV:PersistentVolume
  • PVC:PersistentVolumeClaim

ApplicationはPVCを通じて必要なStorageを要求する。


45. CSI

CSI(Container Storage Interface)は、 Container OrchestratorとStorage Systemを接続する標準インターフェースである。


Kubernetes
    |
    v
CSI
    |
    v
Storage Driver
    |
    v
Storage System

CSIによって、 Kubernetes本体とStorage実装を分離できる。

Volume Mount障害では、 PodだけでなくPVC、PV、StorageClass、CSI Driverなどまで確認する必要がある。


46. StatefulSet

StatefulなWorkloadではStatefulSetが利用される場合がある。

Deploymentとは異なり、 Podへ安定したIdentityを持たせる設計が可能である。


database-0
database-1
database-2

StatefulSetでは以下のような特性を利用できる。

  • 安定したPod名
  • 安定したNetwork Identity
  • PodごとのStorage
  • 順序を考慮した起動・終了

ただしStatefulSetを利用しただけで、 データベースのReplication・Consensus・Backup・Failoverが自動的に安全になるわけではない。


47. DaemonSet

各Nodeへ1つずつPodを配置したい場合、 DaemonSetを利用する。


Node A
  └─ Agent Pod

Node B
  └─ Agent Pod

Node C
  └─ Agent Pod

代表的な用途には以下がある。

  • ログ収集Agent
  • 監視Agent
  • Network関連Agent
  • Security Agent

48. JobとCronJob

常時稼働するServiceではなく、 完了することを目的とするWorkloadにはJobを利用できる。


Job
 |
 +------> Pod
             |
             v
          Complete

定期実行にはCronJobを利用する。

Batch処理では以下を考慮する必要がある。

  • Retry
  • Idempotency
  • Concurrency
  • Timeout
  • 重複実行
  • 失敗時の再処理

KubernetesがPodを再実行する可能性を考慮し、 Application側も冪等に設計することが重要となる。


49. Horizontal Pod Autoscaler

HPA(Horizontal Pod Autoscaler)は、 負荷に応じてPod Replica数を増減させる。


Traffic Increase
      |
      v
Metric Increase
      |
      v
HPA
      |
      v
Replicas

3 → 5 → 8

CPUなどのResource Metricだけでなく、 構成によってはCustom MetricやExternal Metricを利用することもできる。

ただしAutoscalingには遅延が存在する。


Traffic Spike
    |
Metric Collection
    |
HPA Decision
    |
Pod Creation
    |
Scheduling
    |
Image Pull
    |
Application Startup
    |
Ready

急激なTraffic Spikeでは、 新PodがReadyになる前に既存Podが過負荷になる可能性がある。


50. Vertical Pod Autoscalingの考え方

Horizontal Scalingだけでなく、 Workloadに必要なCPU・Memory量そのものを調整するVertical Scalingの考え方も存在する。


Before

Pod
CPU Request = 500m
Memory = 512Mi

        ↓

After

Pod
CPU Request = 1
Memory = 1Gi

重要なのは、 Requestsを固定値として放置せず、 実際のResource Usageを観測して適切にRight-Sizingすることである。


51. Node CapacityとAllocatable

Nodeの全リソースをPodが利用できるわけではない。


Node Capacity
████████████████████████

System Reserved
██

Kubernetes Reserved
██

Other Reservations
█

Allocatable
███████████████████

SchedulerはPodのRequestsとNodeのAllocatableなどを基に配置を判断する。

「Nodeには32GB RAMがあるから32GB全部Podへ割り当てられる」 とは限らない。


52. Overcommit

RequestsよりLimitsを大きく設定することで、 実際の利用状況を前提としたResource Overcommitが可能になる。


Node CPU = 8 cores

Pod Requests Total = 8 cores

Pod Limits Total = 20 cores

全Podが同時にLimitまで利用しなければ効率的だが、 負荷が同時発生するとResource Contentionが起こる。

クラスタ効率と性能安定性のトレードオフを考える必要がある。


53. Node Pressure

Worker Nodeのリソースが逼迫すると、 Node Pressureが発生する。

代表的には以下を監視する。

  • Memory Pressure
  • Disk Pressure
  • PID Pressure

Node Pressureが発生すると、 SchedulingやPod Evictionへ影響する可能性がある。

Application Metricが正常でも、 NodeレベルのResource ExhaustionによってPodが不安定になる場合がある。


54. Eviction

Nodeリソースが不足すると、 kubeletがPodをEvictする場合がある。


Node Memory Pressure
       |
       v
Eviction Decision
       |
       v
Select Pod
       |
       v
Terminate Pod

Eviction解析では以下を確認する。

  • Node Condition
  • Pod QoS
  • Requests
  • 実際のMemory Usage
  • Disk Usage
  • Event

55. PriorityClassとPreemption

重要なPodを優先的にSchedulingするため、 Pod Priorityを利用できる。


High Priority Pod
       |
       v
No Capacity
       |
       v
Preemption
       |
       v
Lower Priority Pod Removed

ただしPriorityを乱用すると、 低Priority Workloadが長時間Schedulingできない可能性がある。

Priorityはビジネス上の重要度と障害時の復旧戦略を基に設計する。


56. Admission Control

API Requestが永続化される前には、 Admission Controlが実行される。


Request
   |
Authentication
   |
Authorization
   |
Admission
   |
Validation / Mutation
   |
Persist

Admission処理によって、 クラスタへ登録されるResourceへ追加ルールを適用できる。

組織レベルでは、 セキュリティ・Resource設定・Image Policyなどの統制に利用される。


57. Custom Resource Definition

Kubernetes APIは、 CRD(CustomResourceDefinition)によって独自Resourceを拡張できる。


Custom Resource
      |
      v
API Server
      |
      v
Custom Controller
      |
      v
Reconciliation

これによって、 独自のインフラResourceやApplication Lifecycleを Kubernetesの宣言的モデルで管理できる。


58. Operator Pattern

Operatorは、 CRDとControllerを組み合わせて高度な運用処理を自動化する設計パターンである。


DatabaseCluster Resource
          |
          v
      Operator
          |
          +---- Create Nodes
          |
          +---- Configure Replication
          |
          +---- Detect Failure
          |
          +---- Failover

人間の運用手順をControllerへ実装することで、 複雑なStateful ApplicationのLifecycleを自動化できる。

ただしOperator自体も分散システムの一部であり、 誤ったReconciliation Logicはクラスタ全体へ影響する可能性がある。


59. KubernetesのEventual Consistency

Kubernetesでは、 API Resourceを変更した瞬間にすべてが同期的に完成するわけではない。


Deployment Updated
       |
       v
API Server
       |
       v
Controller Detects
       |
       v
ReplicaSet Updated
       |
       v
Pod Created
       |
       v
Scheduler Detects
       |
       v
Node Selected
       |
       v
kubelet Detects
       |
       v
Container Started

複数のControllerが非同期に状態を観測し、 最終的にDesired Stateへ収束させる。

この性質を理解すると、 「applyしたのにまだ変わっていない」という現象を正しく解釈できる。


60. Optimistic Concurrency Control

複数のControllerやClientが同じResourceを更新する可能性があるため、 Kubernetes APIではResource Versionなどを利用した Optimistic Concurrency Controlが重要となる。


Client A
Read Version 10

Client B
Read Version 10

Client A
Update
Version 11

Client B
Update based on Version 10
        |
        v
Conflict

更新競合が発生した場合には、 最新状態を再取得して再試行する必要がある。


61. Watch Mechanism

Kubernetes Componentは、 Resource状態を効率的に監視するためWatchを利用する。


API Server
    |
    | Resource Changed
    v
Watch Stream
    |
    +------> Controller
    |
    +------> Scheduler
    |
    +------> Client

毎回すべてのResourceをPollingするのではなく、 変更イベントを継続的に受信することで効率的なControl Loopを実現する。

ただしController設計では、 Watch Eventだけを絶対的な事実として扱うのではなく、 現在状態を再同期して収束できる設計が重要となる。


62. etcd障害がクラスタへ与える影響

etcdはクラスタ状態のSource of Truthとして重要である。

Quorumを失うなどしてetcdへの正常な書き込みができなくなると、 Control Planeの状態変更能力へ重大な影響が発生する。


API Server
    |
    X
    |
   etcd

New Pod Creation
Update
Delete
Scheduling-related state changes

        ↓

Affected

一方で、既にWorker Node上で動作しているApplication Containerが 即座にすべて停止するとは限らない。

Control Plane障害とData Plane上の既存Workloadの挙動を区別して考えることが重要である。


63. Control Plane障害とData Plane障害

■ Control Plane障害

  • API操作不能
  • 新規Scheduling不能
  • Controllerによる状態収束への影響
  • クラスタ変更不能

■ Data Plane障害

  • Application通信障害
  • Pod障害
  • Node障害
  • Network障害
  • Storage障害

「Kubernetesが壊れた」という表現ではなく、 Control PlaneとData Planeのどちらで問題が発生しているかを切り分ける。


64. Node障害時に何が起きるのか

Worker Nodeが停止したケースを考える。


Before

Node A
Pod 1
Pod 2

Node B
Pod 3
Pod 4


Node A Failure
       X

Control PlaneがNode異常を認識し、 Controllerによる状態管理を通じて、 必要なReplicaが別Nodeへ再作成される。


Desired Replicas = 4

Current Available = 2

        ↓

Create Replacement Pods

        ↓

Node B / Node C

ただし障害検知・Pod再作成・Scheduling・Image Pull・Application起動・Readiness完了には時間がかかる。

したがって「Kubernetesだから無停止」という理解は誤りである。


65. Failure Domainを考える

高可用性を設計する場合、 Pod Replica数だけではなくFailure Domainを考える。


Rack A
Node 1
Node 2

Rack B
Node 3
Node 4

Rack C
Node 5
Node 6

すべてのReplicaが同じNode・Rack・Zoneへ配置されている場合、 共通障害によって同時停止する可能性がある。

高可用性では以下を階層的に考える。

  • Process Failure
  • Container Failure
  • Pod Failure
  • Node Failure
  • Rack Failure
  • Zone Failure
  • Network Failure
  • Storage Failure

66. KubernetesにおけるObservability

Kubernetes障害解析では、 Application Metricだけでは不十分である。

最低でも以下のレイヤーを観測する。


Application
     |
     v
Container
     |
     v
Pod
     |
     v
Node
     |
     v
Kubernetes Control Plane
     |
     v
Network / Storage

■ Metrics

  • CPU Usage
  • CPU Throttling
  • Memory Working Set
  • Restart Count
  • Pod Availability
  • Node Pressure
  • Network Traffic
  • Storage Latency

■ Logs

  • Application Log
  • Container Log
  • kubelet Log
  • Control Plane Log

■ Events

Scheduling Failure、Image Pull Failure、Probe Failure、 Evictionなどの情報を確認する。


67. kubectlによる基本障害解析

■ Pod一覧

kubectl get pods -o wide

■ Pod詳細

kubectl describe pod <pod-name>

■ Log

kubectl logs <pod-name>

■ 前回ContainerのLog

kubectl logs <pod-name> --previous

■ Event確認

kubectl get events --sort-by=.metadata.creationTimestamp

■ Node状態

kubectl get nodes
kubectl describe node <node-name>

■ Service

kubectl get svc

■ EndpointSlice

kubectl get endpointslices

重要なのはコマンドを暗記することではなく、 「現在どのレイヤーを確認しているのか」を理解して使用することである。


68. 実践障害解析:PodがPendingのまま起動しない

Deploymentを更新したが、 新しいPodがPendingのまま起動しないケースを考える。

Step 1:Pod状態確認

kubectl get pods -o wide

Step 2:Pod詳細確認

kubectl describe pod <pod-name>

EventsにScheduling Failureが存在するか確認する。

Step 3:Requestsを確認する


CPU Request = 4 cores
Memory Request = 8Gi

Step 4:Node Allocatableを確認する

Podの要求を満たすNodeが存在するか確認する。

Step 5:Scheduling制約を確認する

  • Node Affinity
  • Pod Anti-Affinity
  • Taints / Tolerations
  • Topology Constraints
  • Volume制約

Pending状態では、 Application内部を調査する前にScheduling Layerを確認する。


69. 実践障害解析:PodがCrashLoopBackOffになる

Step 1:Container状態を確認する

kubectl describe pod <pod-name>

Step 2:現在のLogを確認する

kubectl logs <pod-name>

Step 3:前回Logを確認する

kubectl logs <pod-name> --previous

Step 4:終了理由を確認する

  • Exit Code
  • OOMKilled
  • Error
  • Probe Failure

Step 5:設定を確認する

  • ConfigMap
  • Secret
  • Environment Variable
  • Command / Args

Step 6:依存サービスを確認する

DBや外部Serviceへ接続できないことが、 Application終了原因になっていないか確認する。


70. 実践障害解析:Serviceへ接続できない

Pod自体はRunningだが、 Service経由でアクセスできないケースを考える。

Step 1:PodがReadyか確認する

kubectl get pods

Step 2:Serviceを確認する

kubectl get svc

Step 3:Selectorを確認する

Service SelectorとPod Labelが一致しているか確認する。

Step 4:EndpointSliceを確認する

kubectl get endpointslices

バックエンドPod IPが登録されているか確認する。

Step 5:Portを確認する

  • Service Port
  • Target Port
  • Application Listen Port

Step 6:DNSを確認する

Service名が正常に名前解決されるか確認する。

Step 7:Network Policyを確認する

通信がPolicyによって拒否されていないか確認する。

Step 8:CNI / Node Networkを確認する

Pod間通信そのものが失敗している場合には、 より下位のネットワークレイヤーへ調査を進める。


71. 実践障害解析:Podは正常なのにLatencyが高い

すべてのPodがRunning / Readyだが、 APIのp99 Latencyが急激に悪化したケースを考える。

■ 調査対象

  • CPU Throttling
  • Memory Pressure
  • GC
  • Network Latency
  • DNS Latency
  • Service通信
  • Storage Latency
  • DB Latency
  • Connection Pool
  • Node Resource Contention

Runningは「プロセスが存在している」ことを示すだけであり、 Application性能が正常であることを保証しない。


72. 実践障害解析:Rolling Updateで大量の5xxが発生した

新VersionをDeploymentした瞬間、 大量の5xxが発生したケースを考える。


Old Pods
   |
Terminate
   |
New Pods
   |
Not Ready Yet
   |
Capacity Shortage
   |
5xx

■ 調査項目

  • Readiness Probe
  • Startup Time
  • maxUnavailable
  • maxSurge
  • Graceful Shutdown
  • Termination Grace Period
  • Connection Draining
  • Application Warmup

Deployment Strategyだけではなく、 Application Lifecycleまで含めて設計する必要がある。


73. 実践障害解析:HPAがあるのにTraffic Spikeで落ちた

HPAを設定しているにもかかわらず、 急激なTraffic Spikeで既存Podが過負荷になったケースを考える。


Traffic Spike
      |
      v
Existing Pods Overloaded
      |
      v
Metrics Increase
      |
      v
HPA Scale Out
      |
      v
Pod Scheduling
      |
      v
Image Pull
      |
      v
Startup
      |
      v
Readiness

Autoscalingは即時ではない。

■ 対策として検討する要素

  • 最低Replica数
  • Scaling Policy
  • Application Startup Time
  • Image Size
  • Resource Requests
  • Load Shedding
  • Rate Limiting
  • Queueing
  • Capacity Headroom

Autoscalingを障害対策そのものとして過信せず、 負荷急増まで含めたCapacity Planningが必要となる。


74. Kubernetesで発生するCascading Failure

Kubernetesは自己修復機能を持つが、 設定次第では自己修復処理が障害を増幅する場合もある。

例えばDB障害を考える。


Database Slow
     |
     v
Application Health Check Slow
     |
     v
Liveness Failure
     |
     v
Pod Restart
     |
     v
More DB Connections
     |
     v
Database More Overloaded
     |
     v
More Pod Restarts

このような再起動連鎖によって障害が悪化する可能性がある。

Probe・Retry・Autoscaling・Restartは、 すべて「正しく設定すれば回復機構」だが、 誤れば障害増幅機構になる。


75. Kubernetesで避けるべきアンチパターン

  • Requests / Limitsを設定しない
  • すべてのPodへ同じResource設定を使用する
  • LivenessとReadinessを同じ意味で利用する
  • Livenessで外部依存サービスを過剰に確認する
  • latestタグへ依存する
  • ContainerをRoot権限で無条件に実行する
  • SecretをImageへ埋め込む
  • Application LogをContainer内部だけへ保存する
  • Replicaを同一Nodeへ集中させる
  • StatefulSetを使えばDBが自動的に高可用になると考える
  • HPAがあればCapacity Planning不要と考える
  • Pod再起動を根本的な障害解決と考える
  • Cluster Admin権限をApplicationへ付与する
  • Pod IPへ直接依存する
  • 障害時にkubectlだけを手当たり次第実行する

76. Kubernetes性能解析のレイヤーモデル

Kubernetesで性能問題が発生した場合、 以下の順序でレイヤーを分解すると原因を整理しやすい。


User Request
     |
     v
External Network
     |
     v
Ingress / Gateway
     |
     v
Service
     |
     v
Pod Network
     |
     v
Application
     |
     v
CPU / Memory
     |
     v
Node
     |
     v
Storage / Database / External Dependency

「Kubernetesが遅い」という現象は存在しても、 原因は必ずより具体的なResource・Component・Dependencyへ分解できる。


77. Kubernetes障害解析の体系的フロー

  1. ユーザー影響を確認する
  2. 対象Namespace・Workloadを特定する
  3. Pod Statusを確認する
  4. Eventを確認する
  5. Container終了理由を確認する
  6. Application Logを確認する
  7. Requests / Limitsを確認する
  8. CPU Throttling・OOMを確認する
  9. Node Conditionを確認する
  10. Service / EndpointSliceを確認する
  11. DNSを確認する
  12. Network Policy / CNIを確認する
  13. Volume / CSIを確認する
  14. Control Plane状態を確認する
  15. 外部Dependencyを確認する
  16. 変更履歴とDeploymentを確認する

重要なのは、 最初から原因を決めつけず、 ApplicationからKernel・Network・Storageまでレイヤーを横断して観測することである。


78. 応用エンジニアに求められるKubernetes思考

応用レベルでは、 「kubectl get podsを実行できます」というだけでは不十分である。

以下の問いに技術的根拠を持って回答できる必要がある。

  • ManifestをapplyしてからContainer起動まで何が起こるのか
  • Desired Stateは誰がCurrent Stateへ収束させるのか
  • SchedulerはなぜこのNodeを選択したのか
  • PodがPendingなのはApplication障害なのかScheduling障害なのか
  • CPUに余裕があるのにLatencyが高い原因は何か
  • OOMKilledとNode Memory Pressureの違いは何か
  • Serviceがあるのに通信できないのはなぜか
  • Pod IPはどのように構成されるのか
  • CNI障害とApplication障害をどう切り分けるか
  • ReadinessとLivenessをどう設計するか
  • Rolling Updateで容量不足を起こさないために何が必要か
  • Node障害時にサービス復旧まで何秒必要なのか
  • ReplicaはFailure Domainをまたいで配置されているか
  • AutoscalingがTraffic Spikeへ間に合うか
  • etcdのQuorumを失うと何が起きるか
  • Control Plane障害とData Plane障害を区別できるか
  • Stateful Workloadのデータ整合性を誰が保証するのか
  • クラスタ内の権限はLeast Privilegeになっているか
  • 障害時にどのMetric・Log・Eventを見るべきか

Kubernetesを操作方法ではなく、 分散システム・Linux・ネットワーク・ストレージ・セキュリティを統合する インフラプラットフォームとして理解することが重要である。


本章のゴール

本章のゴールは、 Kubernetes Resourceの表面的な操作から脱却し、 Control PlaneからLinux Kernelまでの内部構造を理解した上で、 大規模なContainer Platformを設計・運用・障害解析できるようになることである。

  • Control PlaneとWorker Nodeの役割を説明できる
  • API Server・etcd・Scheduler・Controller Managerの役割を理解できる
  • Desired StateとReconciliation Loopを説明できる
  • Deployment・ReplicaSet・Podの関係を理解できる
  • Pod作成処理を内部コンポーネント単位で追跡できる
  • Requests / Limitsを適切に設計できる
  • CPU ThrottlingとOOMKillを解析できる
  • QoSとEvictionの関係を理解できる
  • kubelet・CRI・Container Runtimeの関係を説明できる
  • Linux Namespaceとcgroupsを理解できる
  • CNIとPod Networkingを理解できる
  • Service・EndpointSlice・DNSを利用したService Discoveryを理解できる
  • NetworkPolicyを設計できる
  • IngressからPodまで通信経路を追跡できる
  • Liveness・Readiness・Startup Probeを正しく設計できる
  • CrashLoopBackOffとPendingを体系的に解析できる
  • Affinity・Anti-Affinity・Taints・Tolerationsを設計できる
  • Failure Domainを考慮してPodを配置できる
  • Rolling UpdateとGraceful Shutdownを設計できる
  • PDBの目的と限界を理解できる
  • RBACとServiceAccountをLeast Privilegeで設計できる
  • PV・PVC・CSIの関係を理解できる
  • StatefulSetの役割と限界を説明できる
  • HPAとAutoscaling Delayを考慮できる
  • Node PressureとEvictionを解析できる
  • CRDとOperator Patternを理解できる
  • WatchとOptimistic Concurrency Controlを理解できる
  • etcd障害とQuorumの影響を説明できる
  • Control PlaneとData Planeの障害を切り分けられる
  • Kubernetes上のCascading Failureを防止できる
  • Metrics・Logs・Eventsを横断して障害解析できる

これにより、 「Podを再起動したら直った」という運用から脱却し、 Scheduler、Controller、Network、Storage、Kernel、Applicationのどこで問題が発生しているのかを 技術的根拠に基づいて特定できるKubernetesエンジニアを目指す。