diff --git a/cmd/kops-controller/controllers/legacy_node_controller.go b/cmd/kops-controller/controllers/legacy_node_controller.go index 832d86ab77..8f7c10c4ad 100644 --- a/cmd/kops-controller/controllers/legacy_node_controller.go +++ b/cmd/kops-controller/controllers/legacy_node_controller.go @@ -132,12 +132,23 @@ func (r *LegacyNodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } - if len(updateLabels) == 0 { + deleteLabels := make(map[string]struct{}) + for k := range node.Labels { + // If it is one of our managed labels, "prune" values we don't want to be there + switch k { + case nodelabels.RoleLabelMaster16, nodelabels.RoleLabelAPIServer16, nodelabels.RoleLabelNode16, nodelabels.RoleLabelControlPlane20: + if _, found := labels[k]; !found { + deleteLabels[k] = struct{}{} + } + } + } + + if len(updateLabels) == 0 && len(deleteLabels) == 0 { klog.V(4).Infof("no label changes needed for %s", node.Name) return ctrl.Result{}, nil } - if err := patchNodeLabels(r.coreV1Client, ctx, node, updateLabels); err != nil { + if err := patchNodeLabels(r.coreV1Client, ctx, node, updateLabels, deleteLabels); err != nil { klog.Warningf("failed to patch node labels on %s: %v", node.Name, err) return ctrl.Result{}, err } diff --git a/cmd/kops-controller/controllers/node_controller.go b/cmd/kops-controller/controllers/node_controller.go index 136f01bf5c..f7017fe03a 100644 --- a/cmd/kops-controller/controllers/node_controller.go +++ b/cmd/kops-controller/controllers/node_controller.go @@ -29,6 +29,7 @@ import ( corev1client "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/klog/v2" "k8s.io/kops/pkg/nodeidentity" + "k8s.io/kops/pkg/nodelabels" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -99,12 +100,23 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. } } - if len(updateLabels) == 0 { + deleteLabels := make(map[string]struct{}) + for k := range node.Labels { + // If it is one of our managed labels, "prune" values we don't want to be there + switch k { + case nodelabels.RoleLabelMaster16, nodelabels.RoleLabelAPIServer16, nodelabels.RoleLabelNode16, nodelabels.RoleLabelControlPlane20: + if _, found := labels[k]; !found { + deleteLabels[k] = struct{}{} + } + } + } + + if len(updateLabels) == 0 && len(deleteLabels) == 0 { klog.V(4).Infof("no label changes needed for %s", node.Name) return ctrl.Result{}, nil } - if err := patchNodeLabels(r.coreV1Client, ctx, node, updateLabels); err != nil { + if err := patchNodeLabels(r.coreV1Client, ctx, node, updateLabels, deleteLabels); err != nil { klog.Warningf("failed to patch node labels on %s: %v", node.Name, err) return ctrl.Result{}, err } @@ -124,14 +136,22 @@ type nodePatch struct { } type nodePatchMetadata struct { - Labels map[string]string `json:"labels,omitempty"` + Labels map[string]*string `json:"labels,omitempty"` } // patchNodeLabels patches the node labels to set the specified labels -func patchNodeLabels(client *corev1client.CoreV1Client, ctx context.Context, node *corev1.Node, setLabels map[string]string) error { +func patchNodeLabels(client *corev1client.CoreV1Client, ctx context.Context, node *corev1.Node, setLabels map[string]string, deleteLabels map[string]struct{}) error { nodePatchMetadata := &nodePatchMetadata{ - Labels: setLabels, + Labels: make(map[string]*string), } + for k, v := range setLabels { + v := v + nodePatchMetadata.Labels[k] = &v + } + for k := range deleteLabels { + nodePatchMetadata.Labels[k] = nil + } + nodePatch := &nodePatch{ Metadata: nodePatchMetadata, }