2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KubernetesのEventログの一覧

2
Last updated at Posted at 2026-09-29

はじめに

Kubernetesのトラブルシュートでは「Eventログを確認しましょう」「Event ログは保管しておいた方がいいですよ」という話をよく耳にします。実際、kubectl describe pod を叩けば画面の下の方に Events: という表が出てきますし、kubectl get events でも一覧を取れます。

ただ、「Event を見ましょう」と言われても、そこにどんな種類の情報が載っていて、何が分かって何が分からないのかのイメージが湧かない、という相談を受けたことがあります。実際にEventのReasonを何十種類も見比べたことがある人は少なく、初めて kubectl describe pod の出力を見たときに、FailedScheduling や BackOff といった文字列だけを頼りに手探りで調べることになりがちです。

そこでこの記事では、Kubernetesが標準で発行するEventを「どのコンポーネントが」「どんな条件で」「何のために」発火させているのかを、kubernetes/kubernetes のソースコードを直接読んでカテゴリ別に整理しました。実際にどんな Event ログがあるのか、一緒に見ていきましょう。

対象コンポーネントとバージョン

コンポーネント バージョン リポジトリ 本記事での役割
kube-scheduler / kubelet / kube-controller-manager 等 v1.37.1(タグ) kubernetes/kubernetes Event Reasonの発火箇所・発火条件をソースコードで確認

TL;DR

  • EventはAPIオブジェクトとしては地味ですが、reason / type / message / count / firstTimestamp ・lastTimestamp / reportingComponent を組み合わせることで「何が・いつから・何回・どのコンポーネントの判断で」起きたかを表現しています(参考: Event API)。
  • Eventは既定で1時間(--event-ttl)しか保持されません。トラブルシュートの前に消えていることが多く、「保管しておいた方がいい」という話はここに由来します。
  • EventのReasonは、スケジューリング→イメージ取得→コンテナ起動→ヘルスチェック→リソース逼迫時のEvictionという、Podのライフサイクルの各フェーズにほぼ1対1で対応しています。 どのフェーズで詰まっているかは、出ているReasonの種類から逆算できます。
  • NodeNotReady や Evicted のように見た目は深刻でもEventTypeが Normal のReasonがあります。 Warning/Normalの区分だけで深刻度を判断すると見誤ります。
  • StatefulSetのPod操作Eventは固定のReason文字列ではなく Successful<動詞> / Failed<動詞> という形で動的に組み立てられています。 他のワークロードコントローラーの SuccessfulCreate / FailedCreate と紛らわしいので注意が必要です。
  • kubectl events --types=Warning でWarningだけに絞り込める、kubectl events --for pod/xxx --watch でリアルタイムに追える、といった kubectl events サブコマンド独自のオプションも押さえておくと調査が速くなります。

第1章: Event とは何か

1.1 Event オブジェクトの構造

Kubernetesの Event は、他のリソースと同様にAPIオブジェクトとして表現されます。次のフィールドが特に重要です。

フィールド 意味
reason 状態遷移の理由を表す短い機械可読な文字列(例: FailedScheduling)
type Normal か Warning(将来増える可能性がある、とドキュメントに明記あり)
message 人間可読な説明文
involvedObject どのリソースに関するEventか
count / firstTimestamp / lastTimestamp 同じEventが何回・いつからいつまで発生したか
reportingComponent どのコンポーネントが発行したか(例: kubernetes.io/kubelet)
series 短時間に連続発生した場合の集約情報

(参考: Event API リファレンス)

reason/type の組み合わせ方は各コンポーネントの実装に委ねられていますが、この記事で見ていく通り、多くのコンポーネントは「成功したら Normal + 名詞や過去分詞」「失敗したら Warning + Failed始まりの文字列」という緩やかな命名規則に従っています。

1.2 Eventは「ベストエフォートで短命」なデータである

Event用語集ページには次のように明記されています。

Events have a limited retention time and triggers and messages may evolve with time. Event consumers should not rely on the timing of an event with a given reason reflecting a consistent underlying trigger, or the continued existence of events with that reason.

Events should be treated as informative, best-effort, supplemental data.

(参考: Event | Kubernetesドキュメント用語集)

実際、kube-apiserverには保持期間を制御する --event-ttl フラグがあり、既定値は1時間です。

Amount of time to retain events.(Default: 1h0m0s)

(参考: kube-apiserver)

この「1時間で消える」という制約が、「Event ログを保管しておいた方がいい」と言われる理由です。1時間以上前に起きた問題を後から調査したい場合、クラスタ標準のEvent APIだけでは間に合わず、Event Exporterのような仕組みで外部にエクスポートしておく必要があります。

また、kube-apiserverには --etcd-servers-overrides というフラグもあり、リソースごとに別のetcdクラスタへ書き込み先を切り替えられます。ドキュメントのフラグ説明の例には /events#http://etcd6:2379 が挙げられており、Eventは発生頻度が高く揮発性も高いデータであるため、Pod等の本体データとは別のetcdクラスタへ分離する構成例として言及されています。

(参考: kube-apiserver)

1.3 kubectl events というサブコマンド

kubectl describe の末尾に表示される以外に、kubectl events という専用サブコマンドもあります。--types=Normal,Warning でタイプを絞り込んだり、--for TYPE/NAME で特定リソースに絞って --watch でリアルタイムに眺めたりできます。

# Warning だけに絞って一覧表示
kubectl events --types=Warning

# 特定のPodのEventだけをwatchし続ける
kubectl events --for pod/web-pod-13je7 --watch

(参考: kubectl events)

ここから先は、実際にどのコンポーネントがどんなReasonを発行しているのかを、カテゴリ別に見ていきます。

第2章: スケジューリング系Event

Podがどのノードに割り当てられるか、という段階で発生するEventです。kube-schedulerが involvedObject をPodにして発行します。

Reason Type 発生条件 ソース
FailedScheduling Warning スケジューリングに失敗した(適合するノードが無い等) schedule_one.go#L1253
Scheduled Normal Podのノードへのバインドに成功した schedule_one.go#L1138
Preempted Normal 優先度の高いPodのために本Podがプリエンプション(強制削除)された executor.go#L159
BindingConditionsPending Normal Dynamic Resource Allocation(DRA)でデバイスのバインド条件待ち dynamicresources.go#L1720

Preempted は、削除される対象のPod(ソースコード上の変数名は victim)の視点で見るとWarningであってもよさそうな名前ですが、実装上は EventTypeNormal です。プリエンプションはスケジューラの正常な意思決定の結果であり、異常事態ではない、という設計判断が読み取れます。

Pending のまま進まないPodを見たら、まず FailedScheduling の message を読むのが基本です。ここにはCPU/メモリ不足、Taint/Toleration不一致、Affinity不一致などスケジューリングに失敗した具体的な理由が入ります。

第3章: コンテナ起動・イメージ取得系Event

kubeletの pkg/kubelet/kuberuntime/ と pkg/kubelet/images/ が発行するEventです。Reason定数は pkg/kubelet/events/event.go に集約されています。

Reason Type 発生条件 ソース
Pulling Normal イメージのpullを開始した image_manager.go#L362
Pulled Normal イメージのpullに成功した(サイズ・所要時間をmessageに含む) image_manager.go#L381
Failed(FailedToPullImage) Warning イメージのpullに失敗した image_manager.go#L369
BackOff(BackOffPullImage) Warning 直前のpull失敗から間もないため再pullをバックオフした image_manager.go#L346
InspectFailed Warning pull済みイメージのメタデータ取得に失敗した image_manager.go#L124
ErrImageNeverPull Warning imagePullPolicy: Never でローカルにイメージが無い image_manager.go#L164
Created(CreatedContainer) Normal コンテナの作成に成功した kuberuntime_container.go#L289
Started(StartedContainer) Normal コンテナの起動に成功した kuberuntime_container.go#L298
Failed(FailedToCreateContainer / FailedToStartContainer) Warning コンテナの作成・起動、あるいはPreCreate/PreStartフックの実行に失敗した kuberuntime_container.go#L280
BackOff(BackOffStartContainer) Warning 直前の終了から一定時間内で、コンテナの再起動をバックオフした kuberuntime_manager.go#L2098
Killing(KillingContainer) Normal コンテナを終了させようとしている kuberuntime_container.go#L887
FailedPostStartHook / FailedPreStopHook Warning lifecycle hook(postStart/preStop)の実行に失敗した kuberuntime_container.go#L330
SandboxChanged Normal 既存のPod sandboxを作り直す必要が生じた kuberuntime_manager.go#L1591
FailedCreatePodSandBox Warning Pod sandboxの作成に失敗した kuberuntime_manager.go#L1749
Starting(StartingKubelet) Normal kubelet自体が起動した(ノード単位で1回) kubelet.go#L3378

Pulling → Pulled → Created → Started という並びが、正常系のコンテナ起動シーケンスをそのまま反映しています。Waiting のまま進まないPodのEventにこの並びの途中で Failed や BackOff が挟まっていれば、そこで止まっている工程が特定できます。

FailedToCreateContainer と FailedToStartContainer はどちらもReason文字列が "Failed" である点に注意が必要です。Reasonだけでは作成の失敗か起動の失敗かを区別できず、message を読む必要があります。

第4章: プローブ(ヘルスチェック)系Event

liveness/readiness/startup probeの結果はkubeletの pkg/kubelet/prober/ から発行されます。

Reason Type 発生条件 ソース
Unhealthy(ContainerUnhealthy) Warning probeが失敗した、またはprobe自体がエラーになった prober.go#L124
ProbeWarning(ContainerProbeWarning) Warning probeは成功したが、レスポンス内容に警告が含まれていた prober.go#L118

Unhealthy はliveness probeの失敗によるコンテナ再起動の直前に出ることが多く、BackOff と組み合わせて「再起動を繰り返している(CrashLoopBackOff)」状態を切り分ける手がかりになります。

第5章: リソース逼迫・Eviction系Event

ノードのリソースが逼迫したときに、kubeletのEviction Managerが発行するEventです。

Reason Type 発生条件 ソース
EvictionThresholdMet Warning Eviction閾値を超過し、リソース回収を試みようとしている(ノードに対して発行) eviction_manager.go#L392
Evicted Warning 閾値超過が続き、実際にPodを強制終了(Evict)した eviction_manager.go#L643

Evicted は pod.status.phase を Failed、pod.status.reason を Evicted にすると同時に発行されます(参考: helpers.go#L44)。message には The node was low on resource: <資源名>. のような形式で、どのリソース(メモリ・ディスク・PID等)が逼迫要因だったかが入ります。

Eviction一歩手前のノード状態は、pkg/kubelet/nodestatus/setters.go がNode Conditionの更新と合わせてEventを発行します。

Reason Type 発生条件 ソース
NodeHasSufficientMemory / NodeHasInsufficientMemory Normal メモリ逼迫のCondition(MemoryPressure)が変化した setters.go#L604
NodeHasDiskPressure / NodeHasNoDiskPressure Normal ディスク逼迫のCondition(DiskPressure)が変化した setters.go#L728
NodeHasSufficientPID / NodeHasInsufficientPID Normal PID逼迫のCondition(PIDPressure)が変化した setters.go#L666

これらはすべて EventTypeNormal です。「メモリが足りない」という状態遷移自体はkubeletにとって正常に検知できている状態であり、実際にPodを追い出すところまで行って初めて Evicted(Warning)になる、という段階分けです。

kubeletが受け付け時点でPodを拒否する(スケジュールはされたがそのノードでは動かせない)場合は、pkg/kubelet/lifecycle/predicate.go で定義された OutOfcpu / OutOfmemory / OutOfephemeral-storage / OutOfpods といったReasonが使われます(参考: predicate.go#L85)。スケジューラが把握しているリソース量とkubeletが実際に確保できるリソース量がずれた場合に発生します。

第6章: ボリューム・ストレージ系Event

kubeletとcontroller-manager(AttachDetachController)は同じ pkg/volume/util/operationexecutor/operation_generator.go を共有しており、Attach/Mount/Resizeの成否をそこから発行します。

Reason Type 発生条件 ソース
SuccessfulAttachVolume Normal ボリュームのAttachに成功した operation_generator.go#L307
FailedAttachVolume Warning ボリュームのAttachに失敗した operation_generator.go#L317
SuccessfulMountVolume Normal ボリュームのMountに成功した operation_generator.go#L1118
FailedMountVolume(FailedMount) Warning Pod起動時にAttach/Mountに失敗した(kubelet側からも発行) kubelet.go#L2238
VolumeResizeSuccessful / VolumeResizeFailed Normal / Warning ボリューム本体のリサイズの成否 operation_generator.go#L1584
FileSystemResizeSuccessful / FileSystemResizeFailed Normal / Warning ボリューム上のファイルシステム拡張の成否 operation_generator.go#L2144

PersistentVolume/PersistentVolumeClaimのバインディングやプロビジョニングは pkg/controller/volume/persistentvolume/pv_controller.go が発行し、定数は pkg/controller/volume/events/event.go にあります。

Reason Type 発生条件 ソース
FailedBinding Warning PVCにマッチするPVが見つからない等でバインドできない pv_controller.go#L468
ProvisioningFailed Warning 動的プロビジョニングに失敗した pv_controller.go#L1537
ProvisioningSucceeded Normal 動的プロビジョニングに成功した pv_controller.go#L1766
VolumeFailedDelete Warning PV削除に失敗した pv_controller.go#L1310

FailedMount はPodが ContainerCreating のまま止まる典型的な原因の1つです。ノード側(kubelet)とcontroller-manager側の両方が似た名前のEventを出すため、involvedObject を見て、どちらのコンポーネントが検知した失敗かを区別すると原因の切り分けが早くなります。

第7章: ノード系Event

ノードの起動・状態変化・強制排除に関するEventです。

Reason Type 発生条件 ソース
NodeReady Normal Node ConditionのReadyがTrueになった setters.go#L548
NodeNotReady Normal Node ConditionのReadyがFalse(またはUnknown)になった setters.go#L550
Rebooted(NodeRebooted) Warning kubeletがノードの再起動を検知した setters.go#L251
Shutdown(NodeShutdown) Normal Graceful Node Shutdownが実行された nodeshutdown_manager_linux.go#L304
RegisteredNode Normal node lifecycle controllerがノードの新規登録を検知した node_lifecycle_controller.go#L698
RemovingNode Normal node lifecycle controllerがノードの削除を検知した node_lifecycle_controller.go#L706
TaintManagerEviction Normal NoExecute Taintに基づき、taint eviction controllerがPodを削除対象にした(またはキャンセルした) taint_eviction.go#L600

前章の Evicted(kubeletによるリソース逼迫時の個別Pod排除)と、この章の TaintManagerEviction(Taintに基づくcontroller-manager側の排除)は、どちらも「Podが追い出される」という結果は同じでも、発生源とトリガーの条件がまったく異なります。「Node Not Ready になってからしばらくしてPodが消えた」という現象を見た場合、TaintManagerEviction の方を疑うのが筋です。

NodeNotReady がEventTypeとしては Normal である点は、TL;DRでも触れた通り注意が必要です。Warningで絞り込んでEventを眺めていると、このEvent自体は見逃してしまいます。

第8章: ネットワーク・Service系Event

EndpointSliceの更新やkube-proxyのヘルスチェックサーバーに関するEventです。

Reason Type 発生条件 ソース
FailedToUpdateEndpoint Warning (レガシーの)Endpointsオブジェクトの更新に失敗した endpoints_controller.go#L549
FailedToUpdateEndpointSlices Warning EndpointSliceの更新に失敗した endpointslice_controller.go#L455
FailedToStartServiceHealthcheck Warning kube-proxyのService用ヘルスチェックサーバーの起動に失敗した service_health.go#L161

Service経由の通信が疎通しない場合、Pod自体のEventだけでなく、これらServiceやEndpointSlice宛てのEventも合わせて確認する必要があります。kubectl events --for service/xxx のように involvedObject を指定して絞り込むと見つけやすくなります。

第9章: ワークロードコントローラー系Event

Deployment/ReplicaSet/DaemonSet/Job/StatefulSetなど、Podを間接的に作成するコントローラーが発行するEventです。

ReplicaSet・DaemonSet・Jobに共通するPodの作成・削除は、pkg/controller/controller_utils.go の共通ヘルパー経由で発行されており、Reason文字列も共通です(定数定義: controller_utils.go#L414-L425)。

Reason Type 発生条件 ソース
SuccessfulCreate Normal 管理下のPodの作成に成功した controller_utils.go#L614
FailedCreate Warning 管理下のPodの作成に失敗した controller_utils.go#L600
SuccessfulDelete Normal 管理下のPodの削除に成功した controller_utils.go#L634
FailedDelete Warning 管理下のPodの削除に失敗した controller_utils.go#L631

Deployment固有のEventはこれに加えて次のものがあります。

Reason Type 発生条件 ソース
ScalingReplicaSet Normal 配下のReplicaSetのレプリカ数を増減させた sync.go#L432
DeploymentRollback(RollbackDone) Normal ロールバックが完了した rollback.go#L108-L109
DeploymentRollbackRevisionNotFound Warning ロールバック先のリビジョンが見つからない rollback.go#L45

なお ProgressDeadlineExceeded や NewReplicaSetAvailable は名前だけ見るとEventにありそうですが、pkg/controller/deployment/*.go の範囲では .status.conditions[].reason としてのみ使われており、EventRecorder経由のEventとしては発行されていません(参考: progress.go#L60)。kubectl describe deployment の出力では Conditions: 欄と Events: 欄は別物なので、混同しないよう注意が必要です。

DaemonSet・Jobにも個別のReasonがあります。

Reason Type 発生条件 ソース
FailedDaemonPod Warning DaemonSetのPod作成に失敗した daemon_controller.go#L894
Suspended Normal Jobが一時停止(spec.suspend: true)された job_controller.go#L1178
Resumed Normal Jobの一時停止が解除された job_controller.go#L1189
Completed Normal Jobが完了した job_controller.go#L1647

StatefulSetは少し毛色が違い、recordPodEvent/recordClaimEvent という共通関数の中で、verb(create/update/deleteなど)から Successful<Verb> / Failed<Verb> というReason文字列をその場で組み立てています。

func (spc *StatefulPodControl) recordPodEvent(verb string, set *apps.StatefulSet, pod *v1.Pod, err error) {
	if err == nil {
		reason := fmt.Sprintf("Successful%s", cases.Title(language.English).String(verb))
		...
		spc.recorder.Event(set, v1.EventTypeNormal, reason, message)
	} else {
		reason := fmt.Sprintf("Failed%s", cases.Title(language.English).String(verb))
		...
		spc.recorder.Event(set, v1.EventTypeWarning, reason, message)
	}
}

(参考: stateful_pod_control.go#L333-L343)

verb に "create" が渡された場合は結果として SuccessfulCreate / FailedCreate になり、他のワークロードコントローラーと同じ文字列になりますが、これは共通のReason定数を参照しているわけではなく、たまたま同じ文字列が生成されているだけです。verb に別の値(update 等)が渡されれば SuccessfulUpdate のようにReasonも変わります。

第10章: In-place Pod Resize系Event

CPU/メモリのrequests・limitsをPodを再作成せずに変更する In-place Pod Resize 機能に関連するEventです。pkg/kubelet/allocation/allocation_manager.go と pkg/kubelet/kubelet.go から発行されます。

Reason Type 発生条件 ソース
ResizeStarted Normal リソース変更の適用を開始した allocation_manager.go#L626
ResizeDeferred Normal ノードの空きリソース不足等で変更を一時保留した allocation_manager.go#L632
ResizeInfeasible Warning そのノードでは変更を実行できないと判断した allocation_manager.go#L634
ResizeCompleted Normal リソース変更が完了した kubelet.go#L2100
ResizeError Warning リソース変更の適用中にエラーが発生した kubelet.go#L2300

ResizeDeferred は他のノードへの再スケジュールを伴わず「今は無理なので待つ」という状態を表しており、FailedScheduling のような即時の失敗とは性質が異なります。この機能を使っている場合、kubectl describe pod のEvents欄にこれらのReasonが出ていないか確認すると、リソース変更がなぜ反映されないのかを追いやすくなります。

おわりに

自分は割とEventログを見ている方だと思っていましたが、実際に調べてみると知らないEventも多く、面白かったです。

普段よく見ているのはこの辺りで、ここまで分かれば基本的なトラブルシュートは一通りできるようになると思います。

  • スケジューリング系
  • コンテナ起動・イメージ取得系
  • プローブ(ヘルスチェック)系
  • リソース逼迫・Eviction系

In-place Pod ResizeのEventログは今回初めて把握しましたが、かなり興味を持ちました。Resize系は利用される環境が今後増えていきそうで、目にする機会も増えてくるのではないかと思っています。

参考

参考リンク

本文で登場する順に並べています。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?