Workload Rebalancer

目标

一般情况下,工作负载类资源被调度后,会保持调度结果不变,其副本分布不会轻易发生变化。 现在,假设某些特殊情况下,您想主动触发一次重调度,可以通过使用 WorkloadRebalancer 来实现。

因此,本节将指导您如何使用 WorkloadRebalancer 来触发重调度。

前提条件

Karmada 及多个子集群已安装

运行安装命令:

  1. git clone https://github.com/karmada-io/karmada
  2. cd karmada
  3. hack/local-up-karmada.sh
  4. export KUBECONFIG=~/.kube/karmada.config:~/.kube/members.config

说明:

在开始之前,我们应该至少安装三个 kubernetes 集群,一个用于安装 Karmada 控制平面,另外两个作为成员集群。 为了方便,我们直接使用 hack/local-up-karmada.sh 脚本快速准备上述集群。

执行上述命令后,您将看到 Karmada 控制平面和多个成员集群已安装完成。

教程

第一步:创建一个 Deployment

首先准备一个名为 foo 的 Deployment,您可以创建一个新文件 deployment.yaml,内容如下:

deployment.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: foo
  5. labels:
  6. app: test
  7. spec:
  8. replicas: 3
  9. selector:
  10. matchLabels:
  11. app: foo
  12. template:
  13. metadata:
  14. labels:
  15. app: foo
  16. spec:
  17. terminationGracePeriodSeconds: 0
  18. containers:
  19. - image: nginx
  20. name: foo
  21. resources:
  22. limits:
  23. cpu: 10m
  24. memory: 10Mi
  25. ---
  26. apiVersion: policy.karmada.io/v1alpha1
  27. kind: PropagationPolicy
  28. metadata:
  29. name: default-pp
  30. spec:
  31. placement:
  32. clusterTolerations:
  33. - effect: NoExecute
  34. key: workload-rebalancer-test
  35. operator: Exists
  36. tolerationSeconds: 0
  37. clusterAffinity:
  38. clusterNames:
  39. - member1
  40. - member2
  41. replicaScheduling:
  42. replicaDivisionPreference: Weighted
  43. replicaSchedulingType: Divided
  44. weightPreference:
  45. dynamicWeight: AvailableReplicas
  46. resourceSelectors:
  47. - apiVersion: apps/v1
  48. kind: Deployment
  49. name: foo
  50. namespace: default

然后,运行下述命令来创建这些资源:

  1. kubectl --context karmada-apiserver apply -f deployment.yaml

您可以通过下述方式来检查该步骤是否成功:

  1. $ karmadactl --karmada-context karmada-apiserver get deploy foo
  2. NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
  3. foo member1 2/2 2 2 20s Y
  4. foo member2 1/1 1 1 20s Y

可以看到,2 个副本分发到 member1 集群,1 个副本分发到 member2 集群。

第二步:在 member1 集群添加 NoExecute 污点以模拟集群故障

1)运行以下命令将 NoExecute 污点添加到 member1 集群:

  1. $ karmadactl --karmada-context=karmada-apiserver taint clusters member1 workload-rebalancer-test:NoExecute
  2. cluster/member1 tainted

然后,由于集群故障转移,将触发重调度,并且所有副本将被分发到 member2 集群,您可以看到:

  1. $ karmadactl --karmada-context karmada-apiserver get deploy foo
  2. NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
  3. foo member2 3/3 3 3 57s Y

2)运行以下命令从 member1 集群中移除上述 NoExecute 污点:

  1. $ karmadactl --karmada-context=karmada-apiserver taint clusters member1 workload-rebalancer-test:NoExecute-
  2. cluster/member1 untainted

移除污点不会导致副本传播变化,因为调度结果是惰性的,所有副本将保持在 member2 集群中不变。

第三步:创建一个 WorkloadRebalancer 来触发重调度

为了触发上述资源的重调度,您可以创建一个新文件 workload-rebalancer.yaml,内容如下:

  1. apiVersion: apps.karmada.io/v1alpha1
  2. kind: WorkloadRebalancer
  3. metadata:
  4. name: demo
  5. spec:
  6. workloads:
  7. - apiVersion: apps/v1
  8. kind: Deployment
  9. name: foo
  10. namespace: default

然后运行以下命令来创建该资源:

  1. kubectl --context karmada-apiserver apply -f workload-rebalancer.yaml

您将得到 workloadrebalancer.apps.karmada.io/demo created 的结果,这意味着该资源创建成功。

第四步:检查 WorkloadRebalancer 的状态

运行以下命令:

  1. $ kubectl --context karmada-apiserver get workloadrebalancer demo -o yaml
  2. apiVersion: apps.karmada.io/v1alpha1
  3. kind: WorkloadRebalancer
  4. metadata:
  5. creationTimestamp: "2024-05-25T09:49:51Z"
  6. generation: 1
  7. name: demo
  8. spec:
  9. workloads:
  10. - apiVersion: apps/v1
  11. kind: Deployment
  12. name: foo
  13. namespace: default
  14. status:
  15. finishTime: "2024-05-25T09:49:51Z"
  16. observedGeneration: 1
  17. observedWorkloads:
  18. - result: Successful
  19. workload:
  20. apiVersion: apps/v1
  21. kind: Deployment
  22. name: foo
  23. namespace: default

因此,您可以在 workloadrebalancer/demostatus.observedWorkloads 字段中观察重调度的结果。 如上述结果所示,deployment/foo 已成功重新调度。

第五步:观察 WorkloadRebalancer 的实际效果。

您可以观察 deployment/foo 的副本实际分发状态:

  1. $ karmadactl --karmada-context karmada-apiserver get deploy foo
  2. NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
  3. foo member1 2/2 2 2 3m14s Y
  4. foo member2 1/1 1 1 4m37s Y

您可以看到重调度已完成,有2个副本迁移回到 member1 集群,而 member2 集群中原有的1个副本保持不变。

此外,您可以观察到由 default-scheduler 发出的调度事件,例如:

  1. $ kubectl --context karmada-apiserver describe deployment foo
  2. ...
  3. Events:
  4. Type Reason Age From Message
  5. ---- ------ ---- ---- -------
  6. ...
  7. Normal ScheduleBindingSucceed 3m34s (x2 over 4m57s) default-scheduler Binding has been scheduled successfully. Result: {member1:2, member2:1}
  8. Normal AggregateStatusSucceed 3m20s (x20 over 4m57s) resource-binding-status-controller Update resourceBinding(default/foo-deployment) with AggregatedStatus successfully.
  9. ...

第六步:更新并自动清理 WorkloadRebalancer

假设您希望 WorkloadRebalancer 能在将来自动清理,您只需编辑资源声明并将 spec.ttlSecondsAfterFinished 字段设置为 300,例如:

  1. apiVersion: apps.karmada.io/v1alpha1
  2. kind: WorkloadRebalancer
  3. metadata:
  4. name: demo
  5. spec:
  6. ttlSecondsAfterFinished: 300
  7. workloads:
  8. - apiVersion: apps/v1
  9. kind: Deployment
  10. name: foo
  11. namespace: default

在您应用了这个修改后,这个 WorkloadRebalancer 资源将在 300 秒后自动删除。