Ryosei Iwai

Software, Infra Engineer / iwakero / GREE, inc.


aws-load-balancer-controller が pod を target group に追加するまでの流れ

Published January 1, 0001

はじめに

aws-load-balancer-controller(albc) は k8s cluster で ALB,NLB を使う際、勝手に LB を立ててくれて勝手に target group の lisner を弄ってくれるので便利

AWS Load Balancer Controller https://github.com/kubernetes-sigs/aws-load-balancer-controller

k8s & LB であるあるの問題が rolling update 時の 502 で、これは両者が非同期で処理を進めることに起因する

原因としては以下の記事が見やすく、

スマホゲームの API サーバにおける EKS の運用事例 https://labs.gree.jp/blog/2020/01/20271/

対応としてはこの辺も参考になる

[AWS][EKS] Zero downtime deployment(RollingUpdate) when using ALB Ingress Controller on Amazon EKS https://easoncao.com/zero-downtime-deployment-when-using-alb-ingress-controller-on-amazon-eks-and-prevent-502-error/

NEG とは何か https://medium.com/google-cloud-jp/neg-%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B-cc1e2bbc979e

ざっくりな原因は、

  • pod の terminate 時に target group から削除されている保証がない
  • pod の terminate 時に、代わりの pod 達が target group で healthy になっている保証がない

の2点で、

で対応する事がプラクティスとして言われている

pod の READY になる条件に target group 側でヘルスチェックが通ってる事を追加する事で rolling update 時の性急な terminate を抑制するのは分かるが、これはつまり notREADY な pod が target group に登録されているということ。では、ALB から見て pod がアクセスを捌けるという事はどうやって保証しているのか?

本記事では albc のコードを読み解くことで、上記の問題への対応を見ていく

詳細

pod を target group へ登録する3ステップ

albc は、以下のステップにて新規 pod を登録する。ざっくりなコードはここで、その中の ResolvePodEndpoints が追加するエンドポイントを取得している

  1. target group の port と同じ port が設定されている service を取得する
  2. 上記 port と同一の port が設定されているエンドポイント(notReady含)を取得する
  3. notReady なエンドポイントの内、 readinessGate が設定されており containersReady なエンドポイントを、 target group に登録する

それぞれの詳細は下に書くが、ここで重要なのは target group への登録対象として、 containersReady である事を保証している事である

上の方に書いた

ALB から見て pod がアクセスを捌けるという事はどうやって保証しているのか?

への回答は、コンテナに readinessProbe を設定する事でコンテナがアクセスを捌ける事を保証し、チェックが通った(=containersReady)な pod を登録している、ということになる

以上でこの記事の結論が出てしまった訳だが、一応上記ステップについて細かく触れていく

ただコードのリンクを飛び飛びで貼っているので、素直に自分で上記のコードを読んだ方が早い気がしないでもない

ステップ詳細

target group の port と同じ port が設定されている service を取得する

findServiceAndServicePort で k8s API( Service ) を叩き、 service 一覧を取得した後、 LookupServicePort で service を絞っている

上記 port と同一の port が設定されているエンドポイント(notReady含)を取得する

エンドポイント一覧をここで k8s API( Endpoints )を叩いて取得している。

当初、k8s上ではこの時点で新podは READY ではなく service のエンドポイントには新podは登録されていないと考えていたが、API reference を読んでみると、 NotReadyAddresses として取得できる事が分かった

notReady なエンドポイントの内、 readinessGate が設定されており containersReady なエンドポイントを、 target group に登録する

notReady な pod 達はここで以下のチェックが入る

  • ReadinessGate が設定されているかどうか
    • ReadinessGate が設定されていない pod は素直に READY になってから登録すれば良い
  • containersReady かどうか
    • containersReady でない、つまり readinessProbe を通っていない pod はアクセスを捌ける保証がないので、登録しない

以上が登録部分の概要である。この辺は k8s cluster と AWS(ALB) がどう同期を取るかという所が工夫されていて、読んでいて面白かった。一方で僕の感じた疑問の回答がネットで見つけられなかったので、ここに残しておくという訳だ

以上