Slide 1

Slide 1 text

#k8sjp 賢く「振り分ける」ための Topology Aware Hints チェシャ猫 (@y_taka_23) Kubernetes Meetup Tokyo #52 (17th Aug. 2022)

Slide 2

Slide 2 text

#k8sjp トラフィックの「賢い」振り分けとは何か? 何であるべきか?

Slide 3

Slide 3 text

#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) がかかる

Slide 4

Slide 4 text

#k8sjp KEP 2433: Topology Aware Hints

Slide 5

Slide 5 text

#k8sjp の前に、今回の KEP に至る前段階としていくつか 没になった KEP があるので経緯を含め紹介

Slide 6

Slide 6 text

#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"

Slide 7

Slide 7 text

#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

Slide 8

Slide 8 text

#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 を削除

Slide 9

Slide 9 text

#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

Slide 10

Slide 10 text

#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 個)

Slide 11

Slide 11 text

#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 個)

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

#k8sjp Now Services Can Take a Hint! Presented by チェシャ猫 (@y_taka_23)