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
- ManifestをAPI Serverへ送信する
- 認証・認可・Admission処理が実行される
- Resourceがetcdへ保存される
- Schedulerが未配置Podを検出する
- 適切なNodeを選択する
- 対象NodeのkubeletがPodを検出する
- Container RuntimeへContainer作成を依頼する
- ネットワークを構成する
- VolumeをMountする
- Containerを起動する
- 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障害解析の体系的フロー
- ユーザー影響を確認する
- 対象Namespace・Workloadを特定する
- Pod Statusを確認する
- Eventを確認する
- Container終了理由を確認する
- Application Logを確認する
- Requests / Limitsを確認する
- CPU Throttling・OOMを確認する
- Node Conditionを確認する
- Service / EndpointSliceを確認する
- DNSを確認する
- Network Policy / CNIを確認する
- Volume / CSIを確認する
- Control Plane状態を確認する
- 外部Dependencyを確認する
- 変更履歴と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エンジニアを目指す。