OpenKruise: ResourceDistribution

161 阅读1分钟

教程一览:Openkruise

doc :openkruise.io/zh/docs/use…

File: pkg/controller/resourcedistribution

ResourceDistribution 目前支持 SecretConfigMap 两类资源的分发和同步

使用示例

apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistribution
metadata:
  name: sample
spec:
  resource:
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: game-demo
    data:
      game.properties: |
        enemy.types=aliens,monsters
        player.maximum-lives=5
      player_initial_lives: "3"
      ui_properties_file_name: user-interface.properties
      user-interface.properties: |
        color.good=purple
        color.bad=yellow
        allow.textmode=true
  targets:
    excludedNamespaces:
      list:
      - name: ns-3
    includedNamespaces:
      list:
      - name: ns-1
      - name: ns-4
    namespaceLabelSelector:
      matchLabels:
        group: test

Reconcile

参数解析

  1. 拿到分发的资源信息: resource, errs := utils.DeserializeResource(&distributor.Spec.Resource, field.NewPath("resource"))
  2. 拿到分发的目的地信息: matchedNamespaces, unmatchedNamespaces, err := listNamespacesForDistributor(r.Client, &distributor.Spec.Targets)

资源分发

succeeded, distributeErrList := r.distributeResource(distributor, matchedNamespaces, resource)

  1. 看资源是否已经存在
oldResource := &unstructured.Unstructured{}
oldResource.SetGroupVersionKind(resource.GetObjectKind().GroupVersionKind())
getErr := r.Client.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: resourceName}, oldResource)
  1. 如果不存在则创建资源
if getErr != nil && errors.IsNotFound(getErr) {
   newResource := makeResourceObject(distributor, namespace, resource, resourceHashCode, nil)
   if createErr := r.Client.Create(context.TODO(), newResource.(client.Object)); createErr != nil 
  1. 如果资源存在但并不是通过 ResourceDistributor 控制的,则证明有矛盾,需要报错
if !isControlledByDistributor(oldResource, distributor) {
  ...... // return error
}
  1. 如果资源存在且受 ResourceDistributor 控制,那么通过函数 needToUpdate(oldResource, utils.ConvertToUnstructured(resource)) 判断资源内容是否需要更新,需要更新则调用 update 更掉

    1. // 从这里看的出来如果只是 metadata 的改变,不会触发资源分发的
      func needToUpdate(old, new *unstructured.Unstructured) bool {
          oldObject := old.DeepCopy().Object
          newObject := new.DeepCopy().Object
          oldObject["metadata"] = nil
          newObject["metadata"] = nil
          oldObject["status"] = nil
          newObject["status"] = nil
          return !reflect.DeepEqual(oldObject, newObject)
      }
      

错误清理

清理所管理的在不匹配 ns 的资源

_, cleanErrList := r.cleanResource(distributor, unmatchedNamespaces, resource)

逻辑比较简单,也是会先检查资源是否受管理,如果不受管理则跳过,否则清理

错误处理

conditions, errList := r.handleErrors(distributeErrList, cleanErrList)

Conditions 内容参考[分发状态追踪]

更新状态

newStatus := calculateNewStatus(distributor, conditions, int32(len(matchedNamespaces)), succeeded)
    if err := r.updateDistributorStatus(distributor, newStatus); err != nil {
        errList = append(errList, field.InternalError(field.NewPath("updateStatus"), err))
    }