Kubernetes Pod 削除操作のソースコード分析

Kubernetes Pod 削除操作のソースコード分析

たとえば、更新戦略が Recreate であるアプリケーションがあり、次のように削除コマンドを実行します。

 ☸ ➜ kubectl ポッドを取得する
名前準備完了ステータス再起動年齢
minio-875749785-sv5ns 1 / 1 実行中1 ( 2分52秒) 42時間
☸ ➜ kubectl 削除ポッドminio-875749785-sv5ns
ポッド「minio-875749785-sv5ns」 が削除されました

削除する前に、別の端末でアプリケーションの状態を確認してください。

 kubectl ポッドを取得-w
名前準備完了ステータス再起動年齢
minio-875749785-sv5ns 1 / 1 実行中1 ( 2分46秒) 42時間
minio-875749785-sv5ns 1 / 1 終了中1 ( 2分57秒) 42時間
minio-875749785-h2j2b 0 / 1 保留中0 0 秒
minio-875749785-h2j2b 0 / 1 保留中0 0 秒
minio-875749785-h2j2b 0 / 1 コンテナ作成0 0s
minio-875749785-sv5ns 0 / 1 終了中1 ( 2分59秒) 42時間
minio-875749785-sv5ns 0 / 1 終了中1 ( 2分59秒) 42時間
minio-875749785-sv5ns 0 / 1 終了中1 ( 2分59秒) 42時間
minio-875749785-h2j2b 0 / 1 実行中0 17秒
minio-875749785-h2j2b 1 / 1 実行中0 30秒

上記のプロセスから、kubectl delete コマンドを実行すると、Pod が Terminating 状態に変わり、その後消えることがわかります。次に、コードの観点から Pod を削除する全体的なプロセスを紹介します。

ここでは、Kubernetes v1.22.8 を例に挙げます。他のバージョンのコードは完全に一貫しているとは保証されませんが、全体的な考え方は同じです。

削除ステータス

kubectl 操作後に表示されるステータスに基づいて追跡できます。上記のフォーマットされた結果は、以下に示すように、コード https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/printers/internalversion/printers.go#L88-L102 によって実装されています。

Pod の出力は printPod 関数を通じて取得されます。コードは次の場所にあります: https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/printers/internalversion/printers.go#L756-L840。以下に示すように、pod.DeletionTimestamp != nil の場合にこの状態に変更される Terminating 値について言及しているコードがあります。

つまり、削除操作が実行されると、Pod の DeletionTimestamp 属性が設定され、Terminating 状態として表示されます。

削除操作が実行されると、DELETE リクエストが API サーバーに送信されます。

 I0408 11 : 25 : 33.002155 42938 round_trippers .go : 435 ] curl - v - XDELETE - H "Content-Type: application/json" - H "User-Agent: kubectl/v1.22.7 (darwin/amd64) kubernetes/b56e432" - H "Accept: application/json" 'https://192.168.0.111:6443/api/v1/namespaces/default/pods/minio-875749785-sv5ns'
I0408 11 : 25 : 33.037245 42938 round_trippers.go : 454 ] DELETE https://192.168.0.111:6443/api/v1/namespaces/default/pods/minio-875749785-sv5ns 200 35 ミリ秒OK

削除リクエストを受信するハンドラーは、以下に示すように、コード https://github.com/kubernetes/kubernetes/blob/v1.22.8/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go#L986 にあります。

BeforeDelete 関数で、正常な削除が必要かどうかを判断します。判断基準は、DeletionGracePeriodSeconds 値が 0 であるかどうかです。ゼロでない場合は、正常な削除とみなされ、apiserver はオブジェクトを etcd からすぐに削除しません。それ以外の場合は直接削除されます。 Pod の場合、デフォルトの DeletionGracePeriodSeconds は 30 秒なので、すぐには削除されません。代わりに、DeletionTimestamp は現在の時刻に設定され、DeletionGracePeriodSeconds はデフォルト値の 30 秒に設定されます。コードは https://github.com/kubernetes/kubernetes/blob/v1.22.8/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go#L93-L159 にあり、DeletionTimestamp の値は次のように設定されています。

上記のコードは、削除操作が実行されると、apiserver が最初に Pod の DeletionTimestamp 属性を現在の時刻に正常な削除猶予期間の時点を加えた時刻に設定することを確認します。この属性を設定すると、クライアントはフォーマット後に終了状態を確認します。

適切な削除

Pod にはサンドボックス コンテナー、ボリュームなど他の多くのリソースが含まれるため、削除後にそれらをリサイクルする必要があります。 Pod を削除すると、対応するコンテナも削除されます。クリーンアップを完了するには、Pod が配置されているノードの kubelet が必要です。まず、kubelet も Pod を監視し続けます。 Pod の削除時間が更新されると、当然イベントを受信し、対応するクリーンアップ作業を実行します。

Kubelet は主に syncLoop 関数で Pod を処理し、イベント関連の処理関数 syncLoopIteration を呼び出します。コードは、以下に示すように、https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kubelet.go#L2040-L2079 にあります。

削除操作を実行すると、apiserver はまず Pod 内の DeletionTimestamp 属性を更新します。この変更は kubelet の更新操作であるため、kubetypes.UPDATE 操作に対応し、更新のために HandlePodUpdates 関数を呼び出します。

HandlePodUpdates では、処理のために Pod の削除を特定のワーカーに割り当てるために、dispatchWork が呼び出されます。 PodWorker は特定のエグゼキューターです。つまり、Pod を更新する必要があるたびに、その更新が podWorker に送信されます。

dispatchWork メソッドは UpdatePod 関数を呼び出して Pod を削除します。コードは https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/pod_workers.go#L540-L765 にあります。この関数では、Pod 情報がチャネルを介して渡され、処理のために goroutine 内で managePodLoop 関数が呼び出されます。この関数では、削除操作を実行するために syncTerminatingPod/syncPod メソッドが呼び出されます。

最終的には、killPod 関数が呼び出され、Pod が削除されます。

killPod 関数はコンテナ ランタイムを呼び出して、Pod 内のコンテナを停止します。コードは https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kubelet_pods.go#L856-L868 にあります:

コンテナ ランタイムの KillPod メソッドは、以下に示すように、https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kuberuntime/kuberuntime_manager.go#L969-L998 にあります。

killPodWithSyncResult メソッドは、まず killContainersWithSyncResult 関数を呼び出して実行中のすべてのコンテナを強制終了し、次に Pod のサンドボックスを削除します。

この関数では、複数の goroutine を使用して Pod 内の各コンテナを削除します。コンテナを削除するメソッドは killContainer です。この関数では、まず事前停止フック(存在する場合)が実行され、その後コンテナが停止されます。コードは https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kuberuntime/kuberuntime_container.go#L660-L736 にあります。

まず、正常な削除の猶予期間を取得します。

TerminationGracePeriodSeconds はリソース リスト ファイルで設定できます。デフォルト値は 30 秒です。 Pod にシャットダウン コマンドが発行されると、SIGTERM シグナルがアプリケーションに送信されます。プログラムは SIGTERM シグナルをキャプチャし、それに応じて処理するだけで済みます。つまり、Pod が SIGTERM シグナルを受信して​​からアプリケーションが正常にシャットダウンするまでにかかる時間です。この時間は、上記で分析した apiserver によって設定されます。

事前停止フックが設定されており、十分な時間がある場合は、フックが実行されます。事前停止の主な目的は、コンテナが削除される前に、リソースの回復やその他の操作など、ビジネスを正常に停止できるようにすることです。

最後に、基盤となるコンテナ ランタイムが呼び出され、コンテナが停止されます。

コンテナが削除された後、前の killPodWithSyncResult 関数に戻り、ランタイム サービスの StopPodSandbox 関数を呼び出してサンドボックス コンテナを停止します (つまり、コンテナを一時停止します)。

 // 同じポッド属するすべてのサンドボックスを停止します
_ の場合podSandbox := range runningPod .Sandboxes {
エラーの場合:= m.runtimeService.StopPodSandbox ( podSandbox .ID .ID ); エラー = nil && !crierror .IsNotFound ( err ) {
killSandboxResult.Fail ( kubecontainer .ErrKillPodSandboxerr.Error ())
klog.ErrorS ( nil , "サンドボックスの停止に失敗しました" , "podSandboxID" , podSandbox .ID )
}
}

この時点で、kubelet は Pod の正常な削除を完了しましたが、これで終わりではありません。

同期ステータス

正常な削除の場合、API サーバーは最初に Pod の DeletionTimestamp 属性のみを設定し、その後 kubelet ウォッチが更新され、Pod の正常な削除が完了します。ただし、サーバー内には Pod の記録が残っており、実際には削除されていません。

kubelet が起動すると、statusManager 同期ループも開始されます。 Manager は kubelet ポッド ステータスの実際のソースであり、最新の v1.PodStatus と同期する必要があります。また、更新は apiserver に同期されます。つまり、正常な削除が完了すると、マネージャーを通じてステータスも apiserver に同期されます。

状態マネージャーが API サーバーとステータスを同期すると、マネージャーの下の syncPod メソッドを呼び出して処理します。コードは、以下に示すように、https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/status/status_manager.go#L149-L181 にあります。

このメソッドでは、Pod が正常に停止したかどうかを判断します。コードは、以下に示すように、https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/status/status_manager.go#L583-L652 にあります。

たとえば、まだ実行中のコンテナがあるかどうか、ボリュームがクリーンアップされていないかどうか、ポッド cgroup が空になっていないかどうかなどを判別します。canBeDeleted が true を返す場合、ポッドが正常に停止したことを意味します。この時点で、API サーバーに削除リクエストを送信して、ポッドを再度削除できます。

ただし、今回は GracePeriodSeconds が 0 に設定されており、Pod が強制的に削除されることを意味します。この時点で、apiserver は DELETE リクエストを再度受信します。初回との違いは、今回は Pod が強制的に削除され、etcd から Pod オブジェクトが削除される点です。

このとき、kubelet は REMOVE イベントを受信し、HandlePodRemoves 関数を呼び出して処理します。

まず、deletePod 関数が呼び出されて関連付けられたポッド ワーカーが停止され、次に、probeManager が呼び出されて、ポッドに関連するプローバー ワーカーが削除されます。これは、ポッドがノードから完全に削除されることを意味します。

<<:  Microsoft、Azure仮想マシンにArmのサポートを追加

>>:  クラウドの方が安全なのに、なぜまだハッキングされるのでしょうか?

推薦する

開設から2年近く経ったサイトの詳細な分析

昨日、浙江省のウェブマスターグループに参加する栄誉に恵まれました。そこで、あるウェブマスターが、自分...

WeChatマーケティングのいくつかの主流の手法についての簡単な説明

WeChatの紹介WeChat(公式サイト:http://weixin.qq.com/)は、テンセン...

エッジアプリケーションテクノロジーはあらゆる業界に利益をもたらす

エッジ コンピューティングは成熟しており、ある業界で学んだ教訓や開発されたソリューションを、別の業界...

デリミタ-20USD/E5420/16GB RAM/1TB HDD/10TB Flow/アトランタ

delimiter.com は、米国の低価格ホスティング プロバイダーです。主な事業はサーバーのレン...

クラウドコンピューティングを使用するときは、群衆に追随しないでください

少し前に読んだレポートでは、その概要はさまざまな業界におけるクラウド コンピューティングの適用に関す...

ショックホスティングはどうですか?東海岸のニュージャージーVPSの簡単なレビュー

ショックホスティングはどうですか?ニュージャージーでショックホスティングはいかがですか?中国人は西海...

#CheapServer# chicagovps-シカゴ/ニューヨーク/ロサンゼルス、サーバーセール

多くの人が知っている、ColoCrossing の独自ブランドである ChicagoGoVPs 。主...

EF Core トランザクション コミットと分散トランザクションの詳細な分析

[[388003]]この記事はWeChatの公開アカウント「Backend Q」から転載したもので...

ベテランウェブマスターが、ウェブサイトの内部リンクをうまく活用する方法を教えます

「外国の侵略に対抗するには、まず内部を固めなければならない」という諺があります。この言葉から、どんな...

電子商取引の専門家の視点からウェブサイトプロモーション

タオバオで働いている友人の多くは、ウェブサイトや店舗を宣伝する方法を尋ねると、いつも同じことを言いま...

2021 年のトップ 5 のエンタープライズ クラウド ストレージ ソリューション

多くの企業はすでにクラウドに移行し、そのメリットを実感しているので、トップクラスのクラウド ストレー...

学習と交流を同時に実現する教育ソーシャルネットワーキングサイトが登場

諺にもあるように、学びは決して終わらない。私たちは人生の約20年間を学校で教育を受けて過ごします。学...

オンラインプロモーション:市場での入札「成功か失敗かは小和にかかっている」

近年、オンラインプロモーションをいち早く取り入れた中小企業が、その恩恵を享受しています。世の中には予...

ファーウェイのクラウド共有専門家トン・シン氏:紙の話から実装まで、アジャイル変革は慎重かつ慎重に行う必要がある

トン・シン: Huawei Cloud・クラウド共有の専門家。長年のソフトウェア開発経験、5年間のア...