賢く「散らす」ための Topology Spread Constraints #k8sjp / Kubernetes Meetup Tokyo 25th

332f89cc697355902a817506b6995f2b?s=47 y_taka_23
November 13, 2019

賢く「散らす」ための Topology Spread Constraints #k8sjp / Kubernetes Meetup Tokyo 25th

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

Kubernetes において、Pod を分散させる基本単位は Node です。しかし現実には複数の Node に Pod が分散している状況であっても、それらの Node が同じ Availability Zone やラックにホスティングされていた場合には、障害が原因で Pod が全滅しサービス停止に陥る可能性があります。

この問題を解決するため、Kubernetes v1.16 ではアルファ機能として Topology Spread が導入されました。この機能を有効にすると、Node に Label を付与することで故障ドメインを表現した論理的なグループを作成し、そのグループ単位での Pod の分散方法を指定することができます。

イベント概要:https://k8sjp.connpass.com/event/150873/
動画:https://www.youtube.com/watch?v=m4SpEzKN-RM&t=8138s

332f89cc697355902a817506b6995f2b?s=128

y_taka_23

November 13, 2019
Tweet

Transcript

  1. 賢く「散らす」ための Topology Spread Constraints チェシャ猫 (@y_taka_23) Kubernetes Meetup Tokyo #25

    (2019/11/13) #k8sjp
  2. Scheduling = Pod の配置戦略 #k8sjp

  3. 複数 Node への Pod の配置 Node Pod Pod Node Pod

    Pod Node Node #k8sjp
  4. 複数 Node への Pod の配置 Availability Zone A Node Pod

    Pod Node Pod Pod Availability Zone B Node Node #k8sjp
  5. Kubernetes の Topology • Node を論理的にグルーピング ◦ Label を付与することで表現 ◦

    運用上は「まとめて故障する単位」に対応 • Well-Known Labels も利用可能 ◦ Cloud Provider が自動で付与 ◦ failure-domain.beta.kubernetes.io/region ◦ failure-domain.beta.kubernetes.io/zone #k8sjp
  6. Zone 間の Pod 分散 Availability Zone A Node [zone=zoneA, node=node1]

    Pod Pod Node [zone=zoneA, node=node2] Availability Zone B Node [zone=zoneB, node=node3] Pod Pod Node [zone=zoneB, node=node4] #k8sjp
  7. Node 間の Pod 分散 Availability Zone A Node [zone=zoneA, node=node1]

    Pod Node [zone=zoneA, node=node2] Availability Zone B Node [zone=zoneB, node=node3] Pod Node [zone=zoneB, node=node4] Pod Pod #k8sjp
  8. 既存の「散らす」機能 • DaemonSet ◦ 全 Node に 1 Pod ずつ配置されてしまう

    ◦ 大きなクラスタでは無駄が多すぎる • Pod Anti Affinity ◦ 自分自身と反発するような設定を記述 ◦ 各 Topology にちょうど 1 Pod しか配置できない ◦ ローリングアップデートできない #k8sjp
  9. Topology Spread Constraints #k8sjp

  10. Topology Spread Constraints • v1.16 で α 版機能として導入 ◦ 従来よりも「柔軟な単位」で分散が可能に

    ◦ Feature Gate: EvenPodsSpread=true • Topology 間で Pod を分散させる ◦ 許容できる Pod 個数の差を指定 ◦ カウント対象となる Pod は Label で指定 ◦ 強制か、あくまでも優先に留めるかは選択可能 #k8sjp
  11. Topology Spread Constraints kind: Pod apiVersion: v1 metadata: name: mypod

    labels: foo: bar spec: constiners: ... topologySpreadConstraints: - topologyKey: zone maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule #k8sjp
  12. Topology Spread Constraints kind: Pod apiVersion: v1 metadata: name: mypod

    labels: foo: bar spec: constiners: ... topologySpreadConstraints: - topologyKey: zone maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule Pod をカウントする単位 #k8sjp
  13. Topology Spread Constraints kind: Pod apiVersion: v1 metadata: name: mypod

    labels: foo: bar spec: constiners: ... topologySpreadConstraints: - topologyKey: zone maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 許容する個数の差 #k8sjp
  14. Topology Spread Constraints kind: Pod apiVersion: v1 metadata: name: mypod

    labels: foo: bar spec: constiners: ... topologySpreadConstraints: - topologyKey: zone maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule カウントする Pod の条件 #k8sjp
  15. Topology Spread Constraints kind: Pod apiVersion: v1 metadata: name: mypod

    labels: foo: bar spec: constiners: ... topologySpreadConstraints: - topologyKey: zone maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 合致しない場合は配置禁止 #k8sjp
  16. Zone に対して maxSkew: 1 Availability Zone A (2 Pods) Node

    [zone=zoneA, node=node1] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (1 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Node [zone=zoneB, node=node4] #k8sjp
  17. Zone に対して maxSkew: 1 Availability Zone A (2 Pods) Node

    [zone=zoneA, node=node1] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (2 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Node [zone=zoneB, node=node4] Pod [foo=bar] #k8sjp
  18. Zone に対して maxSkew: 1 Availability Zone A (2 Pods) Node

    [zone=zoneA, node=node1] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (2 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Node [zone=zoneB, node=node4] Pod [foo=bar] #k8sjp
  19. 複数の Constraints を指定 spec: topologySpreadConstraints: - topologyKey: zone maxSkew: 1

    labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule - topologyKey: node maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule #k8sjp
  20. 複数の Constraints を指定 spec: topologySpreadConstraints: - topologyKey: zone maxSkew: 1

    labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule - topologyKey: node maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule Zone に対する分散 #k8sjp
  21. 複数の Constraints を指定 spec: topologySpreadConstraints: - topologyKey: zone maxSkew: 1

    labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule - topologyKey: node maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule Node に対する分散 #k8sjp
  22. Zone & Node で maxSkew: 1 Availability Zone A (3

    Pods) Node [zone=zoneA, node=node1] Pod [foo=bar] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (2 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Pod [foo=bar] #k8sjp
  23. Zone & Node で maxSkew: 1 Availability Zone A (4

    Pods) Node [zone=zoneA, node=node1] Pod [foo=bar] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (2 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Pod [foo=bar] Pod [foo=bar] #k8sjp
  24. Zone & Node で maxSkew: 1 Availability Zone A (3

    Pods) Node [zone=zoneA, node=node1] Pod [foo=bar] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (3 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Pod [foo=bar] Pod [foo=bar] #k8sjp
  25. 配置できる Node がない! #k8sjp

  26. 矛盾する Constraints の解消 spec: topologySpreadConstraints: - topologyKey: zone maxSkew: 1

    labelSelector: matchLabels: foo: bar whenUnsatisfiable: ScheduleAnyway - topologyKey: node maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule #k8sjp
  27. 矛盾する Constraints の解消 spec: topologySpreadConstraints: - topologyKey: zone maxSkew: 1

    labelSelector: matchLabels: foo: bar whenUnsatisfiable: ScheduleAnyway - topologyKey: node maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 合致しない場合は順位を下げる #k8sjp
  28. 矛盾する Constraints の解消 spec: topologySpreadConstraints: - topologyKey: zone maxSkew: 2

    labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule - topologyKey: node maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 許容できる差の範囲を緩める #k8sjp
  29. Zone & Node で maxSkew: 2 Availability Zone A (4

    Pods) Node [zone=zoneA, node=node1] Pod [foo=bar] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (2 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Pod [foo=bar] Pod [foo=bar] #k8sjp
  30. Zone & Node で maxSkew: 2 Availability Zone A (4

    Pods) Node [zone=zoneA, node=node1] Pod [foo=bar] Pod [foo=bar] Node [zone=zoneA, node=node2] Pod [foo=bar] Availability Zone B (3 Pods) Node [zone=zoneB, node=node3] Pod [foo=bar] Pod [foo=bar] Pod [foo=bar] Pod [foo=bar] #k8sjp
  31. まとめ • Kubernetes の Topology ◦ Node を論理的にグルーピング • Topology

    Spread Constraint ◦ Topology に対して「散らす」設定が可能に ◦ Topology ごと障害が起きた際の可用性が向上 • 運用上の注意点 ◦ DoNotScheduler はうっかりデッドロックを招く #k8sjp
  32. 【PR】Scheduling 徹底解説 https://speakerdeck.com/ytaka23/cloudnative-days-tokyo-2019 #k8sjp

  33. More Spreading, More Reliable! Presented by チェシャ猫 (@y_taka_23) #k8sjp