K8S多集群管理很难?试试Karmada | K8S Internals系列第3期
分类:技术社区 发布时间:2022/7/19 0:00:00
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 :
字段 类型 必填 描述 示例
ResourceSelectors []ResourceSelector 用于筛选资源
Association bool 已弃用
PropagateDeps bool 是否自动传播相关资源,例如deployment引用configmap,设置为true时,可以从ResourceSelectors中省略引用的资源,在故障转移场景中也将一起被转移。 默认false
Placement Placement 选择集群分发资源的规则
DependentOverrides []string OverridePolicy列表,当前namesapce中的OverridePolicy和ClusterOverridePolicy如果与要分发的资源匹配,即使不在此列表中也会生效。
SchedulerName string 指定scheduler,否则使用默认scheduler


Spec.ResourceSelector :
字段 类型 必填 描述 示例
APIVersion string 目标资源的 API version
Kind string 目标资源的kind
Namespace string 目标资源的namespace
Name string 目标资源的name
LabelSelector *metav1.LabelSelector 通过label筛选资源集,name不为空时忽略该值


Spec.Placement:
字段 类型 必填 描述 示例
ClusterAffinity *ClusterAffinity 表示对特定集群集的调度限制。如果未设置,任何集群都可以成为调度候选者。
ClusterTolerations []corev1.Toleration 集群 tolerations(容忍度)
SpreadConstraints []SpreadConstraint 调度约束列表,定义应用分发的HA策略
ReplicaScheduling *ReplicaSchedulingStrategy 在将具有规范副本的资源(例如deployments、statefulsets)传播到成员集群时处理副本数量的调度策略。


Spec.Placement.ClusterAffinity:
字段 类型 必填 描述 示例
LabelSelector *metav1.LabelSelector LabelSelector 是一个按标签选择成员集群的过滤器。如果non-nil且non-empty,则仅选择匹配此过滤器的集群。
FieldSelector *FieldSelector 通过字段来选择成员集群。如果non-nil且non-empty,只有匹配这个过滤器的集群才会被选中。
ClusterNames []string 要选择的集群name列表。
ExcludeClusters []string 要忽略的集群列表。


Spec.Placement.SpreadConstraint:
字段 类型 必填 描述 示例
SpreadByField SpreadFieldValue 代表karmada动态的将成员集群分成不同的组的字段,资源将被分发到不同的集群组中,该字段可以是cluster, region,zone, provider,该字段不应与SpreadByLabel共存,两者都为空时,SpreadByField默认为cluster。 cluster,
region,
zone,
provider
SpreadByLabel string 表示将成员集群分成不通组所用的label,资源将被分发到不同的集群组。
MaxGroups int 限制要选择的集群组的最大数量。
MinGroups int 限制要选择的集群组的最小数量。

Spec.Placement.ReplicaSchedulingStrategy:

字段 类型 必填 描述 示例
ReplicaSchedulingType ReplicaSchedulingType ReplicaSchedulingType 确定在 karmada 传播资源时如何调度副本。有效的选项是Duplicated和Divided。“Duplicated”将相同的副本从资源复制到每个候选成员集群。
“Divided”根据有效候选成员集群的数量将副本划分为多个部分,每个集群的确切副本由 ReplicaDivisionPreference 确定。
Duplicated,Divided
ReplicaDivisionPreference ReplicaDivisionPreference ReplicaDivisionPreference 确定如何划分副本,当 ReplicaSchedulingType 为“Divided”时。
有效选项是Aggregated 和Weighted。
“Aggregated ”将副本划分为尽可能少的集群,同时在划分期间尊重集群的资源可用性。
“加Weighted”根据 WeightPreference 按weight 划分副本。
Aggregated,Weighted
WeightPreference *ClusterPreferences WeightPreference 描述每个集群或每组集群的权重 如果 ReplicaDivisionPreference 设置为“Weighted”,并且未设置 WeightPreference,调度程序将对所有集群进行相同的加权。


Spec.Placement.ClusterAffinity.FieldSelector :

字段 类型 必填 描述 示例
MatchExpressions []corev1.NodeSelectorRequirement
字段选择器要求列表。


Spec.Placement.ReplicaSchedulingStrategy.WeightPreference, ClusterPreferences:
字段 类型 必填 描述 示例
StaticWeightList []StaticClusterWeight 定义静态集群权重。
DynamicWeight DynamicWeightFactor DynamicWeight 指定生成动态权重列表的因素。如果指定,StaticWeightList 将被忽略。 当前只支持AvailableReplicas

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:


字段 类型 必填 描述 示例
TargetCluster ClusterAffinity 用于选择集群的过滤器。
Weight






OverridePolicy


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

  • ImageOverrider 覆盖工负载的镜像
  • CommandOverrider 覆盖工作负载的 commands
  • ArgsOverrider 覆盖工作负载的 args
  • PlaintextOverrider 通用工具,覆盖任何种类的资源


Spec :
字段 类型 必填 描述 示例
ResourceSelectors []ResourceSelector 限制了此覆盖策略适用的资源类型。nil 表示匹配所有资源。
(字段结构同PropagationPolicy)

OverrideRules []RuleWithCluster 定义目标集群上的覆盖规则集合。
TargetCluster *ClusterAffinity 定义了对此覆盖策略应用到成员集群的目标选择。nil 表示匹配所有集群。(字段同PropagationPolicy)
Overriders Overriders Overriders 表示将应用于资源的覆盖规则,已弃用,请使用OverrideRules


RuleWithCluster:
字段 类型 必填 描述 示例
TargetCluster *ClusterAffinity 定义了对此覆盖策略应用到成员集群的目标选择。nil 表示匹配所有集群。
(字段同PropagationPolicy)

Overriders Overriders 应用于资源的覆盖规则


Overriders:
字段 类型 必填 描述 示例
ImageOverrider []ImageOverrider 覆盖镜像的规则
Plaintext []PlaintextOverrider 覆盖规则
CommandOverrider []CommandArgsOverrider 容器command覆盖规则
ArgsOverrider []CommandArgsOverrider 容器arg覆盖规则


ImageOverrider :
字段 类型 必填 描述 示例
Predicate *ImagePredicate 默认为nil,
如果资源是Pod, ReplicaSet, Deployment, StatefulSet系统自动检测镜像,如果资源对象有多个容器,所有镜像都将被处理。如果不为空,则只处理匹配到的镜像。

Component ImageComponent 假设镜像组成成分:
[registry/]repository[:tag]
Registry,Repository,Tag
Operator OverriderOperator 对镜像进行的操作 add,remove,replace
Value string 当Operator为'add'或'replace'时不能为空,默认为空,当operator为remove时忽略。


ImagePredicate :
字段 类型 必填 描述 示例
Path string 目标字段的路径 /spec/template/spec/containers/0/image


PlaintextOverrider :
字段 类型 必填 描述 示例
Path string
目标字段的路径
Operator OverriderOperator
对目标字段操作类型 add,remove,replace
Value apiextensionsv1.JSON 应用在目标字段的值,当Operator为remove时,此字段必须为空


CommandArgsOverrider:
字段 类型 必填 描述 示例
ContainerName string 容器名
Operator OverriderOperator 应用在commad/args上的操作 add;remove
Value []string 应用在command/args上的值,当operator为add时该值append到commad/args,当operator为remove时,该值从command/args移除,如果该值为空command/args维持原状。


ResourceBinding和ClusterResourceBinding


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


Spec:

字段 类型 必填 描述 示例
Resource ObjectReference 被分发的kubernetes资源
PropagateDeps bool 引用资源是否被自动分发,继承自PropagationPolicy
ReplicaRequirements *ReplicaRequirements 每个replica的需求
Replicas int32 副本数
Clusters []TargetCluster 目标成员集群
RequiredBy []BindingSnapshot 引用资源的Bindings列表


Spec.ObjectReference:
字段 类型 必填 描述 示例
APIVersion string 资源API version
Kind string 资源Kind
Namespace string 资源Namespace
Name string 资源Name
UID string 资源UID
ResourceVersion string 资源ResourceVersion


Spec.ReplicaRequirements:
字段 类型 必填 描述 示例
NodeClaim *NodeClaim 表示每个副本所需的节点声明 HardNodeAffinity、
NodeSelector 和 Tolerations。

ResourceRequest corev1.ResourceList 每个副本所需的资源请求


Spec.ReplicaRequirements.NodeClaim:
字段 类型 必填 描述 示例
HardNodeAffinity *corev1.NodeSelector 请注意,此处仅包含 PodSpec.Affinity.NodeAffinity中 RequiredDuringSchedulingIgnoredDuringExecution因为它对 Pod 调度有硬性限制。
NodeSelector map[string]string 节点选择器,匹配要调度的到的Node的label
Tolerations []corev1.Toleration 容忍度


TargetCluster:
字段 类型 必填 描述 示例
Name string 目标集群名
Replicas int32 副本数


BindingSnapshot:

字段 类型 必填 描述 示例
Namespace string ResourceBinding的namespace
Name string RB或者CRB的名
Clusters []TargetCluster 调度结果


ResourceBindingStatus:
字段 类型 必填 描述 示例
Conditions []metav1.Condition contain the different condition statuses
AggregatedStatus []AggregatedStatusItem 资源运行在每个子群上的状态列表


AggregatedStatusItem:

字段 类型 必填 描述 示例
ClusterName string 资源所部署处的集群
Status *runtime.RawExtension 当前manifest运行状态
Applied bool 资源是否成功的应用到集群中
AppliedMessage string 应用失败的人类可读的错误信息


Work


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


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

Spec:


字段 类型 必填 描述 示例
Workload WorkloadTemplate 工作负载manifest


WorkloadTemplate:

字段 类型 必填 描述 示例
Manifests []Manifest 工作负载manifest


Manifest:

字段 类型 必填 描述 示例
Manifest runtime.RawExtension 工作负载manifest

Status:

字段 类型 必填 描述 示例
Conditions []metav1.Condition work不同情况的状态:1. Applied represents workload in Work is applied successfully on a managed cluster.
2. Progressing represents workload in Work is being applied on a managed cluster.
3. Available represents workload in Work exists on the managed cluster.
4. Degraded represents the current state of workload does not match the desired state for a certain period.

ManifestStatuses []ManifestStatus spec中的Manifest运作的状态



ManifestStatus:

字段 类型 必填 描述 示例
Identifier ResourceIdentifier Spec中manifest的身份
Status *runtime.RawExtension manifest运行的状态

ResourceIdentifier:
字段 类型 必填 描述 示例
Ordinal int manifests中的索引
Group string 资源Group
Version string 资源Version
Kind string 资源Kind
Resource string 为空字符,资源类型
Namespace string 资源Namespace
Name string 资源Name



04 关注

在 karmada 的2022年的 roadmap 中,社区计划完善 Multi-cluster HA scheduling policy,联邦资源配额,及添加多集群日志、存储、RABC,管理,多集群监控等。本期文章先介绍那么多,后面我们也会持续关注 karmada 的发展,并再推出 karmada 更深入的介绍文章。
体验创新云技术带来核心业务效率显著提升
立即预约,加速企业数字化转型进程
Copyright ⓒ 2022 苏州博纳讯动软件有限公司 国徽 苏ICP备13004761号 法律声明及隐私政策