Slide 1

Slide 1 text

合同会社DMM.com プラットフォーム開発本部 なずな (@na2na_chang) 1 PreStopによるSleep中に何が起きているか ~安全なRollingUpdateの実施のために~

Slide 2

Slide 2 text

⾃⼰紹介 なずな(@na2na_chang) ➢ 合同会社DMM.com(2024年新卒) ○ プラットフォーム開発本部 マイクロサービスアーキテクトグループ 認可チーム ➢ 認可プロダクトをリプレースするお仕事 ○ PHP → Go ○ MySQL → TiDB Cloud ○ オンプレ → GKE ➢ 最近の悩み: おうちKubernetesのコスパのいい監視基盤の作り⽅ 2

Slide 3

Slide 3 text

今⽇話すこと preStopのSleep中にPodへのトラフィックが⽌まる仕組み 3

Slide 4

Slide 4 text

調査のきっかけ 保守しているアプリケーションは、Kubernetesを利⽤して運⽤しています。 無停⽌での更新を⾏う必要があるため、基本的にはRollingUpdateを採⽤しています。 RollingUpdateの最中に起きていることについて調べる中で、 preStop中にServiceから外れるという話⾃体はみかけるものの、仕組みまではわかりませんでした。 詳しく知りたかったのでKubernetesコードを⾒たり、GKEで実験したりしました。 4

Slide 5

Slide 5 text

ポイント preStop ● コンテナを停⽌する前に実⾏される 前処理を定義できる機能 ○ 任意のコマンドを実⾏するExec ○ コンテナ上の任意のエンドポイントに リクエストを送るHttp ○ 指定秒数の間「何もしない」をするSleep 5

Slide 6

Slide 6 text

PreStopによるSleep中に何が起きているか 結論 Podが終了する前に、終了予定Podが トラフィックの対象から外れるまでの時間稼ぎをしている 6

Slide 7

Slide 7 text

PreStopによるSleep中に何が起きているか 具体的には、 1. Podの更新イベントが発⽕する(.metadata.deletionTimestampが付与される) 2. 1のイベントを受けてEndpointSlice Controllerが削除予定Podを⽰すEndpointの Conditions.readyをfalseに変える 3. 2のイベントを受けてkube-proxyが削除予定Podをiptablesのエントリに含めないようにする という処理になっています 7

Slide 8

Slide 8 text

PodにdeletionTimestampが付与されます これにより、PodがTerminatingとして 扱われるようになります これは、Podの更新イベントです。 ArgoCDから⾒る Podのmetadataフィールドに deletionTimestampがセットされた時の様⼦→ 削除予定PodがTrafficの対象から外れるまで: その1 8

Slide 9

Slide 9 text

削除予定PodがTrafficの対象から外れるまで: その2 Podの更新イベントを受けて、 EndpointSlice Controllerが 該当EndpointのConditions.readyを falseにセットします。 Podがterminatingであればreadyはfalseになる、という処理 kubernetes/kubernetes master(5aeea45 modified): staging/src/k8s.io/endpointslice/utils.go:L42付近→ 9

Slide 10

Slide 10 text

削除予定PodがTrafficの対象から外れるまで: その3 EndpointSliceの更新をうけて、 kube-proxyがEndpointの再評価と、 iptablesに書き込むルールの組み⽴てと 更新をします。 EndpointとしてReadyでなければルーティングの対象にしない処理 kubernetes/kubernetes master(5aeea45 modified): pkg/proxy/topology.go:L46-L48付近→ ※他に通信を受けるべきPodがServiceに存在しない場合はその限りでない 10

Slide 11

Slide 11 text

参考: 実験していた様⼦の⼀部 以下の条件 - GKE 通常クラスター - v1.30系 - Dataplane V2無効 - CNIはCalico - PreStop: PodLifecycleSleepAction 30s HTTP KeepAlive無効にしたクライアントで Pod→Serviceでひたすらにリクエスト& Nodeに潜り込んでiptablesのエントリ確認 11

Slide 12

Slide 12 text

おわりに この登壇を⾒た⽅が、 「Sleepの間に古いPodがServiceから外れるまで待つ」というのはよく⾒るんだけれども、 どういう原理になっていたのかは今初めて理解できた、 という感想になったら嬉しいです。 OSSでGoのソースコードリーディングは初めてなので苦戦しました。 ここ間違っているよ!等あればX ( @na2na_chang )まで教えていただけますと幸いです。 12

Slide 13

Slide 13 text

Appendix 13

Slide 14

Slide 14 text

RollingUpdate発⽕後の全体の流れ 14 各コンポーネント間の前後関係は厳密なものではありません。