diff --git a/housekeeper/operator/housekeeper-controller/controllers/update_controller.go b/housekeeper/operator/housekeeper-controller/controllers/update_controller.go index 5fcf92f19486f002254dfb7688b87dd989252b05..67feb11ed158fc040c7dbd4348d57049ea2b7eab 100644 --- a/housekeeper/operator/housekeeper-controller/controllers/update_controller.go +++ b/housekeeper/operator/housekeeper-controller/controllers/update_controller.go @@ -31,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + "k8s.io/kubectl/pkg/drain" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -95,7 +96,16 @@ func (r *UpdateReconciler) upgradeNodes(ctx context.Context, upInstance *houseke controlPlane = true } if _, ok := node.Labels[constants.LabelUpgrading]; ok { - //todo drain + drainer := &drain.Helper{ + Ctx: ctx, + Client: r.KubeClientSet, + GracePeriodSeconds: -1, + Out: os.Stdout, + ErrOut: os.Stderr, + } + if err := drainNode(drainer, node); err != nil { + return err + } pushInfo := &connection.PushInfo{ KubeVersion: upInstance.Spec.KubeVersion, OSImageURL: upInstance.Spec.OSImageURL, @@ -113,7 +123,17 @@ func (r *UpdateReconciler) upgradeNodes(ctx context.Context, upInstance *houseke func (r *UpdateReconciler) refreshNodes(ctx context.Context, upInstance *housekeeperiov1alpha1.Update, node *corev1.Node) error { deleteLabel(ctx, r, node) if node.Spec.Unschedulable { - //todo drain + drainer := &drain.Helper{ + Ctx: ctx, + Client: r.KubeClientSet, + GracePeriodSeconds: -1, + Out: os.Stdout, + ErrOut: os.Stderr, + } + if err := drain.cordonOrUncordonNode(false, drainer, node); err != nil { + return err + } + logrus.Infof("uncordon successfully %s node", node.Name) } return nil } @@ -129,6 +149,36 @@ func deleteLabel(ctx context.Context, r common.ReadWriterClient, node *corev1.No return nil } +func cordonOrUncordonNode(desired bool, drainer *drain.Helper, node *corev1.Node) error { + carry := "cordon" + if !desired { + carry = "uncordon" + } + logrus.Info(node.Name, "initiating %s", carry) + if node.Spec.Unschedulable == desired { + return nil + } + err := drain.RunCordonOrUncordon(drainer, node, desired) + if err != nil { + return fmt.Errorf("failed to %s: %w", carry, err) + } + return nil +} + +func drainNode(drainer *drain.Helper, node *corev1.Node) error { + logrus.Info(node.Name, "is cordoning") + // Perform cordon + if err := cordonOrUncordonNode(true, drainer, node); err != nil { + return fmt.Errorf("failed to cordon node %s: %v", node.Name, err) + } + // Attempt drain + logrus.Info(node.Name, "initiating drain") + if err := drain.RunNodeDrain(drainer, node.Name); err != nil { + return fmt.Errorf("unable to drain: %v", err) + } + return nil +} + func reqInstance(ctx context.Context, r common.ReadWriterClient, name types.NamespacedName, HostName string) (upInstance housekeeperiov1alpha1.Update, nodeInstance corev1.Node) { if err := r.Get(ctx, name, &upInstance); err != nil {