diff --git a/content/en/blog/addon-rollout-zh/index.md b/content/en/blog/addon-rollout-zh/index.md new file mode 100644 index 00000000..6022b745 --- /dev/null +++ b/content/en/blog/addon-rollout-zh/index.md @@ -0,0 +1,531 @@ +--- +title: 以GitOps方式应对多集群工具链的升级挑战 +date: 2023-10-27 +author: 郝青 [@haoqing0110](https://github.com/haoqing0110) +toc_hide: true +--- + +## 多集群环境下工具链的升级挑战 + +OCM(open-cluster-management)是一个专注于 Kubernetes 应用跨多集群和多云的管理平台,提供了集群的注册,应用和负载的分发,调度等基础功能。Add-on 插件是 OCM 提供的一种基于基础组件的扩展机制,可以让 Kubernetes 生态的应用很容易迁移到 OCM 平台上,拥有跨多集群多云的编排和调度的能力。如 Istio,Prometheus,Submarine 可以通过 Add-on 的方式扩展至多集群。在多集群环境中,如何优雅、平滑地升级整个工具链(比如 Istio、Prometheus 和其他工具)是我们在多集群管理中遇到的挑战,工具链的升级失败可能会导致数千个用户工作负载无法访问。因此,找到一种简单、安全的跨集群升级解决方案变得非常重要。 + +本文我们将介绍 Open Cluster Management(OCM)如何将工具链升级视为配置文件的变更,使用户能够利用 Kustomize 或 GitOps 实现跨集群的无缝滚动/金丝雀升级。 + +在正式开始前,首先介绍几个 OCM 中的概念。 + +## add-on 插件 + +在 OCM 平台上,add-on 插件可以实现在不同托管集群(Spoke)上应用不同的配置,也可以实现从控制面(Hub)获取数据到 Spoke 集群上等功能。比如:你可以使用[managed-serviceaccount](https://github.com/open-cluster-management-io/managed-serviceaccount) +插件在 Spoke 集群上将指定的 ServiceaCount 信息返回给 Hub 集群,可以使用[cluster-proxy](https://github.com/open-cluster-management-io/cluster-proxy)插件建立一个从 spoke 到 hub 的反向代理通道。 + +现阶段 OCM 社区已经有的一些 add-on: + +- [Multicluster Mesh Addon](https://github.com/open-cluster-management-io/multicluster-mesh) 可用于管理(发现、部署和联合)OCM 中跨多个集群的服务网格。 +- [Submarine Addon](https://github.com/stolostron/submariner-addon) 让[Submarine](https://github.com/submariner-io/submariner) + 和 OCM 方便集成,在 hub cluster 上部署 Submariner Broker,在 managed cluster 上部署所需的 Submariner 组件, 为托管集群提供跨集群的 Pod 和 Service 网络互相访问的能力。 +- [Open-telemetry add-on](https://github.com/open-cluster-management-io/addon-contrib/tree/main/open-telemetry-addon) 自动在 hub cluster 和 managed cluster 上 + 安装 otelCollector,并在 hub cluster 上自动安装 jaeger-all-in-one 以处理和存储 traces。 +- [Application lifecycle management](https://open-cluster-management.io/zh/getting-started/integration/app-lifecycle/) + 实现多集群或多云环境中的应用程序生命周期管理。add-on 插件提供了一套通过 Subscriptions 订阅 channel,将 github 仓库,Helm release 或者对象存储仓库的应用分发到指定 Spoke 集群上的机制。 +- [Policy framework](https://open-cluster-management.io/getting-started/integration/policy-framework/)和[Policy controllers](https://open-cluster-management.io/getting-started/integration/policy-controllers/) add-on 插件可以让 Hub 集群管理员很轻松为 Spoke 集群部署安全相关的 policy 策略。 +- [Managed service account](https://open-cluster-management.io/getting-started/integration/managed-serviceaccount/) add-on 插件可以让 Hub 集群管理员很容易管理 Spoke 集群上 serviceaccount。 +- [Cluster proxy](https://open-cluster-management.io/getting-started/integration/cluster-proxy/) add-on 插件通过反向代理通道提供了 Hub 和 Spoke 集群之间 L4 网络连接。 + +**更多关于 add-on 插件的介绍可以参考[详解 OCM add-on 插件](https://open-cluster-management.io/zh/blog/addon-introduction/)。** + +OCM 提供了两种方式帮助开发者开发自己的 add-on: + +- Hard 模式:使用[addon-framework](https://github.com/open-cluster-management-io/addon-framework)的内置机制,可根据[Add-on 开发指南](https://open-cluster-management.io/developer-guides/addon/)来开发 add-on 插件的 addon manager 和 addon agent。 +- Easy 模式:OCM 提供了一个新的插件开发模型,可使用[AddOnTemplate](https://open-cluster-management.io/developer-guides/addon/#build-an-addon-with-addon-template)来构建 add-on。在此模型中开发者无需开发 addon manager,只需准备 addon agent 的 image 和 AddOnTemplate,AddOnTemplate 描述了如何部署 addon agent 以及如何注册 addon。 + +如下是一个样例 add-on 的 ClusterManagementAddOn 和 AddOnTemplate。AddOnTemplate 被视为 add-on 一个配置文件,定义在 supportedConfigs 中。AddOnTemplate 资源中则包含了部署 add-on 所需的 manifest 以及 add-on 的注册方式。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: hello-template + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + addOnMeta: + description: hello-template is a addon built with addon template + displayName: hello-template + supportedConfigs: # declare it is a template type addon + - group: addon.open-cluster-management.io + resource: addontemplates + defaultConfig: + name: hello-template +``` + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: AddOnTemplate +metadata: + name: hello-template +spec: + addonName: hello-template + agentSpec: # required + workload: + manifests: + - kind: Deployment + metadata: + name: hello-template-agent + namespace: open-cluster-management-agent-addon +... + - kind: ServiceAccount + metadata: + name: hello-template-agent-sa + namespace: open-cluster-management-agent-addon + - kind: ClusterRoleBinding + metadata: + name: hello-template-agent +... + registration: # optional + ... +``` + +## Placement Decision Strategy + +Placement API 用于在一个或多个托管集群组(ManagedClusterSet)中选择一组托管群集(ManagedCluster),以便将工作负载部署到这些群集上。 + +**更多关于 Placement API 的介绍可以参考[Placement 文档](https://open-cluster-management.io/concepts/placement/)。** + +Placement 调度过程的“输入”和“输出”被解耦为两个独立的 Kubernetes API: Placement 和 PlacementDecision。 + +- Placement 提供了通过标签选择器`labelSelector`或声明选择器`claimSelector`过滤集群,同时也提供了一些内置的优选器`prioritizer`,可对过滤后的集群进行打分排序和优先选择。 +- Placement 的调度结果会放在`PlacementDecision`中, `status.decisions`列出得分最高的前 N 个集群并按名称排序,且调度结果会随着集群的变化而动态变化。Placement 中的`decisionStrategy`部分可以用来将创建的`PlacementDecision`划分为多个组,并定义每个决策组中的集群数量。`PlacementDecision`支持分页显示,每个 resource 做多支持放置 100 个集群的名称。 + +如下是一个 Placement 和`decisionStrategy`的例子。假设 global 集群组中有 300 个托管集群(ManagedCluster),其中 10 个集群有标签 canary。下面的例子描述了将拥有 canary 标签的集群分为一组,并将剩下的集群以每组最多 150 个集群来进行分组。 + +```yaml +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: aws-placement + namespace: default +spec: + clusterSets: + - global + decisionStrategy: + groupStrategy: + clustersPerDecisionGroup: 150 + decisionGroups: + - groupName: canary + groupClusterSelector: + labelSelector: + matchExpressions: + - key: canary + operator: Exists + +``` + +分组的结果将显示在 Placement 的 status 中。其中 canary 组有 10 个集群,结果放在 aws-placement-decision-1 中。其他的默认分组只有 group index,每组分别有 150 个和 140 个集群。由于一个 PlacementDecsion 只支持 100 个集群,因此每组的结果放入两个 PlacementDecision 中。 + +```yaml +status: +... + decisionGroups: + - clusterCount: 10 + decisionGroupIndex: 0 + decisionGroupName: canary + decisions: + - aws-placement-decision-1 + - clusterCount: 150 + decisionGroupIndex: 1 + decisionGroupName: "" + decisions: + - aws-placement-decision-2 + - aws-placement-decision-3 + - clusterCount: 140 + decisionGroupIndex: 2 + decisionGroupName: "" + decisions: + - placement1-decision-3 + - placement1-decision-4 + numberOfSelectedClusters: 300 +``` + +以 canary 组为例,它的 PlacementDecision 如下所示,其中的标签 cluster.open-cluster-management.io/decision-group-index 代表了所属组的 index,cluster.open-cluster-management.io/decision-group-name 代表了所属组的名称,cluster.open-cluster-management.io/placement 代表了所属于的 Placement。使用者可以通过标签选择器来灵活获取调度结果。 + +```yaml +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: PlacementDecision +metadata: + labels: + cluster.open-cluster-management.io/decision-group-index: "0" + cluster.open-cluster-management.io/decision-group-name: canary + cluster.open-cluster-management.io/placement: aws-placement + name: aws-placement-decision-1 + namespace: default +status: + decisions: + - clusterName: cluster1 + reason: "" +... + - clusterName: cluster10 + reason: "" +``` + +## 以 GitOps 方式简化升级 + +以上简单介绍了 add-on template 和 placement decision strategy 的概念。 + +在 OCM 中,我们将 add-on 的升级视为其配置文件的升级,这里的配置可以是 AddOnTemplate,也可以是其他自定义的配置文件 AddOnDeploymentConfig。一次 add-on 的升级等同于一次配置文件的更新,这使得用户能够利用 Kustomize 或 GitOps 来进行无缝的跨集群滚动/金丝雀升级。RolloutStrategy 定义了升级策略,支持全部升级(All),按集群渐进升级(Progressive Per Cluster)和按集群组渐进升级(Progressive Per Group),并可定义一组 MandatoryDecisionGroups 来优先尝试新配置。 + +依照 GitOps 的四个原则,我们来看看 OCM 如何支持以 GitOps 的方式应对多集群环境下的升级挑战。 + +- 声明式 + +在`ClusterManagementAddOn`中可以声明 add-on 所使用的配置文件。配置文件可在全局的`supportedConfigs`中声明,该配置文件会应用到所有的`ManagedClusterAddOn`实例上。也可在`installStrategy`下不同的 placements 中声明,每个 Placement 所选择集群的`ManagedClusterAddOn`将拥有相同的配置文件,placements 中声明的配置会覆盖全局配置。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount +spec: + supportedConfigs: + - defaultConfig: + name: managed-serviceaccount-0.4.0 + group: addon.open-cluster-management.io + resource: addontemplates + installStrategy: + placements: + - name: aws-placement + namespace: default + configs: + - group: addon.open-cluster-management.io + resource: addondeploymentconfigs + name: managed-serviceaccount-addon-deploy-config + rolloutStrategy: + type: Progressive + progressive: + mandatoryDecisionGroups: + - groupName: "canary" + maxConcurrency: 1 + type: Placements +``` + +- 版本控制 + +add-on 配置文件名称或 spec 内容的变化会被认为是一个配置更改,会触发 add-on 的一次升级。用户可以利用 Kustomize 或 GitOps 来控制配置文件升级。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: AddOnTemplate +metadata: + name: managed-serviceaccount-0.4.0 +spec: + agentSpec: # required + workload: + manifests: + - kind: Deployment + metadata: + name: managed-serviceaccount-addon-agent + namespace: open-cluster-management-agent-addon +... + - kind: ServiceAccount + metadata: + name: managed-serviceaccount + namespace: open-cluster-management-agent-addon +… + registration: # optional +``` + +- 自动化 + +OCM 在 open-cluster-management-hub 命名空间下的组件 addon-manager-controller 是一个更通用的 addon manager,它会 watch 以下两种类型的 add-on 并负责维护此类 add-on 的生命周期,包括安装与升级。当配置文件的名称或者 spec 内容变化时,此组件会按照 rolloutStrategy 所定义的升级策略来升级 add-on。 + +- Hard 模式:使用最新[addon-framework](https://github.com/open-cluster-management-io/addon-framework)开发的 add-on,需要删除代码中的`WithInstallStrategy()`方法并在`ClusterManagementAddOn`添加 annotation `addon.open-cluster-management.io/lifecycle: "addon-manager"`。详细内容参考[Add-on 开发指南](https://open-cluster-management.io/developer-guides/addon/#managing-the-add-on-agent-lifecycle-by-addon-manager)。 +- Easy 模式:使用 AddOnTemplate 模式开发的 add-on。 + +```bash +✗ kubectl get deploy -n open-cluster-management-hub +NAME READY UP-TO-DATE AVAILABLE AGE +cluster-manager-addon-manager-controller 1/1 1 1 10h +cluster-manager-placement-controller 1/1 1 1 10h +cluster-manager-registration-controller 1/1 1 1 10h +cluster-manager-registration-webhook 1/1 1 1 10h +cluster-manager-work-webhook 1/1 1 1 10h +``` + +- 持续协调 + +Add-on 配置文件的 spec hash 会被记录在`ClusterManagementAddOn`以及`ManagedClusterAddOn`的 status 中,当 spec hash 变化时,addon-manager-controller 会根据 rolloutStrategy 定义的升级策略持续更新 add-on,直至 lastAppliedConfig,lastKnownGoodConfig 和 desiredConfig 相一致。如下例子中,由于 lastAppliedConfig 与 desiredConfig 不匹配,add-on 状态显示为升级中。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount +… + status: + installProgressions: + - conditions: + - lastTransitionTime: "2023-09-21T06:53:59Z" + message: 1/3 upgrading, 0 timeout. + reason: Upgrading + status: "False" + type: Progressing + configReferences: + - desiredConfig: + name: managed-serviceaccount-0.4.1 + specHash: dcf88f5b11bd191ed2f886675f967684da8b5bcbe6902458f672277d469e2044 + group: addon.open-cluster-management.io + lastAppliedConfig: + name: managed-serviceaccount-0.4.0 + specHash: 1f7874ac272f3e4266f89a250d8a76f0ac1c6a4d63d18e7dcbad9068523cf187 + lastKnownGoodConfig: + name: managed-serviceaccount-0.4.0 + specHash: 1f7874ac272f3e4266f89a250d8a76f0ac1c6a4d63d18e7dcbad9068523cf187 + resource: addontemplates + name: aws-placementl + namespace: default +``` + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ManagedClusterAddOn +metadata: + name: managed-serviceaccount + namespace: cluster1 +… +status: + conditions: + - lastTransitionTime: "2023-09-21T06:53:42Z" + message: upgrading. + reason: Upgrading + status: "False" + type: Progressing + configReferences: + - desiredConfig: + name: managed-serviceaccount-0.4.1 + specHash: dcf88f5b11bd191ed2f886675f967684da8b5bcbe6902458f672277d469e2044 + group: addon.open-cluster-management.io + lastAppliedConfig: + name: managed-serviceaccount-0.4.0 + specHash: dcf88f5b11bd191ed2f886675f967684da8b5bcbe6902458f672277d469e2044 + lastObservedGeneration: 1 + name: managed-serviceaccount-0.4.1 + resource: addontemplates +``` + +## 三种升级策略 + +ClusterManagementAddOn 的`rolloutStrategy`字段定义了升级的策略,目前 OCM 支持三种类型的升级策略。 + +- 全部升级(All) + +默认的升级类型是 All,意味着新的配置文件会立刻应用于所有的集群。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + rolloutStrategy: + type: All + type: Placement +``` + +- 按集群渐进升级(Progressive Per Cluster) + +Progressive 意味着将新的配置文件依次部署在所选择的每个集群,只有当前集群升级成功后新的配置文件才会应用到下个集群。前面我们介绍了 Placement Decision Group 的概念,MandatoryDecisionGroups 中可以指定一个或多个 Decision Group。如果定义了 MandatoryDecisionGroups,则优先将新的配置文件部署到这些集群组。 MaxConcurrency 定义了同时部署的最大集群数量。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + rolloutStrategy: + type: Progressive + progressive: + mandatoryDecisionGroups: + - groupName: "canary" + maxConcurrency: 1 + type: Placements +``` + +- 按集群组渐进升级(Progressive Per Group) + +ProgressivePerGroup 意味着将新的配置文件依次部署在所选择的每个集群组,只有当前集群组升级成功后新的配置文件才会应用到下个集群组。如果定义了 MandatoryDecisionGroups,则优先将新的配置文件部署到这些集群组。如果没有 mandatoryDecisionGroups,则按照集群组的 index 顺序依次升级。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + rolloutStrategy: + type: ProgressivePerGroup + progressivePerGroup: + mandatoryDecisionGroups: + - groupName: "canary" + type: Placements +``` + +依照 GitOps 的四个原则,和 OCM 的三种升级策略,使用者可以利用 Kustomize 或 GitOps 实现跨集群的无缝滚动/金丝雀升级。值得注意的是,installStrategy 下支持多个 Placement 的定义,使用者可以基于此实现更多高级的升级策略。如下面的例子,可以同时定义两个 Placement 分别选择 aws 与 gcp 上的集群,使得同一个 add-on 在不同的集群中使用不同的配置文件和升级策略。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + configs: + - group: addon.open-cluster-management.io + resource: addondeploymentconfigs + name: managed-serviceaccount-addon-deploy-config-aws + rolloutStrategy: + type: ProgressivePerGroup + progressivePerGroup: + mandatoryDecisionGroups: + - groupName: "canary" + type: Placements + - name: gcp-placement + namespace: default + configs: + - group: addon.open-cluster-management.io + resource: addondeploymentconfigs + name: managed-serviceaccount-addon-deploy-config-gcp + rolloutStrategy: + type: ProgressivePerGroup + progressivePerGroup: + mandatoryDecisionGroups: + - groupName: "canary" + type: Placements +``` + +## 三种升级配置 + +`rolloutStrategy`升级策略中还可以定义`MinSuccessTime`, `ProgressDeadline`和`MaxFailures`来实现更细粒度的升级配置。 + +- MinSuccessTime + +`MinSuccessTime`定义了当addon升级成功且未达到`MaxFailures`时,controller需要等待多长时间才能继续升级下一个集群。默认值是0代码升级成功后立刻升级下一个集群。如下例子中,将按照每5分钟一个集群的速度升级addon。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + rolloutStrategy: + type: Progressive + progressive: + mandatoryDecisionGroups: + - groupName: "canary" + maxConcurrency: 1 + minSuccessTime: "5m" + type: Placements +``` + +- ProgressDeadline + +`ProgressDeadline`定义了controller等待addon升级成功的最大时间,在此时间之后将addon视为超时“timeout”并计入`MaxFailures`。超过`MaxFailures`时将停止升级。默认值为“None”代表controller会一直等待addon升级成功。 +如下例子中,controller会在每个集群上等待10分钟直到addon升级成功,若超过10分钟未成功,将标记该集群升级状态为timeout。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + rolloutStrategy: + type: Progressive + progressive: + mandatoryDecisionGroups: + - groupName: "canary" + maxConcurrency: 1 + progressDeadline: "10m" + type: Placements +``` + +- MaxFailures + +`MaxFailures`定义了可以容忍的升级失败的集群数量,可以是一个数值或者百分比。集群状态为failed或者timeout均视为升级失败,失败的集群超过`MaxFailures`后将停止升级。 +如下例子中,当有3个addon升级失败或者超过10分钟未升级成功,将停止升级。 + +```yaml +apiVersion: addon.open-cluster-management.io/v1alpha1 +kind: ClusterManagementAddOn +metadata: + name: managed-serviceaccount + annotations: + addon.open-cluster-management.io/lifecycle: "addon-manager" +spec: + supportedConfigs: +... + installStrategy: + placements: + - name: aws-placement + namespace: default + rolloutStrategy: + type: Progressive + progressive: + mandatoryDecisionGroups: + - groupName: "canary" + maxConcurrency: 1 + maxFailures: 2 + progressDeadline: "10m" + type: Placements +``` + +## 小结 + +本文详细介绍了如何使用 Open Cluster Management 以 GitOps 方式应对多集群环境下工具链的升级挑战。OCM 提供了基于 Kubernetes 的跨多集群和多云的管理平台,通过 Add-on 插件和 Placement API,使得用户能够优雅、平滑地升级整个工具链。同时,OCM 将 add-on 升级视为配置文件的变更,使得用户能够利用 Kustomize 或 GitOps 实现跨集群的无缝滚动/金丝雀升级。此外,OCM 还提供了多种升级策略,包括全部升级(All),按集群渐进升级(Progressive Per Cluster)和按集群组渐进升级(Progressive Per Group),以满足不同的升级需求。 + +## 未来计划 + +在社区中,我们正在计划实现[RolloutConfig](https://github.com/open-cluster-management-io/api/pull/281)以提供更细粒度的 rollout 配置,比如 MinSuccessTime, ProgressDeadline, MaxFailures,使得用户可以定义在失败情况下的升级行为,这将为多集群下的升级提供更多的可操作空间。 \ No newline at end of file diff --git a/content/en/blog/addon-rollout/index.md b/content/en/blog/addon-rollout/index.md index ad0cdb08..9cacc204 100644 --- a/content/en/blog/addon-rollout/index.md +++ b/content/en/blog/addon-rollout/index.md @@ -1,7 +1,7 @@ --- title: Using the GitOps way to deal with the upgrade challenges of multi-cluster tool chains date: 2024-01-19 -author: Hao Qing [@haoqing0110](https://github.com/haoqing0110) +author: Qing Hao [@haoqing0110](https://github.com/haoqing0110) toc_hide: true --- diff --git a/content/en/blog/extending-multicluster-scheduling-capabilities-zh/assets/extend-multicluster-scheduling-capabilities.png b/content/en/blog/extending-multicluster-scheduling-capabilities-zh/assets/extend-multicluster-scheduling-capabilities.png new file mode 100644 index 00000000..f8cd1f5b Binary files /dev/null and b/content/en/blog/extending-multicluster-scheduling-capabilities-zh/assets/extend-multicluster-scheduling-capabilities.png differ diff --git a/content/en/blog/extending-multicluster-scheduling-capabilities-zh/index.md b/content/en/blog/extending-multicluster-scheduling-capabilities-zh/index.md new file mode 100644 index 00000000..eddef083 --- /dev/null +++ b/content/en/blog/extending-multicluster-scheduling-capabilities-zh/index.md @@ -0,0 +1,328 @@ +--- +title: 使用OCM让多集群调度更具可扩展性 +date: 2023-05-10 +author: 郝青 [@haoqing0110](https://github.com/haoqing0110) +toc_hide: true +--- + +## 背景问题 + +OCM Placement API 可以动态的在多集群环境中选择一组托管集群`ManagedCluster`,以便将工作负载部署到这些集群上。 + +在上一篇[CNCF 沙箱项目 OCM Placement 多集群调度指南](https://mp.weixin.qq.com/s/_k2MV4b3hfTrLUCCOKOG8g)中,我们详细介绍了 Placement 的基本概念,提供的调度功能以及调度流程。同时还通过示例展示了如何在不同的应用场景下使用 Placement API。建议首次接触 Placement 的读者先阅读此文。 + +Placement 提供了通过标签选择器`labelSelector`或声明选择器`claimSelector`过滤集群,同时也提供了一些内置的优选器`prioritizer`,可对过滤后的集群进行打分排序和优先选择。 +内置的`prioritizer`中包括了最大可分配 CPU 资源(ResourceAllocatableCPU)和最大可分配内存资源(ResourceAllocatableMemory),它们提供了根据集群的可分配 CPU 和内存进行调度的能力。但是,由于集群的"AllocatableCPU"和"AllocatableMemory"是静态值,即使"集群资源不足",它们也不会改变。这导致在实际使用中,这两个`prioritizer`不能满足基于实时可用 CPU 或内存进行调度的需求。此外,使用者还可能需要根据从集群中获取的资源监控数据进行调度,这些都是内置的`prioritizer`无法满足的需求。 + +以上这些需求要求 Placement 能够更灵活的根据第三方数据来进行调度。为此,我们实现了一种更具扩展性的方式来支持基于第三方数据的调度,使用者可以使用自定义的分数来选择集群。 + +本文将介绍 OCM 是如何让多集群调度更具可扩展性,并通过实例展示如何实现一个第三方数据控制器`controller`来扩展 OCM 的多集群调度功能。 + +## OCM 如何让调度具有可扩展性 + +为了实现基于第三方数据的调度,OCM 引入了 API `AddOnPlacementScore`,它支持存储自定义的集群分数,使用者可以在 Placement 中指定使用此分数选择集群。 + +如下是一个`AddOnPlacementScore`的例子,更多关于 API 的细节可访问[types_addonplacementscore.go](https://github.com/open-cluster-management-io/api/blob/main/cluster/v1alpha1/types_addonplacementscore.go "types_addonplacementscore.go")。 + +```yaml +apiVersion: cluster.open-cluster-management.io/v1alpha1 +kind: AddOnPlacementScore +metadata: + name: default + namespace: cluster1 +status: + conditions: + - lastTransitionTime: "2021-10-28T08:31:39Z" + message: AddOnPlacementScore updated successfully + reason: AddOnPlacementScoreUpdated + status: "True" + type: AddOnPlacementScoreUpdated + validUntil: "2021-10-29T18:31:39Z" + scores: + - name: "cpuAvailable" + value: 66 + - name: "memAvailable" + value: 55 +``` + +`AddOnPlacementScore`的主要内容都在`status`中,因为我们不希望使用者更新它。`AddOnPlacementScore`的生命周期维护及`scores`的更新应该由第三方`controller`负责。 + +- `conditions`包括了资源不同的条件状态。 +- `scores`是一个列表,包含了一组分数的名称和值。在上例中,`scores`包含了自定义分数 cpuAvailable 和 memAvailable。 +- `validUntil`定义了`scores`的有效时间。在此时间之后,分数被 Placement 视为无效,nil 代表永不过期。controller 需要在更新 score 时更新此字段,保证分数是最新状态。 + +作为使用者,需要知道`AddOnPlacementScore`的资源名称`default`和`socre`名称`cpuAvailable` `memAvailable`。之后可在 Placement 中指定用此分数选择集群。 + +例如,下面的 Placement 想要选择具有最高`cpuAvailable`分数的前 3 个集群。 + +```yaml +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: placement + namespace: ns1 +spec: + numberOfClusters: 3 + prioritizerPolicy: + mode: Exact + configurations: + - scoreCoordinate: + type: AddOn + addOn: + resourceName: default + scoreName: cpuAvailable + weight: 1 +``` + +[32-extensiblescheduling](https://github.com/open-cluster-management-io/enhancements/blob/main/enhancements/sig-architecture/32-extensiblescheduling/32-extensiblescheduling.md "32-extensiblescheduling")包含了关于此设计的详细内容。 + +接下来,将用一个示例展示如何实现一个 controller 来更新`score`,并使用此`score`选择集群。 + +## 示例 + +示例代码位于 GitHub 仓库[resource-usage-collect-addon](https://github.com/open-cluster-management-io/addon-contrib/tree/main/resource-usage-collect-addon "resource-usage-collect-addon")。它提供的分数可实时反映集群的 CPU 和内存利用率。 + +示例使用 OCM [addon-framework](https://github.com/open-cluster-management-io/addon-framework "addon-framework") 进行开发,它可以作为一个 addon 插件被安装到每个`ManagedCluster`上,并将集群的`score`更新到对应的`AddOnPlacementScore`中。(本文不涉及 addon 开发细节,详细内容可参考[add-on 开发指南](https://open-cluster-management.io/developer-guides/addon/ "add-on开发指南")。) + +resource-usage-collect addon 遵循`hub-agent`的架构,如下所示。 + +![](./assets/extend-multicluster-scheduling-capabilities.png) + +resource-usage-collect addon 包括了一个 hub 上的 manager 和 managed cluster 上的 agent(绿色部分)。 + +工作流程为: + +- hub 上运行 addon 的 manager,它负责在 hub 上为每个 agent 创建部署所需的`ManifestWork`。 +- 在每个 managed cluster 上,work agent 负责监控 hub 上的`ManifestWork`并在 managed cluster 上安装 agent。 +- agent 是 addon 的核心部分,它负责为每个 managed cluster 创建`AddonPlacementScore`,并每 60 秒刷新一次`scores`和`validUntil`。 +- 当`AddonPlacementScore`创建完成,用户便可以在`Placement`中指定`AddOnPlacementScore`的资源名称和`score`名称,根据分数来选择集群。 +- Placement controller 会在每个集群的命名空间中获取`AddOnPlacementScore`资源,在`scores`列表中读取分数,并使用该分数对集群进行打分排序。 + +上述是`AddonPlacementScore`和 placement controller 的工作流程,非常容易理解。下面我们来试着运行样例代码。 + +**准备 OCM 环境(包含 2 个`ManagedCluster`)** + +1. 运行[setup dev environment by kind](https://github.com/open-cluster-management-io/OCM/tree/main/solutions/setup-dev-environment "setup dev environment by kind")准备环境。 + +```bash +curl -sSL https://raw.githubusercontent.com/open-cluster-management-io/OCM/main/solutions/setup-dev-environment/local-up.sh | bash +``` + +2. 确认两个`ManagedCluster`和一个默认的`ManagedClusterSet`创建完成。 + +```bash +$ clusteradm get clusters +NAME ACCEPTED AVAILABLE CLUSTERSET CPU MEMORY KUBERENETES VERSION +cluster1 true True default 24 49265496Ki v1.23.4 +cluster2 true True default 24 49265496Ki v1.23.4 + +$ clusteradm get clustersets +NAME BOUND NAMESPACES STATUS +default 2 ManagedClusters selected +``` + +3. 将默认`ManagedClusterSet`绑定到 default`Namespace`。 + +```bash +clusteradm clusterset bind default --namespace default +``` + +```bash +$ clusteradm get clustersets +NAME BOUND NAMESPACES STATUS +default default 2 ManagedClusters selected +``` + +**安装 resource-usage-collect addon** + +1. 下载源代码。 + +```bash +git clone git@github.com:open-cluster-management-io/addon-contrib.git +cd addon-contrib/resource-usage-collect-addon +``` + +2. 编译容器镜像。 + +```bash +# Set image name, this is an optional step. +export IMAGE_NAME=quay.io/haoqing/resource-usage-collect-addon:latest +# Build image +make images +``` + +如果你使用了 kind,需要手工将镜像加载到 kind 环境中。 + +```bash +kind load docker-image $IMAGE_NAME --name # kind load docker-image $IMAGE_NAME --name hub +``` + +3. 部署 resource-usage-collect addon。 + +```bash +make deploy +``` + +4. 验证安装成功。 + +在 hub 集群上, 验证 resource-usage-collect-controller pod 运行成功。 + +```bash +$ kubectl get pods -n open-cluster-management | grep resource-usage-collect-controller +resource-usage-collect-controller-55c58bbc5-t45dh 1/1 Running 0 71s +``` + +在 hub 集群上, 验证每个 managed cluster 生成了对应的`AddonPlacementScore`。 + +```bash +$ kubectl get addonplacementscore -A +NAMESPACE NAME AGE +cluster1 resource-usage-score 3m23s +cluster2 resource-usage-score 3m24s +``` + +`AddonPlacementScore`的 status 中应该包含了如下的分数。 + +```bash +$ kubectl get addonplacementscore -n cluster1 resource-usage-score -oyaml +apiVersion: cluster.open-cluster-management.io/v1alpha1 +kind: AddOnPlacementScore +metadata: + creationTimestamp: "2022-08-08T06:46:04Z" + generation: 1 + name: resource-usage-score + namespace: cluster1 + resourceVersion: "3907" + uid: 6c4280e4-38be-4d45-9c73-c18c84799781 +status: + scores: + - name: cpuAvailable + value: 12 + - name: memAvailable + value: 4 +``` + +如果`AddonPlacementScore`没有生成或者 status 中没有分数,可以登陆到 managed cluster 上,检查 resource-usage-collect-agent pod 是否正常运行。 + +```bash +$ kubectl get pods -n default | grep resource-usage-collect-agent +resource-usage-collect-agent-5b85cbf848-g5kqm 1/1 Running 0 2m +``` + +**通过自定义分数选择集群** + +如果上述步骤运行正常,接下来我们可以试着创建一个`Placement`并通过自定义分数选择集群。 + +1. 创建一个`Placement`选择具有最高 cpuAvailable 分数的集群。 + +当`scoreCoordinate`的类型`type`定义为`AddOn`时,placement controller 会在每个集群的命名空间中获取名称为`resource-usage-score`的`AddOnPlacementScore`资源,在`scores`列表中读取分数`cpuAvailable`,并使用该分数对集群进行打分排序。 + +```bash +cat << EOF | kubectl apply -f - +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: placement1 + namespace: default +spec: + numberOfClusters: 1 + clusterSets: + - default + prioritizerPolicy: + mode: Exact + configurations: + - scoreCoordinate: + type: AddOn + addOn: + resourceName: resource-usage-score + scoreName: cpuAvailable + weight: 1 +EOF +``` + +2. 验证`PlacementDecision`。 + +```bash +$ kubectl describe placementdecision -n default | grep Status -A 3 +Status: + Decisions: + Cluster Name: cluster1 + Reason: +``` + +可以看到 Cluster1 被选中,出现在`PlacementDecision`的结果中。 + +运行如下命令获取`AddonPlacementScore`的自定义分数。可以看到"cpuAvailable"的分数是 12。 + +```bash +$ kubectl get addonplacementscore -A -o=jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.status.scores}{"\n"}{end}' +cluster1 [{"name":"cpuAvailable","value":12},{"name":"memAvailable","value":4}] +cluster2 [{"name":"cpuAvailable","value":12},{"name":"memAvailable","value":4}] +``` + +在`Placement`的 events 也可以看到集群的分数是 12 分。这表明自定义分数被直接用于对集群进行打分和排序。由于上述 placement 中 numberOfClusters 定义为 1,最终只有 cluster1 被选中。 + +```bash +$ kubectl describe placement -n default placement1 | grep Events -A 10 +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal DecisionCreate 50s placementController Decision placement1-decision-1 is created with placement placement1 in namespace default + Normal DecisionUpdate 50s placementController Decision placement1-decision-1 is updated with placement placement1 in namespace default + Normal ScoreUpdate 50s placementController cluster1:12 cluster2:12 +``` + +## 如何实现自定义分数控制器 + +现在你已经知道了如何安装 resource-usage-collect addon 并使用自定义分数来选择群集。接下来,让我们深入了解在实现自定义分数控制器`controller`时需要考虑的一些关键点。 + +### 1. 在哪里运行自定义分数控制器 (controller) + +Controller 可以在 hub 集群或 managed cluster 上运行。可以结合具体的使用场景,选择将 controller 运行在何处。 + +比如,在我们的示例中,自定义分数控制器`controller`是使用 addon-famework 开发的,它遵循 hub-agent 架构。resource-usage-collect-agent 真正运行自定义分数程序,它安装在每个 managed cluster 上,获取 managed cluster 的可用 CPU 和内存,计算分数,并将其更新到`AddonPlacementScore`中。resource-usage-collect-controller 只负责安装代理 agent。 + +在其他情况下,例如,如果想使用 Thanos 中的指标为每个 managed cluster 计算得分,则自定义分数控制器`controller`需要放置在 hub 上,因为 Thanos 有从每个 managed cluster 收集的所有指标。 + +### 2. 如何维护`AddOnPlacementScore`的生命周期 + +在我们的示例中,维护`AddonPlacementScore`的代码位于[pkg/addon/agent/agent.go](https://github.com/open-cluster-management-io/addon-contrib/blob/main/resource-usage-collect-addon/pkg/addon/agent/agent.go "pkg/addon/agent/agent.go")中。 + +- 何时创建`AddonPlacementScore`? + + `AddonPlacementScore`可以在 managed cluster 创建完成后创建,或者按需创建以减少 hub 上的 resource。 + + 在上述示例中,addon 在 managed cluster 创建完成后,为每个 managed cluster 创建对应的`AddonPlacementScore`,并且生成初始分数。 + +- 何时更新`AddonPlacementScore`? + + 可以在监视数据发生变化时更新分数,或者至少在`ValidUntil`到期之前更新分数。 + 我们建议在更新分数时设置`ValidUntil`,以便 placement controller 可以知道分数是否仍然有效,防止分数长时间未能更新的情况。 + + 在上述示例中,除了每 60 秒重新计算和更新分数外,当 managed cluster 中的节点或 Pod 资源发生更改时,也将触发更新。 + +### 3. 如何计算分数 + +计算分数的代码位于[pkg/addon/agent/calculate.go](https://github.com/open-cluster-management-io/addon-contrib/blob/main/resource-usage-collect-addon/pkg/addon/agent/calculate.go "pkg/addon/agent/calculate.go")。有效的得分必须在-100 至 100 的范围内,你需要在将分数更新到`AddOnPlacementScore`之前将其归一化。在归一化分数时,可能会遇到以下情况。 + +- 分数提供程序知道自定义分数的最大值和最小值。 + + 在这种情况下,可以通过公式轻松实现平滑映射。假设实际值为 X,并且 X 在间隔[min,max]中,则得分=200 \*(x-min)/(max-min)-100 + +- 分数提供程序不知道自定义分数的最大值和最小值。 + + 在这种情况下,需要自己设置最大值和最小值,因为如果没有最大值和最小值,则无法将单个值 X 映射到范围[-100,100]。 + 然后,当 X 大于此最大值时,可以认为群集足够健康可以部署应用程序,可以将分数设置为 100。如果 X 小于最小值,则可以将分数设置为-100。 + + ``` + if X >= max + score = 100 + if X <= min + score = -100 + ``` + +在我们的示例中,运行在每个托管群集上的 resource-usage-collect-agent 没有全局视角,无法知道所有群集的 CPU/内存使用率的最大值/最小值,因此我们在代码中手动将最大值设置为`MAXCPUCOUNT`和`MAXMEMCOUNT`,最小值设置为 0。分数计算公式可以简化为:`score = x / max * 100`。 + +## 总结 + +在本文中,我们介绍了什么是OCM的可扩展调度,并使用示例展示了如何实现自定义分数控制器。此外,本文列出了开发者在实现第三方分数控制器时需要考虑的3个关键点。希望阅读本文后,您可以清楚地了解到如何使用OCM 来扩展多集群调度能力。 \ No newline at end of file diff --git a/content/en/blog/extending-multicluster-scheduling-capabilities-with-ocm-placement/index.md b/content/en/blog/extending-multicluster-scheduling-capabilities/index.md similarity index 82% rename from content/en/blog/extending-multicluster-scheduling-capabilities-with-ocm-placement/index.md rename to content/en/blog/extending-multicluster-scheduling-capabilities/index.md index fb4441fc..f3db637d 100644 --- a/content/en/blog/extending-multicluster-scheduling-capabilities-with-ocm-placement/index.md +++ b/content/en/blog/extending-multicluster-scheduling-capabilities/index.md @@ -1,7 +1,7 @@ --- title: Extending the Multicluster Scheduling Capabilities with Open Cluster Management Placement date: 2022-09-15 -author: Qing Hao +author: Qing Hao [@haoqing0110](https://github.com/haoqing0110) toc_hide: true --- diff --git a/content/en/blog/kubecon-cn-2024-boundaryless-computing-optimizing-llm-performance-cost-and-efficiency-in-multi-cloud-architecture/index.md b/content/en/blog/kubecon-cn-2024-boundaryless-computing-optimizing-llm-performance-cost-and-efficiency-in-multi-cloud-architecture/index.md new file mode 100644 index 00000000..76375e51 --- /dev/null +++ b/content/en/blog/kubecon-cn-2024-boundaryless-computing-optimizing-llm-performance-cost-and-efficiency-in-multi-cloud-architecture/index.md @@ -0,0 +1,10 @@ +--- +title: "KubeCon CN 2024 - Boundaryless Computing: Optimizing LLM Performance, Cost, and Efficiency in Multi-Cloud Architecture | 无边界计算:在多云架构中优化LLM性能、成本和效率" +date: 2024-08-21 +authors: + - Jian Zhu, Red Hat + - Kai Zhang, Alibaba Cloud Intelligence +toc_hide: true +--- + +Read more at [KubeCon CN 2024 - Boundaryless Computing: Optimizing LLM Performance, Cost, and Efficiency in Multi-Cloud Architecture](https://kccncossaidevchn2024.sched.com/event/1eYXG/boundaryless-computing-optimizing-llm-performance-cost-and-efficiency-in-multi-cloud-architecture-yi-dui-dou-zhao-daepnano-llmxia-reyi-jian-zhu-red-hat-kai-zhang-alibaba-cloud-intelligence). \ No newline at end of file diff --git a/content/en/blog/kubecon-cn-2024-connecting-the-dots-towards-a-unified-multi-cluster-aiml-experience/index.md b/content/en/blog/kubecon-cn-2024-connecting-the-dots-towards-a-unified-multi-cluster-aiml-experience/index.md new file mode 100644 index 00000000..eb249496 --- /dev/null +++ b/content/en/blog/kubecon-cn-2024-connecting-the-dots-towards-a-unified-multi-cluster-aiml-experience/index.md @@ -0,0 +1,10 @@ +--- +title: "KubeCon CN 2024 - Connecting the Dots: Towards a Unified Multi-Cluster AI/ML Experience | 连接点:走向统一的多集群AI/ML体验" +date: 2024-08-21 +authors: + - Qing Hao, Red Hat + - Chen Yu, Microsoft +toc_hide: true +--- + +Read more at [KubeCon CN 2024 - Connecting the Dots: Towards a Unified Multi-Cluster AI/ML Experience](https://kccncossaidevchn2024.sched.com/event/1eYXc/connecting-the-dots-towards-a-unified-multi-cluster-aiml-experience-pu-daepyu-ni-zha-zhong-shi-aimlmo-qing-hao-redhat-chen-yu-microsoft). \ No newline at end of file diff --git a/content/en/blog/kubecon-cn-2024-extend-kubernetes-to-edge-using-event-based-transport/index.md b/content/en/blog/kubecon-cn-2024-extend-kubernetes-to-edge-using-event-based-transport/index.md new file mode 100644 index 00000000..bb644aca --- /dev/null +++ b/content/en/blog/kubecon-cn-2024-extend-kubernetes-to-edge-using-event-based-transport/index.md @@ -0,0 +1,10 @@ +--- +title: "KubeCon CN 2024 - Extend Kubernetes to Edge Using Event-Based Transport | 使用基于事件的传输将Kubernetes扩展到边缘" +date: 2024-08-21 +authors: + - Longlong Cao, Red Hat + - Meng Yan, Red Hat +toc_hide: true +--- + +Read more at [KubeCon CN 2024 - Extend Kubernetes to Edge Using Event-Based Transport](https://kccncossaidevchn2024.sched.com/event/1eYX1/extend-kubernetes-to-edge-using-event-based-transport-zhi-27dzha-lian-kubernetesyi-sui-longlong-cao-meng-yan-red-hat). \ No newline at end of file diff --git a/content/en/blog/kubecon-na-2024-scheduling-ai-workload-among-multiple-clusters/index.md b/content/en/blog/kubecon-na-2024-scheduling-ai-workload-among-multiple-clusters/index.md new file mode 100644 index 00000000..0fb95420 --- /dev/null +++ b/content/en/blog/kubecon-na-2024-scheduling-ai-workload-among-multiple-clusters/index.md @@ -0,0 +1,10 @@ +--- +title: KubeCon NA 2024 - Scheduling AI Workload Among Multiple Clusters +date: 2024-11-12 +authors: + - Scott Berens, Red Hat +toc_hide: true +--- + +Read more at [KubeCon NA 2024 - Open Cluster Management: Scheduling AI Workload Among Multiple Clusters | Project Lightning Talk](https://kccncna2024.sched.com/event/1iW9B/open-cluster-management-scheduling-ai-workload-among-multiple-clusters-project-lightning-talk) | +[video](https://www.youtube.com/watch?v=bZrjMEzX0rU). diff --git a/content/en/blog/kubeday-2024-open-sourcing-the-open-cluster-management-project-and-the-lessons-we-can-learn-for-ai/index.md b/content/en/blog/kubeday-2024-open-sourcing-the-open-cluster-management-project-and-the-lessons-we-can-learn-for-ai/index.md new file mode 100644 index 00000000..d5673550 --- /dev/null +++ b/content/en/blog/kubeday-2024-open-sourcing-the-open-cluster-management-project-and-the-lessons-we-can-learn-for-ai/index.md @@ -0,0 +1,10 @@ +--- +title: KubeDay Australia 2024 - Open Sourcing the Open Cluster Management Project and the Lessons We Can Learn for AI +date: 2024-10-15 +authors: + - August Simonelli, Red Hat +toc_hide: true +--- + +Read more at [KubeDay Australia 2024 - Open Sourcing the Open Cluster Management Project and the Lessons We Can Learn for AI](https://kubedayaustralia2024.sched.com/event/1hAUw/open-sourcing-the-open-cluster-management-project-and-the-lessons-we-can-learn-for-ai-august-simonelli-red-hat) | +[video](https://www.youtube.com/watch?v=SLmJ6yJ6lAI). \ No newline at end of file