aws-load-balancer-controller の readinessGate を考慮した pod 追加の挙動

· 1568 words · 4 minute read

最近業務で EKS を運用しており、aws-load-balancer-controller(albc) の挙動で調べたことがあるのでメモしておくはなし

albc(ip-mode) と readinessGate まわりのはなし #

はじめに #

aws-load-balancer-controller は 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 の運用事例

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

[AWS][EKS] Zero downtime deployment(RollingUpdate) when using ALB Ingress Controller on Amazon EKS

NEG とは何か - Yuki Furuyama

ざっくりな原因は、

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

の2点で、

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

pod の READY になる条件に target group 側でヘルスチェックが通ってる事を追加する事で rolling update 時の性急な terminate を抑制するのは分かるが、これはつまり notREADY な pod が target group に登録されているということ

では、ALB から見て pod がアクセスを捌けるという事はどうやって保証しているのか? (この場合、target group で HEALTY な事は pod がアクセスを捌けるという事を保証している訳ではないと考えた)

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

詳細 #

以下のコードを読んでいく

kubernetes-sigs/aws-load-balancer-controller

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 を登録している、ということになる

以上でこの記事の結論が出てしまった訳だが、一応上記ステップについて細かく触れていく。ただコードのリンクを飛び飛びで貼っているので、素直に自分で上記のコードを読んだ方が楽かもしれない

ステップ詳細 #

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

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

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

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

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

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

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

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

以上が登録部分の概要である。

まとめ #

readinessGate は k8s に pod が target group で healthy で登録されている事を伝えながらも、containersReady な pod のみを登録するように制御されていることがわかった

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

以上

k8s