使用资源指标跨集群弹性扩缩容

在 Karmada 中,为了自动扩展工作负载以满足需求,FederatedHPA 会跨多个集群扩/缩容工作负载。

当负载增加时,如果 Pod 数量低于配置的最大值,FederatedHPA 会扩容工作负载(Deployment、StatefulSet 或其他类似资源)的副本。当负载减少时,如果 Pod 数量高于配置的最小值,FederatedHPA 会缩容工作负载的副本。

本文档将引导您完成这样一个案例:启用 FederatedHPA 来自动扩缩容跨集群部署的 nginx。

演示案例将执行以下操作:

federatedhpa-demo

  • member1 集群中存在一个 Deployment 的 Pod。
  • Service 部署在 member1member2 集群。
  • 请求多集群 Service 来提高 Pod 的 CPU 使用率。
  • Pod 副本将在 member1member2 集群中扩容。

前提条件

Karmada 已安装

您可以参考快速入门安装 Karmada,或直接运行 hack/local-up-karmada.sh 脚本,该脚本也用于运行 E2E 测试。

成员集群网络

确保至少已有两个集群加入 Karmada,并且成员集群之间的容器网络已连通。

  • 如果您使用 hack/local-up-karmada.sh 脚本部署 Karmada,Karmada 中会有 3 个成员集群,并且集群 member1member2 间的容器网络已连通。
  • 您可以使用 Submariner 或其他相关开源项目来连接成员集群之间的网络。

注意:为了防止路由冲突,集群中 Pod 和 Service 的 CIDR 必须互不重叠。

ServiceExport 和 ServiceImport 自定义资源已安装

我们需要在成员集群中安装 ServiceExportServiceImport 以启用多集群 Service。

Karmada 控制平面 上安装了 ServiceExportServiceImport 后,我们就可以创建 ClusterPropagationPolicy,将以下两个 CRD 分发到成员集群。

  1. # propagate ServiceExport CRD
  2. apiVersion: policy.karmada.io/v1alpha1
  3. kind: ClusterPropagationPolicy
  4. metadata:
  5. name: serviceexport-policy
  6. spec:
  7. resourceSelectors:
  8. - apiVersion: apiextensions.k8s.io/v1
  9. kind: CustomResourceDefinition
  10. name: serviceexports.multicluster.x-k8s.io
  11. placement:
  12. clusterAffinity:
  13. clusterNames:
  14. - member1
  15. - member2
  16. ---
  17. # propagate ServiceImport CRD
  18. apiVersion: policy.karmada.io/v1alpha1
  19. kind: ClusterPropagationPolicy
  20. metadata:
  21. name: serviceimport-policy
  22. spec:
  23. resourceSelectors:
  24. - apiVersion: apiextensions.k8s.io/v1
  25. kind: CustomResourceDefinition
  26. name: serviceimports.multicluster.x-k8s.io
  27. placement:
  28. clusterAffinity:
  29. clusterNames:
  30. - member1
  31. - member2

成员集群中已安装 metrics-server

我们需要为成员集群安装 metrics-server 以提供 metrics API,通过运行以下命令来安装:

  1. hack/deploy-k8s-metrics-server.sh ${member_cluster_kubeconfig} ${member_cluster_context_name}

如果您使用 hack/local-up-karmada.sh 脚本部署 Karmada,则可以运行以下命令在三个成员集群中部署 metrics-server

  1. hack/deploy-k8s-metrics-server.sh $HOME/.kube/members.config member1
  2. hack/deploy-k8s-metrics-server.sh $HOME/.kube/members.config member2
  3. hack/deploy-k8s-metrics-server.sh $HOME/.kube/members.config member3

Karmada 控制平面已安装 karmada-metrics-adapter

我们需要在 Karmada 控制平面中安装 karmada-metrics-adapter 以提供 metrics API,通过运行以下命令来安装:

  1. hack/deploy-metrics-adapter.sh ${host_cluster_kubeconfig} ${host_cluster_context} ${karmada_apiserver_kubeconfig} ${karmada_apiserver_context_name}

如果您使用 hack/local-up-karmada.sh 脚本部署 Karmada,将默认安装 karmada-metrics-adapter

member1member2 集群中部署 Deployment

我们需要在 member1member2 集群中部署 Deployment(1 个副本)和 Service。

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: nginx
  5. labels:
  6. app: nginx
  7. spec:
  8. replicas: 1
  9. selector:
  10. matchLabels:
  11. app: nginx
  12. template:
  13. metadata:
  14. labels:
  15. app: nginx
  16. spec:
  17. containers:
  18. - image: nginx
  19. name: nginx
  20. resources:
  21. requests:
  22. cpu: 25m
  23. memory: 64Mi
  24. limits:
  25. cpu: 25m
  26. memory: 64Mi
  27. ---
  28. apiVersion: v1
  29. kind: Service
  30. metadata:
  31. name: nginx-service
  32. spec:
  33. ports:
  34. - port: 80
  35. targetPort: 80
  36. selector:
  37. app: nginx
  38. ---
  39. apiVersion: policy.karmada.io/v1alpha1
  40. kind: PropagationPolicy
  41. metadata:
  42. name: nginx-propagation
  43. spec:
  44. resourceSelectors:
  45. - apiVersion: apps/v1
  46. kind: Deployment
  47. name: nginx
  48. - apiVersion: v1
  49. kind: Service
  50. name: nginx-service
  51. placement:
  52. clusterAffinity:
  53. clusterNames:
  54. - member1
  55. - member2
  56. replicaScheduling:
  57. replicaDivisionPreference: Weighted
  58. replicaSchedulingType: Divided
  59. weightPreference:
  60. staticWeightList:
  61. - targetCluster:
  62. clusterNames:
  63. - member1
  64. weight: 1
  65. - targetCluster:
  66. clusterNames:
  67. - member2
  68. weight: 1

部署完成后,您可以检查 Pod 和 Service 的分发情况:

  1. $ karmadactl get pods
  2. NAME CLUSTER READY STATUS RESTARTS AGE
  3. nginx-777bc7b6d7-mbdn8 member1 1/1 Running 0 9h
  4. $ karmadactl get svc
  5. NAME CLUSTER TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ADOPTION
  6. nginx-service member1 ClusterIP 10.11.216.215 <none> 80/TCP 9h Y
  7. nginx-service member2 ClusterIP 10.13.46.61 <none> 80/TCP 9h Y

在 Karmada 控制平面部署 FederatedHPA

接下来让我们在 Karmada 控制平面中部署 FederatedHPA。

  1. apiVersion: autoscaling.karmada.io/v1alpha1
  2. kind: FederatedHPA
  3. metadata:
  4. name: nginx
  5. spec:
  6. scaleTargetRef:
  7. apiVersion: apps/v1
  8. kind: Deployment
  9. name: nginx
  10. minReplicas: 1
  11. maxReplicas: 10
  12. behavior:
  13. scaleDown:
  14. stabilizationWindowSeconds: 10
  15. scaleUp:
  16. stabilizationWindowSeconds: 10
  17. metrics:
  18. - type: Resource
  19. resource:
  20. name: cpu
  21. target:
  22. type: Utilization
  23. averageUtilization: 10

部署完成后,您可以检查 FederatedHPA:

  1. $ kubectl --kubeconfig $HOME/.kube/karmada.config --context karmada-apiserver get fhpa
  2. NAME REFERENCE-KIND REFERENCE-NAME MINPODS MAXPODS REPLICAS AGE
  3. nginx Deployment nginx 1 10 1 9h

将 Service 导出到 member1 集群

正如前文所提到的,我们需要一个多集群 Service 来将请求转发到 member1member2 集群中的 Pod,因此让我们创建这个多集群 Service。

  • 在 Karmada 控制平面创建一个 ServiceExport 对象,然后创建一个 PropagationPolicyServiceExport 对象分发到 member1member2 集群。

    1. apiVersion: multicluster.x-k8s.io/v1alpha1
    2. kind: ServiceExport
    3. metadata:
    4. name: nginx-service
    5. ---
    6. apiVersion: policy.karmada.io/v1alpha1
    7. kind: PropagationPolicy
    8. metadata:
    9. name: serve-export-policy
    10. spec:
    11. resourceSelectors:
    12. - apiVersion: multicluster.x-k8s.io/v1alpha1
    13. kind: ServiceExport
    14. name: nginx-service
    15. placement:
    16. clusterAffinity:
    17. clusterNames:
    18. - member1
    19. - member2
  • 在 Karmada 控制平面创建一个 ServiceImport 对象,然后创建一个 PropagationPolicyServiceImport 对象分发到 member1 集群。

    1. apiVersion: multicluster.x-k8s.io/v1alpha1
    2. kind: ServiceImport
    3. metadata:
    4. name: nginx-service
    5. spec:
    6. type: ClusterSetIP
    7. ports:
    8. - port: 80
    9. protocol: TCP
    10. ---
    11. apiVersion: policy.karmada.io/v1alpha1
    12. kind: PropagationPolicy
    13. metadata:
    14. name: serve-import-policy
    15. spec:
    16. resourceSelectors:
    17. - apiVersion: multicluster.x-k8s.io/v1alpha1
    18. kind: ServiceImport
    19. name: nginx-service
    20. placement:
    21. clusterAffinity:
    22. clusterNames:
    23. - member1

部署完成后,您可以检查多集群 Service:

  1. $ karmadactl get svc
  2. NAME CLUSTER TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ADOPTION
  3. derived-nginx-service member1 ClusterIP 10.11.59.213 <none> 80/TCP 9h Y

在 member1 集群中安装 hey http 负载测试工具

为了发送 http 请求,这里我们使用 hey

  • 下载 hey 并复制到 kind 集群容器中。
  1. wget https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64
  2. chmod +x hey_linux_amd64
  3. docker cp hey_linux_amd64 member1-control-plane:/usr/local/bin/hey

测试扩容

  • 首先检查 Pod 的分发情况。

    1. $ karmadactl get pods
    2. NAME CLUSTER READY STATUS RESTARTS AGE
    3. nginx-777bc7b6d7-mbdn8 member1 1/1 Running 0 61m
  • 检查多集群 Service ip。

    1. $ karmadactl get svc
    2. NAME CLUSTER TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ADOPTION
    3. derived-nginx-service member1 ClusterIP 10.11.59.213 <none> 80/TCP 20m Y
  • 使用 hey 请求多集群 Service,以提高 nginx Pod 的 CPU 使用率。

    1. docker exec member1-control-plane hey -c 1000 -z 1m http://10.11.59.213
  • 等待 15 秒,副本将扩容,然后您可以再次检查 Pod 分发状态。

    1. $ karmadactl get pods -l app=nginx
    2. NAME CLUSTER READY STATUS RESTARTS AGE
    3. nginx-777bc7b6d7-c2cfv member1 1/1 Running 0 22s
    4. nginx-777bc7b6d7-mbdn8 member1 1/1 Running 0 62m
    5. nginx-777bc7b6d7-pk2s4 member1 1/1 Running 0 37s
    6. nginx-777bc7b6d7-tbb4k member1 1/1 Running 0 37s
    7. nginx-777bc7b6d7-znlj9 member1 1/1 Running 0 22s
    8. nginx-777bc7b6d7-6n7d9 member2 1/1 Running 0 22s
    9. nginx-777bc7b6d7-dfbnw member2 1/1 Running 0 22s
    10. nginx-777bc7b6d7-fsdg2 member2 1/1 Running 0 37s
    11. nginx-777bc7b6d7-kddhn member2 1/1 Running 0 22s
    12. nginx-777bc7b6d7-lwn52 member2 1/1 Running 0 37s

测试缩容

1 分钟后,负载测试工具将停止运行,然后您可以看到工作负载在多个集群中缩容。

  1. $ karmadactl get pods -l app=nginx
  2. NAME CLUSTER READY STATUS RESTARTS AGE
  3. nginx-777bc7b6d7-mbdn8 member1 1/1 Running 0 64m