Podのライフサイクル
このページではPodのライフサイクルについて説明します。Podは定義されたライフサイクルに従い Pending
フェーズから始まり、少なくとも1つのプライマリーコンテナが正常に開始した場合はRunning
を経由し、次に失敗により終了したコンテナの有無に応じて、Succeeded
またはFailed
フェーズを経由します。
Podの実行中、kubeletはコンテナを再起動して、ある種の障害を処理できます。Pod内で、Kubernetesはさまざまなコンテナのステータスを追跡して、回復させるためのアクションを決定します。
Kubernetes APIでは、Podには仕様と実際のステータスの両方があります。Podオブジェクトのステータスは、PodのConditionのセットで構成されます。カスタムのReadiness情報をPodのConditionデータに挿入することもできます。
Podはその生存期間に1回だけスケジューリングされます。PodがNodeにスケジュール(割り当て)されると、Podは停止または終了するまでそのNode上で実行されます。
Podのライフタイム
個々のアプリケーションコンテナと同様に、Podは(永続的ではなく)比較的短期間の存在と捉えられます。Podが作成されると、一意のID(UID)が割り当てられ、(再起動ポリシーに従って)終了または削除されるまでNodeで実行されるようにスケジュールされます。
ノードが停止した場合、そのNodeにスケジュールされたPodは、タイムアウト時間の経過後に削除されます。
Pod自体は、自己修復しません。Podがnodeにスケジュールされ、その後に失敗、またはスケジュール操作自体が失敗した場合、Podは削除されます。同様に、リソースの不足またはNodeのメンテナンスによりポッドはNodeから立ち退きます。Kubernetesは、比較的使い捨てのPodインスタンスの管理作業を処理する、controllerと呼ばれる上位レベルの抽象化を使用します。
特定のPod(UIDで定義)は新しいNodeに"再スケジュール"されません。代わりに、必要に応じて同じ名前で、新しいUIDを持つ同一のPodに置き換えることができます。
volumeなど、Podと同じ存続期間を持つものがあると言われる場合、それは(そのUIDを持つ)Podが存在する限り存在することを意味します。そのPodが何らかの理由で削除された場合、たとえ同じ代替物が作成されたとしても、関連するもの(例えばボリューム)も同様に破壊されて再作成されます。
file puller(ファイル取得コンテナ)とWebサーバーを含むマルチコンテナのPod。コンテナ間の共有ストレージとして永続ボリュームを使用しています。
Podのフェーズ
Podのstatus
項目はPodStatusオブジェクトで、それはphase
のフィールドがあります。
Podのフェーズは、そのPodがライフサイクルのどの状態にあるかを、簡単かつ高レベルにまとめたものです。このフェーズはコンテナやPodの状態を包括的にまとめることを目的としたものではなく、また包括的なステートマシンでもありません。
Podの各フェーズの値と意味は厳重に守られています。ここに記載されているもの以外にphase
の値は存在しないと思ってください。
これらがphase
の取りうる値です。
値 | 概要 |
---|---|
Pending |
PodがKubernetesクラスターによって承認されましたが、1つ以上のコンテナがセットアップされて稼働する準備ができていません。これには、スケジュールされるまでの時間と、ネットワーク経由でイメージをダウンロードするための時間などが含まれます。 |
Running |
PodがNodeにバインドされ、すべてのコンテナが作成されました。少なくとも1つのコンテナがまだ実行されているか、開始または再起動中です。 |
Succeeded |
Pod内のすべてのコンテナが正常に終了し、再起動されません。 |
Failed |
Pod内のすべてのコンテナが終了し、少なくとも1つのコンテナが異常終了しました。つまり、コンテナはゼロ以外のステータスで終了したか、システムによって終了されました。 |
Unknown |
何らかの理由によりPodの状態を取得できませんでした。このフェーズは通常はPodのホストとの通信エラーにより発生します。 |
Nodeが停止するか、クラスタの残りの部分から切断された場合、Kubernetesは失われたNode上のすべてのPodのPhase
をFailedに設定するためのポリシーを適用します。
コンテナのステータス
Pod全体のフェーズと同様に、KubernetesはPod内の各コンテナの状態を追跡します。container lifecycle hooksを使用して、コンテナのライフサイクルの特定のポイントで実行するイベントをトリガーできます。
PodがschedulerによってNodeに割り当てられると、kubeletはcontainer runtimeを使用してコンテナの作成を開始します。コンテナの状態はWaiting
、Running
またはTerminated
の3ついずれかです。
Podのコンテナの状態を確認するにはkubectl describe pod [POD_NAME]
のコマンドを使用します。Pod内のコンテナごとにStateの項目として表示されます。
各状態の意味は次のとおりです。
Waiting
コンテナがRunning
またはTerminated
のいずれの状態でもない場合コンテナはWaiting
の状態になります。Waiting状態のコンテナは引き続きコンテナイメージレジストリからイメージを取得したりSecretを適用したりするなど必要な操作を実行します。Waiting
状態のコンテナを持つPodに対してkubectl
コマンドを使用すると、そのコンテナがWaiting
の状態である理由の要約が表示されます。
Running
Running
状態はコンテナが問題なく実行されていることを示します。postStart
フックが構成されていた場合、それはすでに実行が完了しています。Running
状態のコンテナを持つPodに対してkubectl
コマンドを使用すると、そのコンテナがRunning
状態になった時刻が表示されます。
Terminated
Terminated
状態のコンテナは実行されて、完了したときまたは何らかの理由で失敗したことを示します。Terminated
状態のコンテナを持つPodに対してkubectl
コマンドを使用すると、いずれにせよ理由と終了コード、コンテナの開始時刻と終了時刻が表示されます。
コンテナがTerminatedに入る前にpreStop
フックがあれば実行されます。
コンテナの再起動ポリシー
Podのspec
には、Always、OnFailure、またはNeverのいずれかの値を持つrestartPolicy
フィールドがあります。デフォルト値はAlwaysです。
restartPolicy
は、Pod内のすべてのコンテナに適用されます。restartPolicy
は、同じNode上のkubeletによるコンテナの再起動のみを参照します。Pod内のコンテナが終了した後、kubeletは5分を上限とする指数バックオフ遅延(10秒、20秒、40秒...)でコンテナを再起動します。コンテナが10分間実行されると、kubeletはコンテナの再起動バックオフタイマーをリセットします。
PodのCondition
PodにはPodStatusがあります。それはPodが成功したかどうかの情報を持つPodConditionsの配列です。
PodScheduled
: PodがNodeにスケジュールされました。ContainersReady
: Pod内のすべてのコンテナが準備できた状態です。Initialized
: すべてのInitコンテナが正常に実行されました。Ready
: Podはリクエストを処理でき、一致するすべてのサービスの負荷分散プールに追加されます。
フィールド名 | 内容 |
---|---|
type |
このPodの状態の名前です。 |
status |
その状態が適用可能かどうか示します。可能な値は"True "と"False "、"Unknown "のうちのいずれかです。 |
lastProbeTime |
Pod Conditionが最後に確認されたときのタイムスタンプが表示されます。 |
lastTransitionTime |
最後にPodのステータスの遷移があった際のタイムスタンプが表示されます。 |
reason |
最後の状態遷移の理由を示す、機械可読のアッパーキャメルケースのテキストです。 |
message |
ステータスの遷移に関する詳細を示す人間向けのメッセージです。 |
PodのReadiness
Kubernetes v1.14 [stable]
追加のフィードバックやシグナルをPodStatus:_Pod readiness_に注入できるようにします。これを使用するには、Podのspec
でreadinessGates
を設定して、kubeletがPodのReadinessを評価する追加の状態のリストを指定します。
ReadinessゲートはPodのstatus.conditions
フィールドの現在の状態によって決まります。KubernetesがPodのstatus.conditions
フィールドでそのような状態を発見できない場合、ステータスはデフォルトでFalse
になります。
以下はその例です。
Kind: Pod
...
spec:
readinessGates:
- conditionType: "www.example.com/feature-1"
status:
conditions:
- type: Ready # これはビルトインのPodCondition
status: "False"
lastProbeTime: null
lastTransitionTime: 2018-01-01T00:00:00Z
- type: "www.example.com/feature-1" # 追加のPodCondition
status: "False"
lastProbeTime: null
lastTransitionTime: 2018-01-01T00:00:00Z
containerStatuses:
- containerID: docker://abcd...
ready: true
...
PodのConditionは、Kubernetesのlabel key formatに準拠している必要があります。
PodのReadinessの状態
kubectl patch
コマンドはオブジェクトステータスのパッチ適用をまだサポートしていません。Podにこれらのstatus.conditions
を設定するには、アプリケーションとoperatorsはPATCH
アクションを使用する必要があります。Kubernetes client libraryを使用して、PodのReadinessのためにカスタムのPodのConditionを設定するコードを記述できます。
カスタムのPodのConditionが導入されるとPodは次の両方の条件に当てはまる場合のみ準備できていると評価されます:
- Pod内のすべてのコンテナが準備完了している。
ReadinessGates
で指定された条件が全てTrue
である。
Podのコンテナは準備完了ですが、少なくとも1つのカスタムのConditionが欠落しているか「False」の場合、kubeletはPodのConditionをContainersReady
に設定します。
コンテナのProbe
Probe は kubelet により定期的に実行されるコンテナの診断です。診断を行うために、kubeletはコンテナに実装された Handlerを呼びます。Handlerには次の3つの種類があります:
-
ExecAction: コンテナ内で特定のコマンドを実行します。コマンドがステータス0で終了した場合に診断を成功と見まします。
-
TCPSocketAction: PodのIPの特定のポートにTCPチェックを行います。 そのポートが空いていれば診断を成功とみなします。
-
HTTPGetAction: PodのIPの特定のポートとパスに対して、HTTP GETのリクエストを送信します。 レスポンスのステータスコードが200以上400未満の際に診断を成功とみなします。
各Probe 次の3つのうちの一つの結果を持ちます:
Success
: コンテナの診断が成功しました。Failure
: コンテナの診断が失敗しました。Unknown
: コンテナの診断が失敗し、取れるアクションがありません。
Kubeletは3種類のProbeを実行中のコンテナで行い、また反応することができます:
-
livenessProbe
: コンテナが動いているかを示します。 livenessProbe に失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policyに従います。 コンテナにlivenessProbeが設定されていない場合、デフォルトの状態はSuccess
です。 -
readinessProbe
: コンテナがリクエスト応答する準備ができているかを示します。 readinessProbeに失敗すると、エンドポイントコントローラーにより、ServiceからそのPodのIPアドレスが削除されます。 initial delay前のデフォルトのreadinessProbeの初期値はFailure
です。 コンテナにreadinessProbeが設定されていない場合、デフォルトの状態はSuccess
です。 -
startupProbe
: コンテナ内のアプリケーションが起動したかどうかを示します。 startupProbeが設定された場合、完了するまでその他のすべてのProbeは無効になります。 startupProbeに失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policyに従います。 コンテナにstartupProbeが設定されていない場合、デフォルトの状態はSuccess
です。
livenessProbe、readinessProbeまたはstartupProbeを設定する方法の詳細については、Liveness Probe、Readiness ProbeおよびStartup Probeを使用するを参照してください。
livenessProbeをいつ使うべきか?
Kubernetes v1.0 [stable]
コンテナ自体に問題が発生した場合や状態が悪くなった際にクラッシュすることができればlivenessProbeは不要です.
この場合kubeletが自動でPodのrestartPolicy
に基づいたアクションを実行します。
Probeに失敗したときにコンテナを殺したり再起動させたりするには、livenessProbeを設定しrestartPolicy
をAlwaysまたはOnFailureにします。
readinessProbeをいつ使うべきか?
Kubernetes v1.0 [stable]
Probeが成功したときにのみPodにトラフィックを送信したい場合は、readinessProbeを指定します。 この場合readinessProbeはlivenessProbeと同じになる可能性がありますが、readinessProbeが存在するということは、Podがトラフィックを受けずに開始され、Probe成功が開始した後でトラフィックを受け始めることになります。コンテナが起動時に大きなデータ、構成ファイル、またはマイグレーションを読み込む必要がある場合は、readinessProbeを指定します。
コンテナがメンテナンスのために停止できるようにするには、livenessProbeとは異なる、特定のエンドポイントを確認するreadinessProbeを指定することができます。
startupProbeをいつ使うべきか?
Kubernetes v1.18 [beta]
startupProbeは、サービスの開始に時間がかかるコンテナを持つポッドに役立ちます。livenessProbeの間隔を長く設定するのではなく、コンテナの起動時に別のProbeを構成して、livenessProbeの間隔よりも長い時間を許可できます。
コンテナの起動時間が、initialDelaySeconds + failureThreshold x periodSeconds
よりも長い場合は、livenessProbeと同じエンドポイントをチェックするためにstartupProbeを指定します。periodSeconds
のデフォルトは30秒です。次に、failureThreshold
をlivenessProbeのデフォルト値を変更せずにコンテナが起動できるように、十分に高い値を設定します。これによりデッドロックを防ぐことができます。
Podの終了
Podは、クラスター内のNodeで実行中のプロセスを表すため、不要になったときにそれらのプロセスを正常に終了できるようにすることが重要です(対照的なケースは、KILLシグナルで強制終了され、クリーンアップする機会がない場合)。
ユーザーは削除を要求可能であるべきで、プロセスがいつ終了するかを知ることができなければなりませんが、削除が最終的に完了することも保証できるべきです。ユーザーがPodの削除を要求すると、システムはPodが強制終了される前に意図された猶予期間を記録および追跡します。強制削除までの猶予期間がある場合、kubelet正常な終了を試みます。
通常、コンテナランタイムは各コンテナのメインプロセスにTERMシグナルを送信します。多くのコンテナランタイムは、コンテナイメージで定義されたSTOPSIGNAL値を尊重し、TERMの代わりにこれを送信します。猶予期間が終了すると、プロセスにKILLシグナルが送信され、PodはAPI Serverから削除されます。プロセスの終了を待っている間にkubeletかコンテナランタイムの管理サービスが再起動されると、クラスターは元の猶予期間を含めて、最初からリトライされます。
フローの例は下のようになります。
- ユーザーがデフォルトの猶予期間(30秒)でPodを削除するために
kubectl
コマンドを送信する。 - API server内のPodは、猶予期間を越えるとPodが「死んでいる」と見なされるように更新される。
削除中のPodに対してkubectl describe
コマンドを使用すると、Podは「終了中」と表示される。
Podが実行されているNode上で、Podが終了しているとマークされている(正常な終了期間が設定されている)とkubeletが認識するとすぐに、kubeletはローカルでPodの終了プロセスを開始します。- Pod内のコンテナの1つが
preStop
フックを定義している場合は、コンテナの内側で呼び出される。猶予期間が終了した後もpreStop
フックがまだ実行されている場合は、一度だけ猶予期間を延長される(2秒)。備考:preStop
フックが完了するまでにより長い時間が必要な場合は、terminationGracePeriodSeconds
を変更する必要があります。 - kubeletはコンテナランタイムをトリガーして、コンテナ内のプロセス番号1にTERMシグナルを送信する。
備考: Pod内のすべてのコンテナが同時にTERMシグナルを受信するわけではなく、シャットダウンの順序が問題になる場合はそれぞれに
preStop
フックを使用して同期することを検討する。
- Pod内のコンテナの1つが
- kubeletが正常な終了を開始すると同時に、コントロールプレーンは、終了中のPodをEndpoints(および有効な場合はEndpointSlice)オブジェクトから削除します。これらのオブジェクトは、selectorが設定されたServiceを表します。ReplicaSetsとその他のワークロードリソースは、終了中のPodを有効なサービス中のReplicaSetとして扱いません。ゆっくりと終了するPodは、(サービスプロキシーのような)ロードバランサーが終了猶予期間が_始まる_とエンドポイントからそれらのPodを削除するので、トラフィックを継続して処理できません。
- 猶予期間が終了すると、kubeletは強制削除を開始する。コンテナランタイムは、Pod内でまだ実行中のプロセスに
SIGKILL
を送信する。kubeletは、コンテナランタイムが非表示のpause
コンテナを使用している場合、そのコンテナをクリーンアップします。 - kubeletは猶予期間を0(即時削除)に設定することでAPI server上のPodの削除を終了する。
- API serverはPodのAPIオブジェクトを削除し、クライアントからは見えなくなります。
Podの強制削除
デフォルトでは、すべての削除は30秒以内に正常に行われます。kubectl delete
コマンドは、ユーザーがデフォルト値を上書きして独自の値を指定できるようにする --grace-period=<seconds>
オプションをサポートします。
--grace-period
を0
に設定した場合、PodはAPI serverから即座に強制的に削除されます。PodがNode上でまだ実行されている場合、その強制削除によりkubeletがトリガーされ、すぐにクリーンアップが開始されます。
--grace-period=0
と共に --force
というフラグを追加で指定する必要があります。
強制削除が実行されると、API serverは、Podが実行されていたNode上でPodが停止されたというkubeletからの確認を待ちません。API内のPodは直ちに削除されるため、新しいPodを同じ名前で作成できるようになります。Node上では、すぐに終了するように設定されるPodは、強制終了される前にわずかな猶予期間が与えられます。
StatefulSetのPodについては、StatefulSetからPodを削除するためのタスクのドキュメントを参照してください。
失敗したPodのガベージコレクション
失敗したPodは人間またはcontrollerが明示的に削除するまで存在します。
コントロールプレーンは終了状態のPod(SucceededまたはFailedのphase
を持つ)の数が設定された閾値(kube-controller-manager内のterminated-pod-gc-threshold
によって定義される)を超えたとき、それらのPodを削除します。これはPodが作成されて時間とともに終了するため、リソースリークを避けます。
次の項目
-
attaching handlers to Container lifecycle eventsのハンズオンをやってみる
-
Configure Liveness, Readiness and Startup Probesのハンズオンをやってみる
-
Container lifecycle hooksについてもっと学ぶ
-
APIのPod/コンテナステータスの詳細情報はPodStatusおよびContainerStatusを参照してください