Karmada(Kubernetes Armada)是 CNCF 孵化的一个 Kubernetes 管理系统,使您能够在多个 Kubernetes 集群和云中运行云原生应用程序,而无需更改应用程序。通过使用 Kubernetes 原生 API 并提供先进的调度功能,Karmada 实现了真正的开放式、多云 Kubernetes。

Karmada 旨在为多云和混合云场景下的多集群应用程序管理提供即插即用的自动化,具有集中式多云管理、高可用性、故障恢复和流量调度等关键功能。

特性

  • 兼容 K8s 原生 API

            从单集群到多集群的无侵入式升级

            现有 K8s 工具链的无缝集成

  • 开箱即用
  • 针对场景内置策略集,包括:Active-active、Remote DR、Geo Redundant 等。
  • 在多集群上进行跨集群应用程序自动伸缩、故障转移和负载均衡。
  • 避免供应商锁定
  • 与主流云提供商集成
  • 在集群之间自动分配、迁移
  • 未绑定专有供应商编排
  • 集中式管理
  • 位置无关的集群管理
  • 支持公有云、本地或边缘上的集群。
  • 丰富多集群调度策略
  • 集群亲和性、实例在多集群中的拆分调度/再平衡,
  • 多维 HA:区域/AZ/集群/提供商
  • 开放和中立
  • 由互联网、金融、制造业、电信、云提供商等联合发起。
  • 目标是与 CNCF 一起进行开放治理。

Karmada 架构

Karmada 的架构非常类似于单个 Kubernetes 集群,他们都有一个控制平面、一个 APIServer、一个调度器和一组控制器,而且 Karmada 完全兼容 K8s 的原生 API 操作,便于各种 K8s 集群的接入。

Karmada 架构

所以同样 Karmada 的核心是其控制平面,一个完整且可工作的 Karmada 控制平面由以下组件组成。其中 karmada-agent 可以是可选的,这取决于集群注册模式。

karmada-apiserver

APIServer 是 Karmada 控制平面的一个组件,对外暴露 Karmada API 以及 Kubernetes 原生 API,APIServer 是 Karmada 控制平面的前端。

Karmada APIServer 是直接使用 Kubernetes 的 kube-apiserver 实现的,因此 Karmada 与 Kubernetes API 自然兼容。这也使得 Karmada 更容易实现与 Kubernetes 生态系统的集成,例如允许用户使用 kubectl 来操作 Karmada、与 ArgoCD 集成、与 Flux 集成等等。

karmada-aggregated-apiserver

聚合 API 服务器是使用 Kubernetes API 聚合层技术实现的扩展 API 服务器。它提供了集群 API 以及相应的子资源,例如 cluster/status 和 cluster/proxy,实现了聚合 Kubernetes API Endpoint 等可以通过 karmada-apiserver 访问成员集群的高级功能。

kube-controller-manager

kube-controller-manager 由一组控制器组成,Karmada 只是从 Kubernetes 的官方版本中挑选了一些控制器,以保持与原生控制器一致的用户体验和行为。值得注意的是,并非所有的原生控制器都是 Karmada 所需要的。

注意:当用户向 Karmada APIServer 提交 Deployment 或其他 Kubernetes 标准资源时,它们只记录在 Karmada 控制平面的 etcd 中。随后,这些资源会向成员集群同步。然而,这些部署资源不会在 Karmada 控制平面集群中进行 reconcile 过程(例如创建 Pod)。

karmada-controller-manager

Karmada 控制器管理器运行了各种自定义控制器进程。控制器负责监视 Karmada 对象,并与底层集群的 API 服务器通信,以创建原生的 Kubernetes 资源。

karmada-scheduler

karmada-scheduler 负责将 Kubernetes 原生 API 资源对象(以及 CRD 资源)调度到成员集群。

调度器依据策略约束和可用资源来确定哪些集群对调度队列中的资源是可用的,然后调度器对每个可用集群进行打分排序,并将资源绑定到最合适的集群。

karmada-webhook

karmada-webhook 是用于接收 karmada/Kubernetes API 请求的 HTTP 回调,并对请求进行处理。你可以定义两种类型的 karmada-webhook,即验证性质的 webhook 和修改性质的 webhook。修改性质的准入 webhook 会先被调用。它们可以更改发送到 Karmada API 服务器的对象以执行自定义的设置默认值操作。

在完成了所有对象修改并且 Karmada API 服务器也验证了所传入的对象之后,验证性质的 webhook 会被调用,并通过拒绝请求的方式来强制实施自定义的策略。

etcd

一致且高可用的键值存储,用作 Karmada 的所有 Karmada/Kubernetes 资源对象数据的后台数据库。

如果你的 Karmada 使用 etcd 作为其后台数据库,请确保你针对这些数据有一份备份计划。

karmada-agent

Karmada 有 Push 和 Pull 两种集群注册模式,karmada-agent 应部署在每个 Pull 模式的成员集群上。它可以将特定集群注册到 Karmada 控制平面,并将工作负载清单从 Karmada 控制平面同步到成员集群。此外,它也负责将成员集群及其资源的状态同步到 Karmada 控制平面。

插件(Addons)

  • karmada-scheduler-estimator

Karmada 调度估计器为每个成员集群运行精确的调度预估,它为调度器提供了更准确的集群资源信息。

注意:早期的 Karmada 调度器只支持根据集群资源的总量来决策可调度副本的数量。在这种情况下,当集群资源的总量足够但每个节点资源不足时,会发生调度失败。为了解决这个问题,引入了估计器组件,该组件根据资源请求计算每个节点的可调度副本的数量,从而计算出真正的整个集群的可调度副本的数量。

  • karmada-descheduler

Karmada 重调度组件负责定时检测所有副本(默认为两分钟),并根据成员集群中副本实例状态的变化触发重新调度。

该组件是通过调用 karmada-scheduler-estimator 来感知有多少副本实例状态发生了变化,并且只有当副本的调度策略为动态划分时,它才会发挥作用。

  • karmada-search

Karmada 搜索组件以聚合服务的形式,提供了在多云环境中进行全局搜索和资源代理等功能。

其中,全局搜索能力是用来跨多个集群缓存资源对象和事件,以及通过搜索 API 对外提供图形化的检索服务;资源代理能力使用户既可以访问 Karmada 控制平面所有资源,又可以访问成员集群中的所有资源。

CLI 工具

  • karmadactl

Karmada 提供了一个命令行工具 karmadactl,用于使用 Karmada API 与 Karmada 的控制平面进行通信。

你可以使用 karmadactl 执行成员集群的添加/剔除,将成员集群标记/取消标记为不可调度,等等。

  • kubectl karmada

kubectl karmada 以 kubectl 插件的形式提供功能,但它的实现与 karmadactl 完全相同。

安装

首先要注意我们使用 Karmada 管理的多集群包含两类:

  • host 集群:即由 karmada 控制面构成的集群,接受用户提交的工作负载部署需求,将之同步到 member 集群,并从 member 集群同步工作负载后续的运行状况。
  • member 集群:由一个或多个 K8s 集群构成,负责运行用户提交的工作负载

所以首先我们需要准备几个 K8s 集群用于测试,其中 host 集群就是我们要安装 Karmada 的集群,这里我们可以使用 KinD 部署一个 host 集群以及两个 member 集群,用于测试 Karmada 的多集群管理功能,当然首先需要在你的测试环境中安装 Docker 和 KinD。

$ docker version
Client:
 Cloud integration: v1.0.29
 Version:           20.10.21
 API version:       1.41
 Go version:        go1.18.7
 Git commit:        baeda1f
 Built:             Tue Oct 25 18:01:18 2022
 OS/Arch:           darwin/arm64
 Context:           orbstack
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          25.0.5
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.8
  Git commit:       e63daec
  Built:            Tue Mar 19 15:05:27 2024
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          v1.7.13
  GitCommit:        7c3aca7a610df76212171d200ca3811ff6096eb8
 runc:
  Version:          1.1.12
  GitCommit:        51d5e94601ceffbbd85688df1c928ecccbfa4685
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
$ kind version
kind v0.20.0 go1.20.4 darwin/arm64