Karmada调研

Karmada 概念介绍

Karmada 是 CNCF 的云原生项目,主要的能力是纳管多个 Kubernetes 集群,以及基于原生的 Kubernetes 的资源对象,将其下发到多个集群。对于一些有计算资源需求的 Deployment,Job 等 workload 具体副本数调度能力,让不同的 workload 按照一些的策略运行在不同的集群上。以此来达到多云分发的能力的这么一个项目。

Karmada 和 Kubernetes 的关系:

首先 Karmada 本身需要运行在 Kubernetes 集群中,这样的 Kubernetes 集群,我们称作为 Host Cluster (宿主集群),主要是用来运行 Karmada 控制平面的组件,其中包含 Karmada 的 etcd,karmada-api server, karmada-controller manager, Kubernetes controller manager,karmada-scheduler,karmada-webhook, karmada-scheduler-estimator 等控制面的组件。还有一种集群是负责真正运行工作负载的集群,对于这种集群,我们称之为 Workload Cluster。在 Workload Cluster 集群中,会真正运行业务的容器、一些 Kubernetes 的资源对象、存储、网络、dns 等,同时对于 pull 模式的部署方式,还会运行 Karmada 的 agent 组件,用于和控制面组件通信,完成工作负载的下发能力。

ResourceTemplate

在 Karmada 中没有真正的 crd 类型是 ResourceTemplate,这里的ResourceTemplate 只是对 Karmada 可分发的资源对象的一种抽象,这里的Resource 包含 Kubernetes 中所有支持的资源对象的类型,包括常见的 Deployment,Service,Pod,Ingress,PVC,PV, Job 等等,同时也原生的支持 CRD。

Cluster

Cluster 对象代表一个完整的,单独的一套 Kubernetes 集群,是可用于运行工作负载的集群的抽象和连接配置。在 Karmada 中,集群不仅仅有 spec,还有 status,这个 status 中描述了集群的基本信息,支持的 crd,以及集群的可用物理资源的统计等,用于在后续的调度器中使用这些信息进行调度处理。这些 Cluster 对象会被保存在 karmada-cluster 这个 namespace 中,这个 namespace 的作用有点类似 Kubernetes 的 kube-system,是系统预留的 namespace。

name:         member1
Namespace:    
Labels:       <none>
Annotations:  <none>
API Version:  cluster.karmada.io/v1alpha1
Kind:         Cluster
Metadata:  Creation
 Timestamp:  2021-09-17T13:54:50Z
   Finalizers:
       karmada.io/cluster-controller
  Generation:  1
......
Spec:
  API Endpoint:  https://10.23.20.93:6443
  Secret Ref:    
   Name:       10-23-20-93    
   Namespace:  karmada-cluster  
  Sync Mode:    Push
 Status:  
  API Enablements:    
   Group Version:  v1    
   Resources:
   
    Kind:         ConfigMap      
    Name:         configmaps      
    
    Kind:         Pod      
    Name:         pods     
     
    Kind:         Secret      
    Name:         secrets      
    Kind:         ServiceAccount      
    Name:         serviceaccounts      
    Kind:         Service      
    Name:         services    
   Group Version:  apiregistration.k8s.io/v1
   Resources:      
    Kind:         APIService      
    Name:         apiservices    
   Group Version:  apps/v1    
   Resources:      
    Kind:         ControllerRevision      
    Name:         controllerrevisions      
    Kind:         DaemonSet      
    Name:         daemonsets      
    Kind:         Deployment      
    Name:         deployments      
    Kind:         ReplicaSet      
    Name:         replicasets      
    Kind:         StatefulSet      
    Name:         statefulsets    
    
   Group Version:  authentication.k8s.io/v1    
   Resources:      
    Kind:         TokenReview      
    Name:         tokenreviews  
      
   Group Version:  autoscaling/v1    
   Resources:      
    Kind:         HorizontalPodAutoscaler      
    Name:         horizontalpodautoscalers    
    
   Group Version:  batch/v1    
   Resources:      
    Kind:         Job      
     Name:         jobs    
   
   Group Version:  crd.projectcalico.org/v1    
   Resources:      
    Kind:  NetworkPolicy      
    Name:  networkpolicies      
    Kind:  NetworkSet      
    Name:  networksets      
    Kind:  HostEndpoint      
    Name:  hostendpoints      
    Kind:  IPPool      
    Name:  ippools      
    Kind:  IPAMBlock      
    Name:  ipamblocks      
    Kind:  BGPConfiguration      
    Name:  bgpconfigurations 
......

 Conditions:    
  Last Transition Time:  2021-10-03T01:40:02Z    
  Message:               cluster is reachable and health endpoint responded with ok    
  Reason:                ClusterReady    
  Status:                True    
  Type:                  Ready  
 Kubernetes Version:      v1.15.4  
 Node Summary:    
  Ready Num:  5    
  Total Num:  5  
 Resource Summary:
  Allocatable:      
   Cpu:                  26      
   Ephemeral - Storage:  217892505240      
   hugepages-1Gi:        0      
   hugepages-2Mi:        0      
   Memory:               51824616Ki      
   Pods:                 550    
  Allocated:     
   Cpu:                  3100m     
   Ephemeral - Storage:  0      
   Memory:               140Mi      
   Pods:                 0    
  Allocating:      
   Cpu:                  0      
   Ephemeral - Storage:  0      
   Memory:               0      
   Pods:                 0
Events:                     <none

PropagationPolicy/ClusterPropagationPolicy

PropagationPolicy 的作用主要是,为了定义资源对象被下发的策略,如下发到哪些集群,以及下发到这些集群中的需要计算资源的工作负载的副本数应该怎样分配。

apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-propagation
spec:  
  resourceSelectors:    
    - apiVersion: apps/v1      
      kind: Deployment      
      name: nginx  
  placement:    
    clusterAffinity:      
      clusterNames:       
        - member1       
        - member2    
    replicaScheduling:      
      replicaDivisionPreference: Weighted      
      replicaSchedulingType: Divided      
      weightPreference:        
      staticWeightList:         
         - targetCluster:              
              clusterNames:               
                - member1           
           weight: 1         
         - targetCluster:             
              clusterNames:              
                - member2         
           weight: 1

OverridePolicy

OverridePolicy 的作用是,定义在下发到不同集群中的配置,可以是不一样的,例如不同的集群所对应的镜像仓库的地址是不一样的,那就需要设置在不同集群中的工作负载的镜像地址是不一样,例如在不同的环境下,需要设置不同的环境变量等。

OverridePolicy 的作用时机是在 PropagationPolicy 之后,以及在真正在下发到集群之前。主要处理逻辑是 binding controller 中处理的。其中可以使用的 override 的能力目前包括 Plaintext,ImageOverrider,CommandOverrider,ArgsOverrider 这几种,用来完成不同集群的差异化配置能力。

apiVersion: policy.karmada.io/v1alpha1
kind: OverridePolicy
metadata:  
 name: nginx-propagation
spec:  
 resourceSelectors: 
  - apiVersion: apps/v1     
   kind: Deployment      
   name: nginx  
 targetCluster:    
  clusterNames:    
  - member1  
 overriders:    
  plaintext:    
  - path: "/spec/template/spec/containers/0/image"      
    operator: replace      
    value: "nginx:test"

ResouceBinding/ClusterResouceBinding

ResourceBinding 这个 crd 不是用于给最终用户使用的,而是 Karmada 自身机制工作需要的,主要的用途是说明了某一个资源被绑定到了哪个集群上了,这个和集群绑定的逻辑是在 detector 的 PropagationPolicy 的 controller 中来控制,可以理解成 ResourceBinding 是 PropagationPolicy 派生出来的一个 cr 对象。

同时 Karmada 的调度器的处理对象就是以一个 ResourceBinding 为处理单元,在此基础上来完成资源对象所需要副本数的计算和调度,最终会由 binding controller 完成对 ResourceBinding 的处理,从而生成 Work 对象,同步下发到对应的集群上。

Name:         nginx-deployment
Namespace:    default
Labels:       propagationpolicy.karmada.io/name=nginx-propagation 
             propagationpolicy.karmada.io/namespace=default
Annotations:  policy.karmada.io/applied-placement: {"clusterAffinity":{"clusterNames":["10-23-20-93"]}}
API Version:  work.karmada.io/v1alpha1
Kind:         ResourceBinding
Metadata:
 Creation Timestamp:  2021-11-05T02:52:17Z  
 Generation:          5
......  
 Owner References:   
  API Version:           apps/v1    
  Block Owner Deletion:  true    
  Controller:            true    
  Kind:                  Deployment    
  Name:                  nginx    
  UID:                   967b7a14-044b-4834-a9e4-3321323a6799  
 Resource Version:        8545931  
 Self Link:               /apis/work.karmada.io/v1alpha1/namespaces/default/resourcebindings/nginx-deployment  
 UID:                     1d0a867d-c386-41c5-8ac7-43e110348918
Spec:  
 Clusters:    
  Name:  10-23-20-93  
 Replica Requirements:   
  Resource Request:     
   Cpu:                  0      
   Ephemeral - Storage:  0      
   Memory:               0      
   Pods:                 0  
 Replicas:                 1  
 Resource:    
  API Version:       apps/v1    
  Kind:              Deployment    
  Name:              nginx    
  Namespace:         default    
  Resource Version:  8545930
Status:  
 Aggregated Status:    
  Applied:       true    
  Cluster Name:  10-23-20-93    
  Status:      
   Available Replicas:  1      
   Conditions:        
   Last Transition Time:  2021-11-05T02:52:18Z        
   Last Update Time:      2021-11-05T02:52:18Z        
   Message:               Deployment has minimum availability.        
   Reason:                MinimumReplicasAvailable        
   Status:                True        
   Type:                  Available        
   Last Transition Time:  2021-11-05T02:52:17Z        
   Last Update Time:      2021-11-05T02:52:18Z        
   Message:               ReplicaSet "nginx-6c7964bd8f" has successfully progressed.        
   Reason:                NewReplicaSetAvailable        
   Status:                True        
   Type:                  Progressing     
  Observed Generation:     1      
  Ready Replicas:          1      
  Replicas:                1      
  Updated Replicas:        1

Work

Work 这个对象代表了所有资源对象,以及所有资源对象需要下发到多个集群的时候所对应的业务模型。

举例来说,一个 Deployment 需要下发到两个集群中去,那对应到这个 Deployment 的 work 的对象就会有两个,因为 work 是集群单位的对象,主要的作用就是对应和代表一个资源对象在一个集群中的逻辑对象。这个逻辑对象 (work),它保存在控制平面。这里就是 Karmada 在做多集群下发中完成 Host Cluster 和 Workload Cluster 之间真正业务能力的体现。

Name:         nginx-687f7fb96f
Namespace:    karmada-es-10-23-20-93
Labels:       resourcebinding.karmada.io/name=nginx-deployment       
          resourcebinding.karmada.io/namespace=default
Annotations:  policy.karmada.io/applied-overrides:         
         [{"policyName":"nginx-propagation","overriders":{"plaintext":[{"path":"/spec/template/spec/containers/0/image","operator":"replace","value...
API Version:  work.karmada.io/v1alpha1
Kind:         Work
Metadata: 
 Creation Timestamp:  2021-11-03T05:58:49Z  
 Finalizers:   
  karmada.io/execution-controller  
 Generation:  1 
......
Spec:  
 Workload:    
  Manifests:      
   API Version:  apps/v1      
   Kind:         Deployment      
   Metadata:       
    Annotations:         
     kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"10.23.12.61:9120/docker.io/nginx","name":"nginx"}]}}}}        
    Labels:          
     App:                                     nginx          
     propagationpolicy.karmada.io/name:       nginx-propagation          
     propagationpolicy.karmada.io/namespace:  default          
     resourcebinding.karmada.io/name:         nginx-deployment          
     resourcebinding.karmada.io/namespace:    default          
     work.karmada.io/name:                    nginx-687f7fb96f          
     work.karmada.io/namespace:               karmada-es-10-23-20-93        
    Name:                                      nginx        
    Namespace:                                 default      
   Spec:        Progress Deadline Seconds:  600        
    Replicas:                   1        
    Revision History Limit:     10        
    Selector:          
     Match Labels:           
      App:  nginx        
    Strategy:          
     Rolling Update:            
      Max Surge:        25%            
      Max Unavailable:  25%          
     Type:               RollingUpdate        
    Template:          
     Metadata:            
      Creation Timestamp:  <nil>            
      Labels:              
      App:  nginx         
    Spec:            
     Containers:              
     Image:              nginx:test              
     Image Pull Policy:  Always              
     Name:               nginx              
     Resources:              
     Termination Message Path:    /dev/termination-log              
     Termination Message Policy:  File            
    Dns Policy:                    ClusterFirst            
    Restart Policy:                Always            
    Scheduler Name:                default-scheduler            
    Security Context:            
    Termination Grace Period Seconds:  30
Status:  
 Conditions:    
  Last Transition Time:  2021-11-03T05:58:49Z    
  Message:               Manifest has been successfully applied    
  Reason:                AppliedSuccessful    
  Status:                True    
  Type:                  Applied  
  Manifest Statuses:    
  Identifier:      
  Group:      apps      
  Kind:       Deployment      
  Name:       nginx      
  Namespace:  default      
  Ordinal:    0      
  Resource:         
  Version:    v1    
 Status:      
  Conditions:        
   Last Transition Time:  2021-11-03T05:58:50Z        
   Last Update Time:      2021-11-03T05:58:50Z        
   Message:               Deployment does not have minimum availability.        
   Reason:                MinimumReplicasUnavailable        
   Status:                False        
   Type:                  Available        
   Last Transition Time:  2021-11-03T05:58:50Z        
   Last Update Time:      2021-11-03T05:58:50Z        
   Message:               ReplicaSet "nginx-6bd9c997cc" is progressing.        
   Reason:                ReplicaSetUpdated        
   Status:                True        
   Type:                  Progressing      
  Observed Generation:     1      
  Replicas:                1      
  Unavailable Replicas:    1      
  Updated Replicas:        1
  Events:                        <none>

ReplicaSchedulingPolicy

ReplicaSchedulingPolicy 顾名思义就是对副本数分配的一种策略,使用 resource selector 去匹配对应的工作负载,这里的工作负载指的就是 Deployment,Job 之类的。这个和 PropagationPolicy 里的 replicaScheduling 有什么区别?

PropagationPolicy 里的 replicaScheduling 是用于在调度器中使用的,在程序中全称是 ReplicaSchedulingStrategy,也是用于计算副本数分配的。ReplicaSchedulingPolicy 的作用是在调度器没有能计算出每一个集群对应分配的副本数的时候,这个时候 ReplicaSchedulingPolicy 才会生效。在目前的逻辑中,在调度类型是 Failover 类型的时候,会触发 ReplicaSchedulingPolicy 生效。

apiVersion: policy.karmada.io/v1alpha1 
kind: ReplicaSchedulingPolicy 
metadata:
 name: foo 
 namespace: foons 
spec: 
 resourceSelectors:
  - apiVersion: apps/v1
    kind: Deployment 
    namespace: foons 
    name: deployment-1 
 totalReplicas: 100 
 preferences: 
  staticWeightList:
   - targetCluster:
      labelSelector: 
       matchLabels:
        location: us
    weight: 1
  - targetCluster: 
     labelSelector: 
      matchLabels: 
       location: cn 
    weight: 2

ServiceExport

ServiceExport 的作用是为了解决跨集群服务发现的场景,ServiceExport 不是 Karmada 自己的 CRD,而是 Kubernetes 社区在解决跨集群服务发现的场景下定义的一套 mcs api 规范。

主要的作用就是将某一个集群中,需要被其它集群发现的服务去创建一个 ServiceExport,以此来将这个服务暴露出去。当然不是只有仅仅这个一个 ServiceExport 就可以的,配合下述的ServiceImport 来完成。对于 ServiceExport 和 ServiceImport 的实现,是不同的方案提供商来实现的,Karmada 内置实现了 ServiceExport 和 ServiceImport 的 controller。

kind: Service
apiVersion: v1
metadata:
 namespace: demo  
 name: demo-service
spec: 
 selector:   
  app: nginx  
 ports:   
  - port: 8080     
    targetPort: 80
---
kind: ServiceExport
apiVersion: multicluster.x-k8s.io/v1alpha1
metadata: 
 namespace: demo  
 name: demo-service

ServiceImport

ServiceImport 的作用是配合 ServiceExport 来完成跨集群的服务发现,要想在某一个集群中去发现另一个集群的服务,除了要在暴露服务的集群中创建 ServiceExport,还要在需要发现和使用这个服务的集群中,创建 ServiceImport 对象,以此来在集群中发现其它集群的服务,和使用这个其它集群的服务,至于在这个集群中是怎样发现的,以及怎样访问的,是不同的方案提供商来实现的,这里会涉及到 Kubernetes 中已有资源对象EndpointSlice。

apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceImport
metadata: 
 name: my-svc  
 namespace: my-ns
spec: 
 ips:  - 42.42.42.42  
 type: "ClusterSetIP"  
 ports: 
 - name: http    
  protocol: TCP    
  port: 80  
 sessionAffinity: None
status:  
 clusters:  
 - cluster: us-west2-a-my-cluster

EndpointSlice

EndpointSlice 是 Kubernetes 中的已有资源对象的一个。主要作用就是描述了 Service 对应的 Pod 的真正的访问地址以及端口的一些信息。

apiVersion: discovery.k8s.io/v1beta1
kind: EndpointSlice
metadata: 
 name: imported-my-svc-cluster-b-1  
 namespace: my-ns  
 labels:    
   multicluster.kubernetes.io/source-cluster: us-west2-a-my-cluster    
   multicluster.kubernetes.io/service-name: my-svc  
  ownerReferences:  
  - apiVersion: multicluster.k8s.io/v1alpha1    
  controller: false    
  kind: ServiceImport    
  name: my-svc
addressType: IPv4
ports: 
 - name: http  
   protocol: TCP    
   port: 80
   endpoints:  
    - addresses:     
       - "10.1.2.3"    
      conditions:      
       ready: true    
      topology:     
       topology.kubernetes.io/zone: us-west2-a

Execution Namespace

在 Karmada 的控制平面中,会为每一个被纳管的集群创建一个集群相关的 namespace,这个 namespace 中存放的资源对象是 work。每一个和这个集群相关的 Kubernetes 资源对象都会对应到这个 namespace 下的一个 work。

举例在 Karmada 的控制平面创建了一个 service 资源对象,同时通过 PropagationPolicy 下发到两个集群中,那在每一个集群对应的 execution namespace 中都会有一个 work 对象对应到当前集群需要负责的 service对象上。

Karmada架构介绍

image.png

karmadactl

karmadactl 是 Karmada 的命令行程序,主要是方便快速的接入集群,管理集群。

kubectl karmada

kubectl karmada 是 kubectl 的 Karmada 的 plugin 程序,用于 Host Cluster 这个 context 中,使用 kubectl 的 cmd 中可以快速的查看 Karmada 管理的资源对象对象的详细信息。

karmada agent

karmada agent 的作用主要是使用 pull 模式的时候才会需要,这里的 pull 指的是 workload 集群中的 agent 主动去控制平面去 pull 需要下发的资源对象。考虑在云边的场景下,控制面 Host Cluster 运行在公有云,Workload Cluster 运行在私有云的场景下,这个时候是需要安装 agent,每一个集群安装一个 agent 就可以了。也可以在私有环境使用 pull 模式,取决于场景的需要。在安装了 agent 的集群中,这个集群在控制面的工作方式就是 pull 的模式,顾名思义是 agent 主动去控制面去拉取需要处理的 work 对象。

  • 当 agent 在某一个集群启动之后,会在控制平面创建对应的 cluster 对象,同时创建 execution 的 namespace。
  • 启动 4个 controller,包括 cluster status controller, execution controller,work status controller, service export controller 这些 controller,这里有一个需要注意的是在 agent 中启动的这些 controller 在 controller manager 中也会启动,但是区别是 agent 中的 controllers 的关注的事件和 controller manager 中关注的事件是不一样的,通过定义 controller 中的 PredicateFunc 这个参数指定了事件的过滤逻辑,详细请查看 pkg/util/helper/predicate.go 文件。对于需要 agent 处理的事件, 方法名都有一个 “OnAgent” 的后缀。如 “func NewExecutionPredicateOnAgent() predicate.Funcs”。

karmada api server

karmada api server 是和 Kubernetes 集群中的 api server 是一样的角色,负责处理 api 的请求,以及连接到 etcd 数据源持久化元数据,在这个过程中所有的 controllers 和 scheduler 会和 api server 进行通信,类似 Kubernetes 里的 api server 和 controllers 以及 scheduler 的关系。

karmada controller manager

karmada controller manager 主要负责初始化所有相关的 controllers,以及启动所有的 controllers,让所有的 controllers 去工作起来。具体包含的 controller 主要有 cluster controller,cluster status controller,namespace sync controller,propagationpolicy controller,binding controller, execution controller,work status controller,serviceexport controller,endpointslice controller, serviceimport controller,hpa controller。

karmada Kubernetes controller manager

这里的 controller manager 是使用的 kubernetes 的 controller manager,但是只会用到 gc controller 的能力,用于完成资源对象的垃圾回收工作,其它的能力都没有开启,所以不会因为在 Karmada 创建一个 Deployment 而创建 Pod 出来。

karmada scheduler

这个组件是 Karmada 的调度器,主要是用于完成在资源对象的调度。也是以插件的方式支持调度的扩展能力。其中也会包含 filter 和 score 两个接口。

对于一些需要计算副本比例的资源对象,会首先根据 filter 和 score 选择出一些集群,然后再对需要分配副本的资源对象类型计算每一个集群应该需要分发的副本数。

目前只是支持了 Deployment 和 Job 类型的,对于 StatefulSet 是不支持副本数分配到不到集群的能力。对于非工作负载的资源对象,不会有处理副本数的要求,只会在对应需要被调度的集群,创建一个匹配的资源对象,举例,如在 Karmada 的控制面创建了一个 service 对象,同时 PropagationPolicy 设置了对应希望调度的集群,然后只会在对应的集群中创建一个 service 资源对象。

karmada scheduler estimator

estimator 的组件是负责更加精确的计算副本分配的能力。

在早期的版本中,调度器在计算副本数的分配时,只支持了根据集群状态的资源总和来调度副本数,或者根据静态的权重来固定副本数。

在这个情况下,很有可能因为集群的总体资源是充足的,但是每一台机器的资源不足的,导致最终的 Pod 调度不出去。

为了解决这个问题,引入了 estimator 组件,每一个 estimator 会负责一个独立的集群的可调度副本数的计算。estimator 会根据调度的资源请求,计算出这样的资源规格 (如,pod 的 cpu 是 1core,内存是 2G),在这个集群中,以及这个集群中,所有的节点上可调度的副本数的总和返回回去,在计算每一个节点的可调用副本数的时候,会获取节点的资源使用,根据请求的 pod 的 cpu 和内存去计算,这个主机最多可以运行多少个这样的 pod,这样就可以计算出,单个机器的可用副本数,根据同样的逻辑,对所有的节点都会进行这样的计算,最后得到一个集群真正可以调度的 pod 数量。

这样就可以保证,只要是被调度器计算好的副本数的分配之后,可以在对应的集群中真正的被调度和正常的启动。目前 estimator 只会负责 PropagationPolicy 的 replicaScheduling 中,调度类型为 devided,同时副本分配策略是动态权重的这种调度设置。duplicated 类型,以及静态权重的这种,不会处理。

karmada webhook

webhook 是 kubernetes 中,以及 operator 中常见的组件,主要作用就是对负责的资源对象进行数据格式的验证,以及在没有进入到 etcd 之前进行一些拦截修改数据的能力。

举例,在创建 serviceimport 需要的 PropagationPolicy 的时候会在 webhook 中修改 PropagationPolicy 的 resource selector,在其中增加 service 和 endpointslice 的部分,最后会随着 detector 和 binding controller 中的逻辑,在对应的集群的 execution 的 space 中创建对应 service 和 endpointslice 的 work,然后由 execution controller 去对应的工作集群去创建真正的资源对象,从而在 serviceimport 的集群中创建出 endpointslice 资源对象,来达到跨集群的服务发现的能力。

Karmada Controllers一览表

image.png

Cluster Controller

cluster controller 主要就是处理 Cluster 资源对象的逻辑,负责处理 Cluster 对应需要的关联资源。

相关资源对象:Cluster

[图片上传失败...(image-928986-1708308916175)]

  • 创建 Cluster 的时候,需要在 Karmada 中创建对应的 execution namespace,这个 namespace 中会保存所有这个集群相关的 Work 对象。
  • 删除Cluster的时候,需要在 Karmada 中删除对应的execution namespace。
  • Cluster 资源对象保存在 karmada-cluster 这个 namespace 中,这个 namespace 中保存了所有集群对应的 Cluster 资源对象。

Cluster status controller

cluster status controller 主要就是处理 cluster status 资源对象的逻辑,用来收集 Cluster 的状态,保存到 Cluster 的 status 字段中,同步上报到 Karmada 的控制平面中。

相关资源对象:Cluster

[图片上传失败...(image-6d9001-1708308916175)]

  • watch Cluster 对象,然后执行 sync 方法,同步上报集群的状态给Karmada 控制平面 (也就是 Karmada 集群中,karmada-cluster 这个 namespace 中的某一个 cluster 对象)。
  • 收集当前 agent 所在集群的状态信息,这些信息包含 Nodes 统计,Pods 相关的资源统计,Kubernetes 版本,以及 Kubernetes 集群支持的资源对象的类型的 GVR,其中包含 CRD 的支持信息等,然后同步更新到 Karmada 控制平面 Cluster 对象的 status 中。

namespace sync controller

namespace sync controller 主要就是处理 namespace 资源对象的逻辑,负责将 Karmada 控制平面创建的 namespace 在集群中同步创建出来。

相关资源对象:namespace

[图片上传失败...(image-5a9797-1708308916175)]

  • namespace sync controller 就是为了将在 Karmada 中创建的 namespace 在所有的工作集群中也去创建出来。
  • namespace 是 “karmada-cluster”,或者是 “karmada-system”,或者是 “default”, 或者 namespace 是 “karmada-es-<xxx>”, 或者是 “kube-<xxx>” 这样 namespace 是不需要处理的。以及被包含在 SkippedPropagatingNamespaces 配置中的 namespace,也不需要处理。

Resourse Template controller

detector 模块中包含了通用 controller 负责 resource template 的 Kubernetes 资源对象的调和处理逻辑,以及匹配 PropagationPolicy。主要就是处理 PropagationPolicy 资源对象的逻辑,来派生出资源对象对应的 ResourceBinding 对象。

相关资源对象:PropagationPolicy, Kubernetes 支持的所有的资源对象 (包括 CRD)

[图片上传失败...(image-f57ee9-1708308916175)]

  • 定义处理 PropagationPolicy / ClusterPropagationPolicy 的 informer,event handler,以及对应的 reconciler 方法。
  • 定义处理 ResourceBinding / ClusterResourceBinding 的 informer,event handler,以及对应的 reconciler 方法。
  • 定义处理所有原生 Kubernetes 资源对象的 informer,event handler,以及对应的 reconciler 方法,然后为其创建对应的 ResourceBinding 对象用于调度。
  • 根据 Kubernetes 的对象定义以及 PropagationPolicy 构建 ResourceBinding 对象,同时这个 ResourceBinding 的 OwnerReferences 设置了这个 Kubernetes 的对象,这样就会在删除 Kubernetes 对象的时候删除这个 ResourceBinding,这个也是目前 ResourceBinding 会被删除的唯一逻辑了。
  • 所以虽然 ResourceBinding 是因为 PropagationPolicy 的创建而被派生出来,但是不会因为 PropagationPolicy 的删除而删除。
  • 在删除 PropagationPolicy 删除的时候,只会去除 PropagationPolicy 和 Kubernetes 对象的关系,这个关系体现在,Kubernetes object 会在匹配到 PropagationPolicy 的时候在自己的 label 上增加 PropagationPolicy 相关的 label。
  • ResourceBinding 中不会包含 Kubernetes 资源对象的详细信息,只会包含类型,namespace,name,版本,副本数,cpu/memory 请求,节点亲和性,真正详细的 Kubernetes 对象的处理是在 controller 的syncbinding() 方法中完成,其中是通过workload, err := helper.FetchWorkload (c.DynamicClient,c.InformerManager,c.RESTMapper, binding.Spec.Resource) 去拿到真正的 Kubernetes 资源对象的定义的。
  • 每隔 30s 去发现新的 Kubernetes 的资源对象类型,只要这些资源对象支持 list,watch,delete 方法,当然也包括 crd 类型。

Binding controller

binding controller 主要就是处理 ResourceBinding 资源对象的增删改逻辑,ResourceBinding 的调和能力是派生出 work 对象,work 对象是和特定集群关联的。一个 work 只能属于一个集群,代表一个集群的资源对象的模型封装。

相关资源对象:ResourceBinding 和 ClusterResourceBinding

  • 负责 ResourceBinding 的处理,根据 binding 去创建对应的 Work 对象到集群对应的 execution space 中。
  • 在生成 Work 的时候,会处理 OverridePolicy,将需要覆盖的数据更新到 Work 对应的 manifest 中。目前支持的 override 的方式主要是 4 种,包括:PlaintextOverrider,mageOverrider,CommandOverrider,ArgsOverrider。
apiVersion: policy.karmada.io/v1alpha1 

kind: OverridePolicy 

metadata: 

 name: nginx-propagation 

spec: 

 resourceselectors: 

  一 apiVersion: apps/v1 

     kind: Deployment name: nginx 

 targetcluster: 

   clusterNames: 

   -10-23-20-93 

 overriders: 

  plaintext: 

  一 path: "/spec/template/spec/containers/O/image"  

  operator: replace value: "nginx:test"
  • 根据调度器计算好的每一个集群负责的副本数,如果调度器计算出来的所有集群的对应的副本数是 0,说明没有找合适的集群,就用 ReplicaSchedulingPolicy 根据权重去计算每一个集群应该负责的副本数,这个 ReplicaSchedulingPolicy 的计算副本分配的方式是用 static weight。
  • 收集每一个 binding 的状态,一个 binding 会包含多个 Work,因为同一个资源对象,在每一个集群中就需要一个 Work,所有 binding 的状态是所有工作集群中 Work 的状态的汇总,汇总之后将这个状态设置到 binding 的 status 中去。

execution controller

execution controller 主要就是处理 Work 资源对象的增删改逻辑,用于处理 Work,将 Work 负责的 Kubernetes 资源对象在对应的集群上创建出来。

相关资源对象:Work

  • watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有新的 Work 对象被创建了之后会在对应的工作集群中创建 Work 负责的资源对象。
  • watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有 Work 对象被删除的时候,会在工作集群中,删除 Work 对象负责的资源对象。watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有 Work 对象被修改了之后,会在工作集群中,修改 Work 对象负责的资源对象。

work status controller

work status controller 主要就是处理 Work 资源对象的状态逻辑,负责收集 Work 的状态,也就是 Work 对应的资源对象的状态,只是这个状态是保存在 Work 的 status 字段里的。

相关资源对象:Work,以及 Work 负责的资源对象。

[图片上传失败...(image-fa4e3e-1708308916175)]

  • watch Work 对象为指定计算集群包含的所有的 Work 对象所负责的资源对象的类型创建对应的 informer 对象,同时调用 informer 的 WaitForCacheSync,当 WaitForCacheSync 结束了之后,也就是 list 结束了,接下来就是 watch 的任务了。这个就是 list and watch 的核心机制。
  • 在 watch 所有 Work 负责的资源对象的时候,设置了一个事件处理器,这个事情处理器会负责处理所有相关资源对象的 Add,Update,Delete 事件。这些事件存放在 queue 中。
  • 启动一个异步的 AsyncWorker, 设置一定的 WorkerNumber 数量的 goroutines 去处理 queue 里的数据,这里的数据是带有集群信息的 fedkey。
  • 从 queue 中获取 fedkey,判断这个 fedkey 的对应的集群中的资源对象,如果这个 Work 负责的资源对象在工作集群中被非法删除了,会重新在工作集群中创建出对应的资源对象。
  • 从 queue 中获取 fedkey,判断这个 fedkey 的对应的集群中的资源对象,如果这个 Work 负责的资源对象被修改了之后是不是修改被修改回去。如果是的话,会重新 sync 回资源对象,防止直接从工作集群中直接修改资源对象。
  • 收集 Work 对象对应的资源对象在 Worload 集群中的运行状态,然后更新到到控制平面的 Work 的 status 中。
  • watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有新的 Work 对象被创建了之后会在对应的工作集群中创建 Work 负责的资源对象。

serviceexport controller

serviceexport controller 主要就是处理 serviceexport 资源对象的状态逻辑,将需要被其它集群发现的服务暴露出来。

相关资源对象:ServiceExport

[图片上传失败...(image-44a2c6-1708308916175)]

  • 当控制平面创建 ServiceExport 对象的时候,会对应的创建出 Work 对象,以及在对应的工作集群中创建出 ServiceExport 对象。
  • 查找出 ServiceExport 对象对应的 service 对象的 EndpointSlice 对象,将这些 EndpointSlice 对象封装成 work 对象创建到控制平面中。
  • 当在控制平面删除 ServiceExport 对象的时候,会找到对应的 work 对象,将其删除。这里删除的时候也会一起删除由 ServiceExport 关联上报上来的 EndpointSlice 对象对应的 Work 对象。因为查找要删除的 Work 的时候是根据服务名查找的,而 ServiceExport 和 Serivce 对应的 EndpointSlice 的 Work 都是用服务名来创建的,所以查找的时候会一起查找到。
  • 当工作集群的 EndpointSlice 发生变化的时候,也会同步去更新控制平面的 EndpointSlice 对象,因为 ServiceExport controller 是 watch 了每一个集群的 ServiceExport 的 add 事件以及 EndpointSlice 的 add 和 update 事件的。只要 EndpointSlice 变化,就会同步到控制平面。这样会触发 PropagationPolicy 关联的对象发生变化,就会触发更新 EndpointSlice 对应的 Work,也就会同步更新 ServiceImport 集群中由于 ServiceImport 而级联出来的 EndpointSlice 了。

endpointslice controller

endpointslice controller 主要根据 serviceexport 资源对象对应到处的 Service,Service 对应的 endpointslice 上报到 Karmada 的控制面。

相关资源对象:EndpointSlice 相关的 Work

  • 负责将 work 中的 manifest 是 EndpointSlice 的 work 中的 EndpointSlice 对象,在 Karmada 控制平面中创建对应的 EndpointSlice 的对象。
  • 其中 Karmada 控制平面中的 EndpointSlice 的 namespace 就是和 work 中 manifest 中的 EndpointSlice 的 namespace 一样。但是 Karmada 控制平面中的 EndpointSlice 的 name 不一样,格式为:“imported-<cluster name>-<endpointslice name>”。

serviceimport controller

serviceimport controller 主要负责根据 ServiceExport 暴露出来的 Service,在自己负责的集群中创建对应的 service,注意 service 的名称不是完全一样的,同时在自己负责的集群中也创建对应的 EndpointSlice,这个 EndpointSlice 的数据就是来源于 EndpointSlice controller 中上报到 karmada 控制平面的 EndpointSlice 对象,具体是通过在 karmada-webhook 中给 ServiceImport 的 PropagationPolicy 中增加了 EndpointSlice 的下发能力。

相关资源对象:ServiceImport

  • 根据在 karmada 控制平面中创建的 ServiceImport ,去创建对应的 Service,这个 Service 是创建在 Karmada 控制平面的。
  • 如果删除控制平面中的 ServiceImport,也会删除控制平面中的由这个 ServiceImport 派生出来的 Service。
  • 由于 ServiceImport 的 controller 中会在控制平面中创建 Service,同时由于 ServiceExport 的 controller 中,会创建一个被 export 的 Service 的 EndpointSlice 的 work 在控制平面中,这个 work 会被 EndpointSlice controller 控制,同时 EndpointSlice controller 在控制平面中创建对应的 EndpointSlice 对象,EndpointSlice 中的每一个 Endpoint 的 IP 都是 Pod 的 IP 地址。
  • 在创建 ServiceImport 需要的 PropagationPolicy 的时候会在 karmada-webhook 中修改 PropagationPolicy 的 resource selector,在其中增加 Service 和 EndpointSlice 的部分,helper.GetFollowedResourceSelectorsWhenMatchServiceImport(policy.Spec.ResourceSelectors)。 最后会随着 detector 和 binding controller 中的逻辑,在对应的集群的 execution 的 space 中创建对应 Service 和 EndpointSlice 的 work,然后由 execution controller 去对应的工作集群去创建真正的资源对象。这样在 ServiceImport 的集群中,就可以通过派生出来的 Service,进行访问远程被 export 出来的服务。前提是两个集群之间的 Pod 网络是互通的。
  • 由 ServiceImport 派生出来的 service 的 name 为 :“derived-<service name>”。

hpa controller

hpa controller 主要负责将 Karmada 控制面中创建的 HPA 对象通过创建 Work 的方式下发到对应的集群中。

相关资源对象:HPA

[图片上传失败...(image-c1b1a8-1708308916175)]

  • 首先根据 HPA 的定义,获取需要被 HPA 控制的资源对象对象,这里主要就是指的像 Deployment 这种需要计算资源的对象。
  • 根据 HPA 控制的资源对象,去查找这些资源对象对应的 ResourceBinding 的 cr 对象,因为 ResourceBinding 是最终反应 Deployment 被调度到哪些集群的实时的,最终的状态。
  • 根据找到的集群,在这些集群中创建每个集群对应的 Work 对象,这个 Work 对象负责的资源对象就是 HPA 对象。
  • 通过这样的实现,保证了 HPA 被创建的集群一定是和真正的工作负载是在一个集群中的,保证了 HPA 的正确的调度。

目前看到需要思考的问题

  • 生产级灾备方案。
  • 在创建一个 namespace 资源对象的时候,Karmada 会同步在所有集群创建相同 namespace,如何支持在某一些集群中创建 namespace。
  • 如果上层有逻辑 quota ,如果底层无法感知和干预调度,会出现调度结果不一致的问题。
  • 怎样支持对 cni 的网络感知,举例,对于支持固定 IP 能力的 cni,如何让调度器感知。
  • 现在 operator 非常的多 (statefulset 部署为最佳实践) 但是 Karmada 未做有状态对象的状态收集。
  • 老版本 api 的兼容问题。举例在对接 Kubernetes1.15 的时候,出现 crd 的版本不匹配导致的 crd 无法通过 PropagationPolicy 下发到 Workload Cluster 中去。

竞品

clusternet

本文部分参考转自 知乎 - 云原生基地

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 核心概念 Master:集群的控制和管理 Kubernetes里的Master指的是集群控制节点,在每个Kuber...
    乙腾阅读 465评论 0 2
  • 容器技术概念入门篇 从进程说开去 容器本身没有价值,有价值的是“容器编排”。 容器其实是一种沙盒技术。顾名思义,沙...
    白板时钟阅读 2,462评论 0 2
  • kubernets学习结构 1. Architecture/Components Master Node: Wor...
    hgjsj阅读 1,581评论 0 0
  • [TOC] Docker容器平台选型调研 编排选型 Swarm Swarm可以从一个Dockerfile来构建镜像...
    AllenWu阅读 2,495评论 0 7
  • 了解什么是容器编排? 容器编排就是有关管理容器生命周期的全部工作,特别是在大型动态环境中。 软件团队使用容器编排来...
    强出头阅读 507评论 0 0