Upgrade to Pro — share decks privately, control downloads, hide ads and more …

賢く「振り分ける」ための Topology Aware Hints #k8sjp / Kubernetes Meetup Tokyo 52nd

y_taka_23
August 17, 2022

賢く「振り分ける」ための Topology Aware Hints #k8sjp / Kubernetes Meetup Tokyo 52nd

Kubernetes Meetup Tokyo #52 で使用したスライドです。

Kubernetes において、Zone や Region の単位で Node をグループ分けしたものを Topology と呼びます。Topology は故障ドメインとしての側面を持つため、可用性の観点から見ると Pod は分散していることが望まれます。一方、Topology 的に遠い通信はパフォーマンス的にも課金的にもコストがかかるため、Service によるロードバランシングの際は「近い」Pod を選択できた方が有利です。

この問題を解決するため、Zone に存在する CPU 容量に応じて Service に対するトラフィックを「近い」Pod に振り分ける機能、Topology Aware Hints について解説しました。

イベント概要:https://k8sjp.connpass.com/event/254803/

y_taka_23

August 17, 2022
Tweet

More Decks by y_taka_23

Other Decks in Technology

Transcript

  1. #k8sjp Topology と Pod の配置 • Kubernetes では Node のグループを

    Topology と呼ぶ ◦ Rack、Zone、Region など、障害される範囲 (Failure Domain) を表現 ◦ Node に topology.kubernetes.io/zone などのラベルを付与 • 可用性の観点からは Pod は Topology に対して分散させたい ◦ Pod が単一の Zone に固まっていると Zone 障害で全滅する可能性がある • 一方、コスパの観点からは通信は Topology 内で完結させたい ◦ AWS の場合、Availability Zone を跨ぐとレイテンシは数倍に ◦ Availabilty Zone を跨いだ通信には追加料金 (0.01 USD / GB) がかかる
  2. #k8sjp Service Topology (KEP 0536) • Service のフィールドとして ユーザが topologyKeys

    を明示 • 複数の Key を指定すると、順番に フェイルオーバして通信先を探す • 右例ではまず Zone 内の Pod を探し 見つからなければ Region 内も探す • わざわざ指定する認知負荷が高く 不便なので v1.20 で Deprecated に apiVersion: v1 kind: Service metadata: name: nginx spec: selector: app: nginx ports: - port: 80 targetPort: 80 topologyKeys: - "topology.kubernetes.io/zone" - "topology.kubernetes.io/region"
  3. #k8sjp EndpointSlice Subsetting (KEP 2004, KEP 2030) • Service Topology

    の問題点に鑑み、ユーザによる Topology 指定が不要に • 裏側では各 Zone 用に自動で分割された EndpointSlice が複数作成される • 分割アルゴリズムの検討が行われ、検証結果は Topology Aware Hints でも活用 • 分割によって EndpointSlice 数・更新が増加する問題から、KEP のみでお蔵入りに EndpointSlice 分割アルゴリズムの比較表 https://github.com/kubernetes/enhance ments/pull/2005
  4. #k8sjp Topology Aware Hints (KEP 2433) • ユーザは Service にアノテーションを追加するだけで発動

    ◦ service.kubernetes.io/topology-aware-hints: auto を追加 ◦ EndpointSlice は分割されず、hints.forZones フィールドを設定 • Zone 内 Node の総 CPU 数に比例してルーティング先 Pod を按分 ◦ 「各 Zone からのリクエストをどの Pod が担当するか」を割り当てる • 端数の影響が大きくなりすぎるときは自動で無効に ◦ 小数点込みで割り算した「理論的な割り当て個数」が実際の Pod 個数の 120 % を超える場合 (Overloading) には Hint を削除
  5. #k8sjp 同一 Zone 内にのみルーティングされるケース • 対象となる Pod は計 3 個

    • Zone A に属する Node のCPU は全体の 2/3 個なので、 Pod 3 個中 2 個 (A, B) を割当 • 同様に、Zone B には Pod 3 個中 1 個 (C) を割当 • 結果として、kube-proxy は 同一 Zone 内でルーティングを 行う(図中の矢印) Zone A (CPU 計 2 → 割当 Pod 2) Zone B (CPU 計 1 → 割当 Pod 1) Node A (CPU 1 個) Pod A Node B (CPU 1 個) Pod B Node C (CPU 1 個) Pod C
  6. #k8sjp Zone 間も含めルーティングされるケース • Zone 内の Pod 数ではなく CPU 数が割当ての基準

    • Zone A に Pod は 2 個あるが CPU は全体の 1/3 なので Pod 3 個中 1 個 (A) のみ割当 • Zone B の CPU は 2/3 なので Pod 3 個中 2 個 (B, C) を割当 • Zone B から Zone A にも 通信が届く(図中の矢印) Zone A (CPU 計 1 → 割当 Pod 1) Zone B (CPU 計 2 → 割当 Pod 2) Pod A Pod B Node B (CPU 2 個) Pod C Node A (CPU 1 個)
  7. #k8sjp Overloading により Hint が使用されないケース • Zone A、Zone B ともに

    1 CPU ずつなので、割当は Pod 1.5 個ずつになるが、 実際の割当は 1 個単位 • 仮に 1 個 (C) を割り当てると 理論値の150 (>120) % の負荷 • この場合、Hint は削除され、 通常のルーティングが行われる (図中の矢印) Zone A (CPU 計 1 → 割当 Pod 1.5) Zone B (CPU 計 1 → 割当 Pod 1.5) Pod A Pod B Node B (CPU 1 個) Pod C Node A (CPU 1 個)
  8. #k8sjp まとめ • 同一 Topology 内で通信を完結させたいケースがある ◦ レイテンシ・コストの面で Zone を跨ぎたくない

    ◦ 非推奨になった Service Topology はユーザによる明示が必要だった • Topology Aware Hints による通信の局所化 ◦ ユーザは Service にアノテーションを追加すればよい ◦ Zone からの発信トラフィック量は CPU の個数に比例すると仮定 • 状況を判断して適宜フェイルオーバしてくれる ◦ 常に Zone 内のみで通信するわけではなく、偏りすぎる場合は無効に