K8S 多集群管理很难?试试 Karmada | K8S Internals 系列第 3 期

290 阅读8分钟

K8S Internals 系列:第三期

随着 Kubernetes 越来越成熟,以 kubernetes 为基础构建基础设施层的企业越来越多。据 CNCF 基金会统计,目前使用 Kubernetes 作为容器管理工具的企业占比早已过半,并且远远超过排名第二的 Swarm。

伴随着 Kubernetes 的使用越来越多,过程中也逐渐发现了一些问题,并促进了 kubernetes 联邦集群的发展。这些问题主要包括:

1、kubernetes 集群自身限制

根据 kubernetes 官方大规模集群注意事项,以最新版本 Kubernetes v1.24 为例我们可以看到 kubernetes 集群存在以下限制:

· 节点数不超过 5000

· 每个节点的 Pod 数量不超过 110 个

· Pod 总数不超过 150000

· 容器总数不超过 300000

由于单个集群的限制,有些业务可能需要部署在大量的 Kubernetes 集群上,此时就需要对多集群进行管理。

2、多集群管理的强烈需求

首先,将业务部署在单个的大规模集群中是比部署在多个较小集群中危险的,例如单个大集群出现故障,无法进行故障转移。其次,通过联邦集群可以在集群间进行资源同步和跨集群的服务发现,例如同城双活的场景。

鉴于以上(不限于)多种原因,企业内的 K8S 集群数量越来越多,K8S 自身的管理也变得日益复杂。

01 kubernetes 联邦集群的发展史

为了解决上述问题,kubernetes 兴趣小组最初推出了项目 kubefed v1。Kubefed v1 在 Kubernetes v1.6 时进入了 Beta 阶段,然而 kubefed v1 后续的发展不尽人意,最终在 Kubernetes v1.11 左右正式被弃用,弃用的主要原因是因为它存在以下问题:

  • 控制平面组件会因为发生问题,而影响整体集群效率。

  • 无法兼容新的 Kubernetes API 资源。

  • 无法有效的在多个集群管理权限,如不支持 RBAC。

  • 联邦层级的设定与策略依赖 API 资源的 Annotations 内容,这使得弹性不佳

kubernetes 兴趣小组并没有放弃发展 kubernetes 联邦集群, 后来升级版的 kubefed v2 出现了,kubefed v2 解决了兼容新的 kubernetes API 资源的问题,通过 CRD 扩充可支持的资源,并将集群划分为 Host 和 Member 两种类型的集群:

  • Host :用于提供 KubeFed API 与控制平面的集群。

  • Member :通过 KubeFed API 注册的集群,并提供相关身份凭证来让 KubeFed Controller 能够连接集群。Host 集群也可以作为 Member 被加入。

继 V1 版本之后,社区又推出了 Kubefed V2。相比于 kubefed v1, V2 有了巨大的改变,例如对 kubernetes 原生资源分发的支持更加灵活,可以支持多个版本的 API,弥补了 kubefed v1 无法兼容新 API 的缺点,另外还支持了 CRD 自身,通过 Placement 字段配置资源分发,通过 Overrides 字段可以差异化配置分发到不同集群的资源。然而 kubefed v2 在推广过程中出现了以下问题:

  • 使用者部署 Kubernetes 资源需要熟悉一套的全新 API,例如 FederatedDeployment。使用一套新的 API 替换 Kubernetes 原生的 API(例如:Deployment),很大地增加了用户的学习成本。

    例如部署 deployment:

    apiVersion: types.kubefed.io/v1beta1 kind: FederatedDeployment _#自定义资源类型_ metadata: name: test-deployment namespace: test-namespace spec: template: _#要部署的资源模板_ metadata: labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx placement: _# 对象需要部署到集群member1和member2_ clusters: - name: member1 - name: member2 overrides: _# 修改部署到member2集群的副本数为2_ - clusterName: member2 clusterOverrides: - path: "/spec/replicas" value: 2

  • 需要通过遍历集群才能获取部署的应用的具体状态,在控制面只能看到应用是否分发成功。

经历了多年发展,联邦集群这个领域的两次尝试都算不上成功。 难道就没有一个更好用的项目用来管理 kubernetes 联邦集群吗?

此时社区中的另一个项目 karmada 初露头角,karmada 继承和改进了 kubefed,例如部署 deployment, 在 karmada 中 FederatedDeployment 被拆解成了三个单独的资源,分别是资源模板 resource template 是 Kubernetes 原生 API 使用起来更舒服, 调度策略 propagation policy 和差异化配置策略 override policy。

下面我们简单介绍一下 karmada 架构及相关资源概念。

02 Karmada 架构

以 karmada v1.2.0 版本为例,karmada 的结构如下图所示:

其中的 karmada controller-manager,karmada aggregated-api-server,karmada Scheduler,karmada DeScheduler,karmada scheduler-estimator, karmada Agent 是 karmada 官方开发的组件,ETCD 即 ETCD 官方镜像,karmada API server 是 Kubernetes 官方的 API server 组件镜像。

  • karmada API server 与 API server 在 Kubernetes 集群中的功能类似,用来处理资源的增删改查及将数据持久到 ETCD 中。

  • karmada controller-manager 功能是管理 karmada 中的实现的 controllers,负责它们的启动和停止等。

  • karmada aggregated-api-server 是一个聚合 API,该组件实现了通过 karmada API server 即可访问成员集群资源的功能,并实现了统一鉴权认证,不用切换 kubeconfig 即可访问不同成员集群。

  • karmada Scheduler 实现了 karmada 对资源调度到成员集群的调度功能,并实现了多种调度策略。

  • karmada DeScheduler 实现了每隔一段时间就检测一次所有部署,将目标集群中不可调度的副本再调度到其他可调度的集群上。

  • karmada scheduler-estimator 用来评估成员集群上可调度的副本数,在一些调度策略中调度器将根据其计算副本数来计算每个目标集群上需要调度的副本数。

  • karmada Agent 是部署在成员集群上的组件,用来上报成员集群信息到 karmda 控制平面和从 karmada 控制平面拉取分发到成员集群的资源信息。

03 Karmada 相关资源概念

下面我们简单介绍一下 karmada 分发资源到成员集群涉及的相关资源,这些资源可分为:

  • 用于设定策略的资源:PropagationPolicy,OverridePolicy。

  • 执行策略相关的资源:ResourceBinding,ClusterResourceBinding, Work。

karmadaresourcerelation

karmada 分发资源到成员集群流程如上图所示, 在 karmada 控制平面创建 Resource Template 即为 kubernetes 原生资源,例如 Deployment,Service, configmap 等资源,同时创建 Propagation Policy 资源用来描述分发 Resource Template 到成员集群的策略,例如描述调度到哪些成员集群,使用静态权重策略等,如果有需要同时也可以创建 Override Policy 用来覆盖分发到不通成员集权中 Resource Template 中某些字段,例如修改 Deployment 中的容器镜像地址,容器参数等。

BindingController 根据 Resource Binging 资源内容创建 work 资源到各个成员集群的执行命名空间, work 中描述了要分到目标集群的资源内容,最终由 ExeuctionController 在各个成员集群中创建被分发的资源。

PropagationPolicy

分发策略包含集群级别的 ClusterPropagationPolicy 和 Namespace 级别的 PropagationPolicy,集群级别的可以分发各个命名空间的 resource Template,namespace 级别的只能分发自己命名空间级别的 resource Template,用来定义将创建的 resource Templater 分发到成员集群的策略。

我们详细看一下该资源相应字段:

Spec :

Spec.ResourceSelector :

Spec.Placement:

Spec.Placement.ClusterAffinity:

Spec.Placement.SpreadConstraint:

Spec.Placement.ReplicaSchedulingStrategy:

Spec.Placement.ClusterAffinity.FieldSelector :

Spec.Placement.ReplicaSchedulingStrategy.WeightPreference, ClusterPreferences:

DynamicWeightByAvailableReplicas 表示应根据可用资源(可用副本)生成集群权重列表。// Example:    //   The scheduler selected 3 clusters (A/B/C) and should divide 12 replicas to them.    //   Workload:    //     Desired replica: 12    //   Cluster:    //     A: Max available replica: 6    //     B: Max available replica: 12    //     C: Max available replica: 18    //   The weight of cluster A:B:C will be 6:12:18 (equals to 1:2:3). At last, the assignment would be 'A: 2, B: 4, C: 6'.

复制代码

Spec.Placement.ReplicaSchedulingStrategy.WeightPreference.StaticClusterWeight:

OverridePolicy

OverridePolicy 和 ClusterOverridePolicy 定义下发到不通成员集群中不通配置,karmada 支持的有:

  • ImageOverrider 覆盖工负载的镜像

  • CommandOverrider 覆盖工作负载的 commands

  • ArgsOverrider 覆盖工作负载的 args

  • PlaintextOverrider 通用工具,覆盖任何种类的资源

Spec :

RuleWithCluster:

Overriders:

ImageOverrider :

ImagePredicate :

PlaintextOverrider :

CommandArgsOverrider:

ResourceBinding 和 ClusterResourceBinding

ResourceBinding 是由控制器 ResourceDetector 根据 resource Template 和 Propagation Policy 的内容自动创建的资源,代表一个 kubernetes 资源和一个分发策略的绑定,与分发策略相对应 ResourceBinding 也分为集群级别的 ClusterResourceBinding 和 Namespace 级别的 ResourceBinding,同时也会记录 resource Template 最中部署的状态和结果。具体字段如下:

Spec:

Spec.ObjectReference:

Spec.ReplicaRequirements:

Spec.ReplicaRequirements.NodeClaim:

TargetCluster:

BindingSnapshot:

ResourceBindingStatus:

AggregatedStatusItem:

Work

work 定义了部署到目标成员集群的资源列表,由 bingingController 创建或者更新,由 execctionController 进行协调。

karmada 会为每一个分发的资源每个目标成员集群的执行命名空间(karmada-es-*)中创建一个 work。被分发的资源不区分是自定义资源还是 kubernetes 内置资源先被转化为 Unstructured 类型的数据,然后在 woker 中以 JSON 字节流的形式保存,然后在 execution_controller 中再反序列化,解析出 GVR,通过 dynamicClusterClient 在目标成员集群中创建指定分发资源。

具体字段如下:

Spec:

WorkloadTemplate:

Manifest:

Status:

ManifestStatus:

ResourceIdentifier:

04 关注

在 karmada 的 2022 年的 roadmap 中,社区计划完善 Multi-cluster HA scheduling policy,联邦资源配额,及添加多集群日志、存储、RABC,管理,多集群监控等。本期文章先介绍那么多,后面我们也会持续关注 karmada 的发展,并再推出 karmada 更深入的介绍文章。