Liveness probe失敗:原因と解決策

冒頭まとめ Liveness probe failed は、kubeletが対象コンテナの生存確認に失敗した記録です。 Warning Unhealthy kubelet Liveness probe failed: Get "http://10.244.1.17:8080/healthz": dial tcp 10.244.1.17:8080: connect: connection refused 失敗が failureThreshold の回数だけ連続すると、kubeletは失敗したコンテナを終了させます。その後の再起動は restartPolicy に従います。Pod lifecycleの公式資料では、Pod単位の値は Always、OnFailure、Never で、既定値は Always と定義されています。そのため、Deploymentなど一般的なPodでは同じPod内でコンテナが再起動します。 Liveness probeが失敗 ↓ failureThreshold回連続 kubeletが対象コンテナを終了 ↓ restartPolicyがAlwaysまたはOnFailure 同じPod、同じNodeでコンテナを再起動 ↓ 失敗が続けば再起動待ちが長くなり、CrashLoopBackOffになり得る ここで、Podが削除されて新しいPodへ置き換わるわけではありません。Pod名とUIDは同じまま、コンテナの restartCount が増えます。複数コンテナのPodなら、probeに失敗したコンテナが対象です。 Kubernetes公式のprobe資料は、liveness probeを、停止しているように見えないまま処理が進まなくなったコンテナを再起動する仕組みとして説明しています。一時的な高負荷、外部データベースの停止、起動の遅さを検出するためのものではありません。 同じ接続失敗でも、readiness probeとは結果が違います。 Liveness probe failed → 対象コンテナを終了し、再起動対象にする Readiness probe failed → コンテナは動かしたまま、PodをServiceの通常転送先から外す 一時的に要求を受けられないだけなら、readinessProbeでServiceから外します。起動に時間がかかるなら startupProbe で、livenessの開始を待たせます。再起動しなければ回復できない状態だけを livenessProbe で判定します。 最初に確認するのは再起動回数ではなく、イベント末尾の失敗理由です。 connect: connection refused → 指定したportで待ち受けていない context deadline exceeded / timeout → timeout内に応答できない HTTP probe failed with statuscode: 500 → endpointが失敗用statusを返した command timed out / exit code != 0 → exec probeのcommandが失敗した エラーの概要 probeは、kubeletがコンテナへ定期的に行う診断です。HTTP、TCP、exec、gRPCの4方式があります。 ...

2026年8月5日 · ErrorLog

Readiness probe失敗:原因と解決策

冒頭まとめ Readiness probe failed は、kubeletが「このコンテナは現在、利用者からの要求を受ける準備ができていない」と判定した記録です。 Warning Unhealthy kubelet Readiness probe failed: Get "http://10.244.1.18:8080/readyz": context deadline exceeded 失敗が failureThreshold の回数だけ連続すると、kubeletはコンテナを終了せず、Podの Ready conditionを False にします。該当Podを選択するServiceでは、EndpointSliceの通常転送対象から外れます。 Readiness probeが失敗 ↓ failureThreshold回連続 コンテナはRunningのまま ↓ Container Ready=False ↓ Pod Ready=False ↓ 該当Serviceの通常転送先から外れる ↓ probeが再び成功 同じPodがReady=Trueへ戻り、転送先へ復帰する したがって、readiness失敗だけでは RESTARTS は増えません。kubectl get pod では次のように、STATUS は Running のまま、READY が 0/1 になることがあります。 NAME READY STATUS RESTARTS AGE app-0 0/1 Running 0 12m 同じprobe失敗でも、livenessProbeとは結果が反対です。 Readiness probe failed → 動かしたままServiceの通常転送先から外す Liveness probe failed → 対象コンテナを終了し、restartPolicyに従って再起動する ただし、readinessはPodのnetworkを切断する機能ではありません。Kubernetes公式のprobe資料が変更すると説明しているのは、PodのReady状態と、該当ServiceのEndpointSliceです。 ...

2026年8月5日 · ErrorLog

Terminating:原因と解決策

冒頭まとめ Terminating は、Podの phase ではありません。削除要求を受け、.metadata.deletionTimestamp が入ったPodを kubectl が一覧で示す表示です。 NAME READY STATUS RESTARTS AGE app-7d8f767544-pk4ch 1/1 Terminating 0 3d 削除要求がAPI Serverに受理されても、Podはすぐには消えません。Kubernetes公式のPod終了処理では、既定で30秒の猶予期間が設けられ、その間に preStop、終了シグナル、接続の退避、コンテナ停止などが進みます。finalizerがある場合は、そのfinalizerを管理するコントローラーの後処理が終わるまで、API上のオブジェクトも残ります。 したがって、数十秒の Terminating は異常とは限りません。長時間変わらない場合は、次の4つを分けて確認します。 猶予期間中の正常な終了処理なのか。 preStop またはアプリケーションの終了処理が完了しないのか。 finalizerを管理するコントローラーが後処理を完了できないのか。 配置先ノードまたはkubeletと通信できず、停止を確認できないのか。 ここで最も重要な事実訂正があります。 kubectl delete pod <Pod名> -n <名前空間> --grace-period=0 --force この強制削除は、ノード上のプロセスを確実に停止してからPodを消す操作ではありません。kubectl delete の公式リファレンスは、API Serverがkubeletによる終了確認を待たず、同じ識別情報を持つ処理が別のマシンで動き続け、データの不整合や損失につながる可能性を警告しています。 強制削除は一覧をきれいにする操作ではありません。古い処理が停止済み、または二度と共有資源へ接続できないと確認した後に限る、最後の手段です。 エラーの概要 Podを通常削除すると、API Serverはオブジェクトへ削除時刻と猶予期間を記録します。 metadata: deletionTimestamp: "2026-08-05T03:12:44Z" deletionGracePeriodSeconds: 30 この時点で削除要求は失敗していません。finalizerの公式説明によれば、finalizerを持つオブジェクトへの削除要求は 202 Accepted で受理され、.metadata.deletionTimestamp が設定されます。その後、必要な後処理が済み、finalizerの一覧が空になると削除が完了します。 Terminating は、この途中経過を kubectl が表示したものです。API上のPodの status.phase は、終了処理中も Running や Pending のままの場合があります。 kubectl get pod <Pod名> -n <名前空間> \ -o jsonpath='{.status.phase}{"\t"}{.metadata.deletionTimestamp}{"\t"}{.metadata.finalizers}{"\n"}' Running 2026-08-05T03:12:44Z [batch.kubernetes.io/job-tracking] もう1つ混同しやすいのが、次の3種類の時間です。 ...

2026年8月5日 · ErrorLog

Kubernetes の 409 エラー:原因と解決策

冒頭まとめ Kubernetes の 409 Conflict は、1つの意味を持つエラーではありません。実装を読むと、409 を返す構築関数が3つあります。 1つ目は、同じ名前のものが既に存在する場合です。区分は AlreadyExists、文言は対象の名前に「already exists」を付けた形になります。 2つ目は、更新しようとした対象が、読み取ってから書き込むまでの間に他者に変更されていた場合です。区分は Conflict、文言は「Operation cannot be fulfilled on …」で始まり、中に「the object has been modified; please apply your changes to the latest version and try again」が入ります。 3つ目は、Server-Side Apply でフィールドの所有権が衝突した場合です。区分は同じ Conflict ですが、details.causes にフィールドごとの衝突と、その所有者の名前が入ります。文言は「Apply failed with N conflict(s)」の形です。 この3つは、対処が正反対です。1つ目は既存を使うか名前を変える。2つ目は読み直してからやり直す。3つ目は所有権を奪うか、手放すか、共有するかを選ぶ。同じ要求をそのまま送り直して直るものは、1つもありません。 したがって、409 を見たら最初にやるのは reason の確認、次に details の確認です。kubectl は区分を括弧付きで表示するので、Error from server (AlreadyExists) か Error from server (Conflict) かがそのまま手がかりになります。 エラーの概要 既に存在する場合の応答です。 { "kind": "Status", "status": "Failure", "message": "configmaps \"app-config\" already exists", "reason": "AlreadyExists", "details": { "kind": "configmaps", "name": "app-config" }, "code": 409 } 楽観ロックの競合は、区分も文言も変わります。 ...

2026年8月3日 · ErrorLog

Kubernetes の 422 エラー:原因と解決策

冒頭まとめ Kubernetes の 422 Unprocessable Entity は、区分が Invalid のエラーです。意味は明快で、内容は読めたが、検証を通らなかったという状態を指します。 このエラーの扱いやすさは、応答の details.causes にあります。実装を読むと、検証のエラー一覧がそのまま causes に変換され、各要素に どのフィールドか(field) と なぜ駄目か(reason) が入ります。reason に入る値は決まっていて、必須項目の欠落なら FieldValueRequired、値が不正なら FieldValueInvalid、対応していない値なら FieldValueNotSupported、禁止された操作なら FieldValueForbidden といった具合です。つまり、推測は不要です。どこがなぜ駄目かは応答に書かれています。 もう1つ、実務で最も誤解されている点があります。知らないフィールドを書いても 422 にはなりません。公式文書には、検証の水準を厳格にした場合、未知または重複したフィールドを検出すると 400 Bad Request で拒否する、と明記されています。さらに但し書きとして、既知のフィールドに型の違う値を入れた場合も 400 になる、とも書かれています。 したがって境界はこうなります。読めなかったのが 400、読めたが内容が通らなかったのが 422。綴りを間違えた、型を間違えた、というよくある失敗は 400 側に落ちます。422 が返っているなら、書式の問題ではなく意味の問題です。 エラーの概要 応答の構造は次の形です。details.causes が本体で、message はその要約にすぎません。 { "kind": "Status", "status": "Failure", "message": "Deployment.apps \"web\" is invalid: spec.selector: Invalid value: ...: field is immutable", "reason": "Invalid", "details": { "group": "apps", "kind": "Deployment", "name": "web", "causes": [ { "reason": "FieldValueInvalid", "field": "spec.selector", "message": "Invalid value: ...: field is immutable" } ] }, "code": 422 } kubectl からの見え方には特徴があります。実装を読むと、区分が Invalid の場合だけ専用の整形が行われ、他のエラーのような Error from server (...) の形にはなりません。 ...

2026年8月3日 · ErrorLog

Kubernetes の 429 エラー:原因と解決策

冒頭まとめ Kubernetes の 429 Too Many Requests には、出どころの違う3つの系統があります。 1つ目は、API サーバーの過負荷保護です。優先度と公平性の仕組み(API Priority and Fairness)が、混雑時に要求を落とします。2つ目は、Pod の退避が PodDisruptionBudget に阻まれた場合です。これは過負荷とは無関係で、「今は許可できない」という意味の拒否です。3つ目は、API サーバー以外、たとえばイメージの取得元が返す制限です。 さらに厄介なのが、429 に見えて 429 ではないものです。ログに「client-side throttling, not priority and fairness」と出ている場合、要求はサーバーにまだ送られていません。クライアント側が自分で待っているだけです。この文言は、ソフトウェア側の実装で「優先度と公平性の仕組みではない」と明示的に書かれています。ここを取り違えると、サーバー側をいくら調べても何も出てきません。 したがって、429 に当たったら最初にやるのは原因の推測ではなく、どこが返したのかの確定です。応答の区分、details の内容、Retry-After の値、この3つで系統が決まります。 エラーの概要 過負荷保護による 429 は、素っ気ない応答です。優先度と公平性の仕組みが要求を落とすとき、実装は Retry-After ヘッダーを付けたうえで、本文に短い文言だけを返します。 HTTP/1.1 429 Too Many Requests Retry-After: 3 Too many requests, please try again later. 一方、退避が拒否された場合の応答は、構造化された情報を持ちます。 { "kind": "Status", "status": "Failure", "message": "Cannot evict pod as it would violate the pod's disruption budget.", "reason": "TooManyRequests", "details": { "causes": [ { "reason": "DisruptionBudget", "message": "The disruption budget web-pdb needs 7 healthy pods and has 6 currently" } ] }, "code": 429 } 同じ 429 でも、details.causes の有無で系統が分かれます。DisruptionBudget が入っていれば退避の拒否であり、混雑とは関係ありません。 ...

2026年8月3日 · ErrorLog

Kubernetes の CreateContainerConfigError:原因と解決策

冒頭まとめ CreateContainerConfigError は、Kubernetes がコンテナを起動する前段階、設定を組み立てる段階で失敗したことを示します。イメージの取得は成功しており、コンテナの作成にも到達していません。 重要なのは、この文字列自体には原因が書かれていないことです。実装を見ると、これは分類のための名前で、kubectl get pods の状態欄にはこの名前だけが出ます。実際の原因は、kubectl describe pod のイベントの側に入ります。しかも、そのイベントの理由欄は CreateContainerConfigError ではなく Failed です。実装で理由の定数がそう定義されています。 原因の大半は、環境変数として参照している ConfigMap や Secret が解決できないことです。文言は2種類に分かれます。参照先そのものが無い場合は secret "app-secrets" not found の形、参照先はあるがキーが無い場合は couldn't find key API_KEY in Secret default/app-secrets の形になります。実装でも、この2つは別々の分岐で作られています。 もう1つ、実務で効く性質があります。kubelet は失敗しても作成を繰り返します。したがって、足りない ConfigMap や Secret を後から作れば、Pod を作り直さなくても起動します。実際の報告を見ても、イベントには同じ失敗が数分間で8回といった形で記録されています。 エラーの概要 まず状態欄です。分類名だけが出ます。 NAME READY STATUS RESTARTS AGE app-6f8d9c7b5-x4k2h 0/1 CreateContainerConfigError 0 64s 原因はイベントにあります。理由欄が Failed である点に注意してください。 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Pulled 3m (x8 over 9m) kubelet Successfully pulled image "app:v1.2" Warning Failed 3m (x8 over 9m) kubelet Error: secret "app-secrets" not found コンテナの状態を直接読むこともできます。分類名と文言が対で入っています。 ...

2026年8月3日 · ErrorLog

Kubernetes の Evicted:原因と解決策

冒頭まとめ Evicted は、Kubernetes の kubelet がノードの資源を守るために Pod を落とした状態です。実装では理由の文字列が Evicted と定義され、Pod は失敗として終了します。 最初に押さえるべきは、これは Pod が使いすぎたという意味ではないことです。公式文書によれば、kubelet は退避シグナルを閾値と比較して退避を決めます。判定の対象はノード側の空き資源です。既定のハード閾値は次のとおりです。 memory.available < 100Mi(Linux)/< 500Mi(Windows) nodefs.available < 10% imagefs.available < 15% nodefs.inodesFree < 5%(Linux) imagefs.inodesFree < 5%(Linux) つまり、ノードがこの線を割った瞬間に、誰かが落とされます。落とされる側の使用量の多さは、順番を決める材料にすぎません。 ここが最大の誤解の元です。文言には「Container X was using 122Ki, request is 0」のような使用量と要求量が並びますが、これは選ばれた理由であって、退避が起きた原因ではありません。この表現が分かりにくいという指摘は、公式の課題として複数回登録されています。 もう1つ、OOMKilled との違いも重要です。公式文書に明記があり、コンテナが OOM で落とされた場合は再起動方針に従って再起動されますが、Pod の退避では再起動されません。 エラーの概要 一覧では状態として現れます。 NAME READY STATUS RESTARTS AGE app-7d8f767544-pk4ch 0/1 Evicted 0 12m app-7d8f767544-q2n8x 0/1 Evicted 0 12m 詳細を見ると、フェーズは失敗、理由が Evicted、そして本文に経緯が入ります。 Status: Failed Reason: Evicted Message: The node was low on resource: ephemeral-storage. Threshold quantity: 94576558032, available: 92034400Ki. Container app was using 122Ki, request is 0, has larger consumption of ephemeral-storage. 実装を読むと、この文言は部品の組み合わせで作られています。どの資源が不足したか、閾値と実際の空き、そして選ばれたコンテナの使用量と要求量です。ほかに、ノードの状態を示す形式、一時領域の上限を超えた場合、一時的なボリュームの使用量が上限を超えた場合の文言も定義されています。 ...

2026年8月3日 · ErrorLog

Kubernetes の NodeNotReady:原因と解決策

冒頭まとめ kubectl get nodes に NotReady と表示されたとき、まず確認すべきは条件の値です。Kubernetes の Ready 条件は3つの値を取り、表示は同じでも意味が違います。 公式の定義はこうです。True はノードが健全で Pod を受け入れられる状態、False は健全ではなく受け入れていない状態、そして Unknown はノード制御役が既定50秒の猶予の間にノードから連絡を受け取れなかった状態です。 この違いが調査の方向を決めます。False はノード自身が「準備できていない」と申告しているので、ノードの中を調べます。Unknown は申告そのものが届いていないので、ノードと制御側の間を調べます。ノードが正常に動いていても Unknown にはなり得ます。 時間の流れも押さえておくと役に立ちます。ノード制御役は5秒ごとに状態を確認し、連絡が途絶えて50秒で Unknown にします。そこから既定で5分待って、Pod の退去を始めます。この5分は、node.kubernetes.io/not-ready と node.kubernetes.io/unreachable に対して自動的に付与される猶予(tolerationSeconds=300)によるものです。 つまり、NotReady になってもすぐ Pod は動かない。逆に、5分を過ぎると一斉に動き始めます。 エラーの概要 一覧では状態として現れます。 NAME STATUS ROLES AGE VERSION node-01 Ready <none> 30d v1.32.1 node-02 NotReady <none> 30d v1.32.1 詳細を見ると、条件と最終連絡時刻が入ります。ここが判断材料です。 Conditions: Type Status LastHeartbeatTime Reason Message ---- ------ ----------------- ------ ------- MemoryPressure Unknown Mon, 03 Aug ... 12:01 NodeStatusUnknown Kubelet stopped posting node status. DiskPressure Unknown Mon, 03 Aug ... 12:01 NodeStatusUnknown Kubelet stopped posting node status. Ready Unknown Mon, 03 Aug ... 12:01 NodeStatusUnknown Kubelet stopped posting node status. すべての条件が同時に Unknown になっていれば、連絡が途絶えた形です。最終連絡時刻を見れば、いつ止まったかが分かります。 ...

2026年8月3日 · ErrorLog

Kubernetes の 502 エラー:原因と解決策

冒頭まとめ Kubernetes で 502 Bad Gateway を見る場面は、利用者向けの通信を取り次ぐ Ingress の制御役に集中します。kubectl の操作で 502 が出ることは、通常ありません。API サーバーが時間切れで打ち切る場合は 504 になり、応答できる相手が居ない場合は 503 になるためです。したがって 502 を見たら、まずコンテナへの通信経路の話だと考えて構いません。 502 の意味は、取り次いだ側が転送先から正しい応答を得られなかった、ということです。ここで重要なのは、転送先そのものは選べているという点です。選べていなければ、そもそも転送する相手が居ないので別のエラーになります。多くの制御役は、対象の転送先が1つも無い場合に 503 を返します。 したがって切り分けの第一歩は、502 と 503 のどちらが出ているかを見ることです。503 なら、転送先の一覧が空です。準備完了の判定が通っていないか、選択の条件が合っていないかのどちらかです。502 なら、一覧には相手が居るのに、その相手との通信が成立していません。 502 の原因は、制御役の土台になっているソフトウェアの作りから、3系統に整理できます。接続そのものを拒否された場合、応答の見出し部分が大きすぎて扱えなかった場合、そして応答を渡し終える前に切られた場合です。ログの文言でこの3つは区別できます。 エラーの概要 制御役のログには、要求ごとの記録と、失敗の理由が残ります。接続を拒否された場合の記録は次の形です。 connect() failed (111: Connection refused) while connecting to upstream, client: 10.1.0.5, server: example.com, request: "GET /api HTTP/1.1", upstream: "http://10.2.3.4:8080/api" 応答の見出し部分が大きすぎる場合は、別の文言になります。 upstream sent too big header while reading response header from upstream, client: 10.1.0.5, server: example.com, request: "GET /api HTTP/1.1" このとき記録に残る転送先の番号を確認してください。ここに出ている番号が、自分が意図したコンテナの番号と違っていれば、原因は設定の食い違いです。 ...

2026年7月29日 · ErrorLog