教程一览:Openkruise
doc :openkruise.io/zh/docs/use…
File: pkg/controller/resourcedistribution
ResourceDistribution 目前支持 Secret 和 ConfigMap 两类资源的分发和同步
使用示例
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
参数解析
- 拿到分发的资源信息: resource, errs := utils.DeserializeResource(&distributor.Spec.Resource, field.NewPath("resource"))
- 拿到分发的目的地信息: matchedNamespaces, unmatchedNamespaces, err := listNamespacesForDistributor(r.Client, &distributor.Spec.Targets)
资源分发
succeeded, distributeErrList := r.distributeResource(distributor, matchedNamespaces, resource)
- 看资源是否已经存在
oldResource := &unstructured.Unstructured{}
oldResource.SetGroupVersionKind(resource.GetObjectKind().GroupVersionKind())
getErr := r.Client.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: resourceName}, oldResource)
- 如果不存在则创建资源
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
- 如果资源存在但并不是通过 ResourceDistributor 控制的,则证明有矛盾,需要报错
if !isControlledByDistributor(oldResource, distributor) {
...... // return error
}
-
如果资源存在且受 ResourceDistributor 控制,那么通过函数
needToUpdate(oldResource, utils.ConvertToUnstructured(resource))判断资源内容是否需要更新,需要更新则调用 update 更掉-
// 从这里看的出来如果只是 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))
}