基于集群资源模型的调度

概览

在将应用程序调度到特定集群时,目标集群的资源状态是一个不容忽视的因素。 例如,当集群资源不足以运行给定的实例时,我们希望调度器尽可能避免这种调度行为。 本文将重点介绍 Karmada 如何基于集群资源模型进行实例的调度。

集群资源模型

在调度过程中,karmada-scheduler 现在根据一系列因素做出决策,其中一个因素是集群的资源状态。 现在 Karmada 有两种不同的基于集群资源的调度方式,其中一种是通用的集群模型,另一种是自定义的集群模型。

通用集群资源模型

使用通用集群资源模型

出于上述目的,Karmada在Cluster API 引入了ResourceSummary的概念。

以下给出了一个ResourceSummary的例子:

  1. resourceSummary:
  2. allocatable:
  3. cpu: "4"
  4. ephemeral-storage: 206291924Ki
  5. hugepages-1Gi: "0"
  6. hugepages-2Mi: "0"
  7. memory: 16265856Ki
  8. pods: "110"
  9. allocated:
  10. cpu: 950m
  11. memory: 290Mi
  12. pods: "11"

从上面的例子中,我们可以知道集群的可分配资源和已分配资源。

基于通用集群资源模型的调度

假设在Karmada控制面上注册了三个成员集群,这时过来一个Pod的调度请求。

Member1:

  1. resourceSummary:
  2. allocatable:
  3. cpu: "4"
  4. ephemeral-storage: 206291924Ki
  5. hugepages-1Gi: "0"
  6. hugepages-2Mi: "0"
  7. memory: 16265856Ki
  8. pods: "110"
  9. allocated:
  10. cpu: 950m
  11. memory: 290Mi
  12. pods: "11"

Member2:

  1. resourceSummary:
  2. allocatable:
  3. cpu: "4"
  4. ephemeral-storage: 206291924Ki
  5. hugepages-1Gi: "0"
  6. hugepages-2Mi: "0"
  7. memory: 16265856Ki
  8. pods: "110"
  9. allocated:
  10. cpu: "2"
  11. memory: 290Mi
  12. pods: "11"

Member3:

  1. resourceSummary:
  2. allocatable:
  3. cpu: "4"
  4. ephemeral-storage: 206291924Ki
  5. hugepages-1Gi: "0"
  6. hugepages-2Mi: "0"
  7. memory: 16265856Ki
  8. pods: "110"
  9. allocated:
  10. cpu: "2"
  11. memory: 290Mi
  12. pods: "110"

假设这个Pod的资源请求是500m CPU。 显然,Member1和Member2有足够的资源来运行这个副本,但Member3没有Pod的配额。 考虑到可用资源的数量,调度器更倾向于将Pod调度到member1。

Clustermember1member2member3
AvailableReplicas(4 - 0.95) / 0.5 = 6.1(4 - 2) / 0.5 = 40

自定义集群资源模型

背景

ResourceSummary 描述了集群的整体可用资源。 但是,ResourceSummary不够精确,它机械地统计所有节点上的资源,而忽略了节点上的碎片资源。例如,一个有 2000 个节点的集群,每个节点上只剩下1核CPU。 从 ResourceSummary 中我们获知集群还有 2000核CPU,但事实上,这个集群甚至无法运行任何需要1核CPU以上的Pod实例。

因此,我们为每个集群引入了“自定义资源模型”的概念,来记录每个节点的资源画像。 Karmada将收集每个集群的节点和pod信息,并经过计算将这个节点被划分为对应等级的合适的资源模型。

启用自定义资源模型

自定义集群资源模型特性开关从Karmada v1.4后处于Beta阶段,并且默认开启。如果你使用Karmada v1.3,你需要在 karmada-schedulerkarmada-aggregated-serverkarmada-controller-manager 中开启 CustomizedClusterResourceModeling 特性开关。

例如,你可以使用以下命令打开 karmada-controller-manager 中的特性开关。

  1. kubectl --kubeconfig ~/.kube/karmada.config --context karmada-host edit deploy/karmada-controller-manager -nkarmada-system
  1. - command:
  2. - /bin/karmada-controller-manager
  3. - --kubeconfig=/etc/kubeconfig
  4. - --bind-address=0.0.0.0
  5. - --cluster-status-update-frequency=10s
  6. - --secure-port=10357
  7. - --feature-gates=CustomizedClusterResourceModeling=true
  8. - --v=4

在开启特性开关后,当集群注册到 Karmada 控制面时,Karmada会自动为集群设置一个通用的资源模型。你可以在 cluster.spec 中看到它。

默认的资源模型如下:

  1. resourceModels:
  2. - grade: 0
  3. ranges:
  4. - max: "1"
  5. min: "0"
  6. name: cpu
  7. - max: 4Gi
  8. min: "0"
  9. name: memory
  10. - grade: 1
  11. ranges:
  12. - max: "2"
  13. min: "1"
  14. name: cpu
  15. - max: 16Gi
  16. min: 4Gi
  17. name: memory
  18. - grade: 2
  19. ranges:
  20. - max: "4"
  21. min: "2"
  22. name: cpu
  23. - max: 32Gi
  24. min: 16Gi
  25. name: memory
  26. - grade: 3
  27. ranges:
  28. - max: "8"
  29. min: "4"
  30. name: cpu
  31. - max: 64Gi
  32. min: 32Gi
  33. name: memory
  34. - grade: 4
  35. ranges:
  36. - max: "16"
  37. min: "8"
  38. name: cpu
  39. - max: 128Gi
  40. min: 64Gi
  41. name: memory
  42. - grade: 5
  43. ranges:
  44. - max: "32"
  45. min: "16"
  46. name: cpu
  47. - max: 256Gi
  48. min: 128Gi
  49. name: memory
  50. - grade: 6
  51. ranges:
  52. - max: "64"
  53. min: "32"
  54. name: cpu
  55. - max: 512Gi
  56. min: 256Gi
  57. name: memory
  58. - grade: 7
  59. ranges:
  60. - max: "128"
  61. min: "64"
  62. name: cpu
  63. - max: 1Ti
  64. min: 512Gi
  65. name: memory
  66. - grade: 8
  67. ranges:
  68. - max: "9223372036854775807"
  69. min: "128"
  70. name: cpu
  71. - max: "9223372036854775807"
  72. min: 1Ti
  73. name: memory

自定义你的集群资源模型

在某些情况下,默认的集群资源模型可能与你的集群不相匹配。你可以调整集群资源模型的细粒度,以便更好地向集群下发资源。 例如,你可以使用以下命令编辑 member1 的集群资源模型。

  1. kubectl --kubeconfig ~/.kube/karmada.config --context karmada-apiserver edit cluster/member1

自定义资源模型应满足以下要求:

  • 每个模型的等级不应该是相同的。
  • 每个模型中资源类型的数量应该相同。
  • 目前只支持 cpu, memory, storage, ephemeral-storage四种资源类型。
  • 每个资源的最大值必须大于最小值。
  • 第一个模型中每个资源的最小值应为 0。
  • 最后一个模型中每个资源的最大值应为 MaxInt64。
  • 每个模型的资源类型应该相同。
  • 从低等级到高等级的模型,资源的范围必须连续且不重叠。

例如:以下给出了一个自定义的集群资源模型:

  1. resourceModels:
  2. - grade: 0
  3. ranges:
  4. - max: "1"
  5. min: "0"
  6. name: cpu
  7. - max: 4Gi
  8. min: "0"
  9. name: memory
  10. - grade: 1
  11. ranges:
  12. - max: "2"
  13. min: "1"
  14. name: cpu
  15. - max: 16Gi
  16. min: 4Gi
  17. name: memory
  18. - grade: 2
  19. ranges:
  20. - max: "9223372036854775807"
  21. min: "2"
  22. name: cpu
  23. - max: "9223372036854775807"
  24. min: 16Gi
  25. name: memory

上述是一个有三个等级的集群资源模型,每个等级分别定义了CPU和内存这两种资源的资源范围。这时如果一个节点的剩余可用资源为0.5核CPU和2Gi内存,则会被划分为0级的资源模型。如果这个节点的剩余可用资源为1.5核CPU和10Gi内存,则会被划分为1级。

基于自定义集群资源模型的调度

自定义集群资源模型将节点划分为不同区间的等级,并且当一个Pod实例需要调度到特定集群时,karmada-scheduler根据将要调度的实例资源请求比较不同集群中满足要求的节点数,并将实例调度到满足要求的节点数更多的集群。 假设有三个注册在Karmada控制面的成员集群,采用默认设置的集群资源模型,这些集群的剩余可用资源情况如下。

成员集群1:

  1. spec:
  2. ...
  3. - grade: 2
  4. ranges:
  5. - max: "4"
  6. min: "2"
  7. name: cpu
  8. - max: 32Gi
  9. min: 16Gi
  10. name: memory
  11. - grade: 3
  12. ranges:
  13. - max: "8"
  14. min: "4"
  15. name: cpu
  16. - max: 64Gi
  17. min: 32Gi
  18. name: memory
  19. ...
  20. ...
  21. status:
  22. - count: 1
  23. grade: 2
  24. - count: 6
  25. grade: 3

成员集群2:

  1. spec:
  2. ...
  3. - grade: 2
  4. ranges:
  5. - max: "4"
  6. min: "2"
  7. name: cpu
  8. - max: 32Gi
  9. min: 16Gi
  10. name: memory
  11. - grade: 3
  12. ranges:
  13. - max: "8"
  14. min: "4"
  15. name: cpu
  16. - max: 64Gi
  17. min: 32Gi
  18. name: memory
  19. ...
  20. ...
  21. status:
  22. - count: 4
  23. grade: 2
  24. - count: 4
  25. grade: 3

成员集群3:

  1. spec:
  2. ...
  3. - grade: 6
  4. ranges:
  5. - max: "64"
  6. min: "32"
  7. name: cpu
  8. - max: 512Gi
  9. min: 256Gi
  10. name: memory
  11. ...
  12. ...
  13. status:
  14. - count: 1
  15. grade: 6

假设这时过来一个Pod的调度请求,Pod的资源请求是3核CPU和20Gi内存。那么,Karmada认为所有满足等级2及以上的节点满足此要求。考虑到不同集群可用节点的数量,调度器更倾向于Pod调度到成员集群3。

Clustermember1member2member3
AvailableReplicas1 + 6 = 74 + 4 = 81 * min(32/3, 256/20) = 10

假设这时过来一个Pod的调度请求,Pod的资源请求是3核CPU和60Gi内存。那么,这时等级2的节点已经无法满足Pod所需所有资源的要求。考虑到不同集群可用节点的数量,调度器更倾向于Pod调度到成员集群1。

Clustermember1member2member3
AvailableReplicas6 1 = 64 1 = 41 * min(32/3, 256/60) = 4

禁用集群资源模型

在基于集群可用资源的动态副本分配场景中,调度器总是会参考资源模型来做出调度决策。 在资源建模的过程中,不论是通用集群资源建模还是自定义集群资源建模,Karmada都会从管理的所有集群中收集节点和Pod信息。 这在大规模场景中带来了不小的性能负担。

你可以通过在 karmada-controller-managerkarmada-agent 中将 --enable-cluster-resource-modeling 设置为 false 来禁用集群资源模型。