Skip to content

Commit

Permalink
Merge pull request #5893 from XiShanYongYe-Chang/inject-preservedLabe…
Browse files Browse the repository at this point in the history
…lState

Inject preservedLabelState to the failover to clusters
  • Loading branch information
karmada-bot authored Nov 29, 2024
2 parents 5beb710 + 1cdc646 commit 54be414
Showing 1 changed file with 48 additions and 25 deletions.
73 changes: 48 additions & 25 deletions pkg/controllers/binding/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -43,34 +44,18 @@ func ensureWork(
overrideManager overridemanager.OverrideManager, binding metav1.Object, scope apiextensionsv1.ResourceScope,
) error {
var targetClusters []workv1alpha2.TargetCluster
var placement *policyv1alpha1.Placement
var requiredByBindingSnapshot []workv1alpha2.BindingSnapshot
var replicas int32
var conflictResolutionInBinding policyv1alpha1.ConflictResolution
var suspension *policyv1alpha1.Suspension
var preserveResourcesOnDeletion *bool
var bindingSpec workv1alpha2.ResourceBindingSpec
switch scope {
case apiextensionsv1.NamespaceScoped:
bindingObj := binding.(*workv1alpha2.ResourceBinding)
targetClusters = bindingObj.Spec.Clusters
requiredByBindingSnapshot = bindingObj.Spec.RequiredBy
placement = bindingObj.Spec.Placement
replicas = bindingObj.Spec.Replicas
conflictResolutionInBinding = bindingObj.Spec.ConflictResolution
suspension = bindingObj.Spec.Suspension
preserveResourcesOnDeletion = bindingObj.Spec.PreserveResourcesOnDeletion
bindingSpec = bindingObj.Spec
case apiextensionsv1.ClusterScoped:
bindingObj := binding.(*workv1alpha2.ClusterResourceBinding)
targetClusters = bindingObj.Spec.Clusters
requiredByBindingSnapshot = bindingObj.Spec.RequiredBy
placement = bindingObj.Spec.Placement
replicas = bindingObj.Spec.Replicas
conflictResolutionInBinding = bindingObj.Spec.ConflictResolution
suspension = bindingObj.Spec.Suspension
preserveResourcesOnDeletion = bindingObj.Spec.PreserveResourcesOnDeletion
bindingSpec = bindingObj.Spec
}

targetClusters = mergeTargetClusters(targetClusters, requiredByBindingSnapshot)
targetClusters = bindingSpec.Clusters
targetClusters = mergeTargetClusters(targetClusters, bindingSpec.RequiredBy)

var jobCompletions []workv1alpha2.TargetCluster
var err error
Expand All @@ -89,7 +74,7 @@ func ensureWork(

// If and only if the resource template has replicas, and the replica scheduling policy is divided,
// we need to revise replicas.
if needReviseReplicas(replicas, placement) {
if needReviseReplicas(bindingSpec.Replicas, bindingSpec.Placement) {
if resourceInterpreter.HookEnabled(clonedWorkload.GroupVersionKind(), configv1alpha1.InterpreterOperationReviseReplica) {
clonedWorkload, err = resourceInterpreter.ReviseReplica(clonedWorkload, int64(targetCluster.Replicas))
if err != nil {
Expand Down Expand Up @@ -121,13 +106,17 @@ func ensureWork(
workLabel := mergeLabel(clonedWorkload, binding, scope)

annotations := mergeAnnotations(clonedWorkload, binding, scope)
annotations = mergeConflictResolution(clonedWorkload, conflictResolutionInBinding, annotations)
annotations = mergeConflictResolution(clonedWorkload, bindingSpec.ConflictResolution, annotations)
annotations, err = RecordAppliedOverrides(cops, ops, annotations)
if err != nil {
klog.Errorf("Failed to record appliedOverrides, Error: %v", err)
return err
}

// we need to figure out if the targetCluster is in the cluster we are going to migrate application to.
// If yes, we have to inject the preserved label state to clonedWorkload with the label.
clonedWorkload = injectReservedLabelState(bindingSpec, targetCluster, clonedWorkload, len(targetClusters))

workMeta := metav1.ObjectMeta{
Name: names.GenerateWorkName(clonedWorkload.GetKind(), clonedWorkload.GetName(), clonedWorkload.GetNamespace()),
Namespace: workNamespace,
Expand All @@ -141,15 +130,49 @@ func ensureWork(
c,
workMeta,
clonedWorkload,
helper.WithSuspendDispatching(shouldSuspendDispatching(suspension, targetCluster)),
helper.WithPreserveResourcesOnDeletion(ptr.Deref(preserveResourcesOnDeletion, false)),
helper.WithSuspendDispatching(shouldSuspendDispatching(bindingSpec.Suspension, targetCluster)),
helper.WithPreserveResourcesOnDeletion(ptr.Deref(bindingSpec.PreserveResourcesOnDeletion, false)),
); err != nil {
return err
}
}
return nil
}

// injectReservedLabelState injects the reservedLabelState in to the failover to cluster.
// We have the following restrictions on whether to perform injection operations:
// 1. Only the scenario where an application is deployed in one cluster and migrated to
// another cluster is considered.
// 2. If consecutive failovers occur, for example, an application is migrated form clusterA
// to clusterB and then to clusterC, the PreservedLabelState before the last failover is
// used for injection. If the PreservedLabelState is empty, the injection is skipped.
// 3. The injection operation is performed only when PurgeMode is set to Immediately.
func injectReservedLabelState(bindingSpec workv1alpha2.ResourceBindingSpec, moveToCluster workv1alpha2.TargetCluster, workload *unstructured.Unstructured, clustersLen int) *unstructured.Unstructured {
if clustersLen > 1 {
return workload
}

if len(bindingSpec.GracefulEvictionTasks) == 0 {
return workload
}
targetEvictionTask := bindingSpec.GracefulEvictionTasks[len(bindingSpec.GracefulEvictionTasks)-1]

if targetEvictionTask.PurgeMode != policyv1alpha1.Immediately {
return workload
}

clustersBeforeFailover := sets.NewString(targetEvictionTask.ClustersBeforeFailover...)
if clustersBeforeFailover.Has(moveToCluster.Name) {
return workload
}

for key, value := range targetEvictionTask.PreservedLabelState {
util.MergeLabel(workload, key, value)
}

return workload
}

func mergeTargetClusters(targetClusters []workv1alpha2.TargetCluster, requiredByBindingSnapshot []workv1alpha2.BindingSnapshot) []workv1alpha2.TargetCluster {
if len(requiredByBindingSnapshot) == 0 {
return targetClusters
Expand Down

0 comments on commit 54be414

Please sign in to comment.