Skip to content
27 changes: 0 additions & 27 deletions pkg/util/provider/drain/drain.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,6 @@ func (o *Options) RunDrain(ctx context.Context) error {
)
}()

if err := o.RunCordonOrUncordon(drainContext, true); err != nil {
klog.Errorf("Drain Error: Cordoning of node failed with error: %v", err)
return err
}
if !cache.WaitForCacheSync(drainContext.Done(), o.podSynced) {
err := fmt.Errorf("timed out waiting for pod cache to sync")
return err
Expand Down Expand Up @@ -1164,29 +1160,6 @@ func SupportEviction(clientset kubernetes.Interface) (string, error) {
return "", nil
}

// RunCordonOrUncordon runs either Cordon or Uncordon. The desired value for
// "Unschedulable" is passed as the first arg.
func (o *Options) RunCordonOrUncordon(ctx context.Context, desired bool) error {
node, err := o.client.CoreV1().Nodes().Get(ctx, o.nodeName, metav1.GetOptions{})
if err != nil {
// Deletion could be triggered when machine is just being created, no node present then
return nil
}
unsched := node.Spec.Unschedulable
if unsched == desired {
klog.V(3).Infof("Scheduling state for node %q is already in desired state", node.Name)
} else {
clone := node.DeepCopy()
clone.Spec.Unschedulable = desired

_, err = o.client.CoreV1().Nodes().Update(ctx, clone, metav1.UpdateOptions{})
if err != nil {
return err
}
}
return nil
}

func getPdbForPod(pdbLister policyv1listers.PodDisruptionBudgetLister, pod *corev1.Pod) *policyv1.PodDisruptionBudget {
// GetPodPodDisruptionBudgets returns an error only if no PodDisruptionBudgets are found.
// We don't return that as an error to the caller.
Expand Down
16 changes: 9 additions & 7 deletions pkg/util/provider/machinecontroller/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"
"time"

"github.com/gardener/machine-controller-manager/pkg/util/nodeops"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -806,6 +807,8 @@ func (c *controller) manageMachinePreservation(ctx context.Context, machine *v1a
var removeAnnotations bool
clone := machine.DeepCopy()
switch effectivePreserveValue {
// effectivePreserveValue == "" implies the preservation annotation was deleted to indicate that
// preservation must be stopped
case "", machineutils.PreserveMachineAnnotationValueFalse:
clone, err = c.stopPreservationIfActive(ctx, clone, removeAnnotations)
case machineutils.PreserveMachineAnnotationValueWhenFailed:
Expand Down Expand Up @@ -840,19 +843,18 @@ func (c *controller) manageMachinePreservation(ctx context.Context, machine *v1a
if err != nil {
return
}
// For the preserve=now path (preservation still active), uncordon the node if the machine
// has recovered to Running. For all other cases, stopPreservationIfActive path handles uncordon internally.
// For the preserve=now path (preservation still active), untaint the node if the machine
// has recovered to Running. For all other cases, stopPreservationIfActive path handles untainting internally.
if clone.Status.CurrentStatus.PreserveExpiryTime != nil && clone.Status.CurrentStatus.Phase == v1alpha1.MachineRunning && nodeName != "" {
var node *corev1.Node
node, err = c.nodeLister.Get(nodeName)
if err != nil {
if apierrors.IsNotFound(err) {
err = nil
return
}
return
}
err = c.uncordonNodeIfCordoned(ctx, node)
err = nodeops.RemoveTaintOffNode(ctx, c.targetCoreClient, node.Name, node, &corev1.Taint{
Key: machineutils.NodePreservedTaintKey,
Effect: corev1.TaintEffectNoSchedule,
})
if err != nil {
return
}
Expand Down
60 changes: 34 additions & 26 deletions pkg/util/provider/machinecontroller/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"math"
"time"

taintutils "github.com/gardener/machine-controller-manager/pkg/util/taints"
k8stesting "k8s.io/client-go/testing"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -4105,7 +4106,7 @@ var _ = Describe("machine", func() {
nodeName string
machinePhase v1alpha1.MachinePhase
preserveExpiryTime *metav1.Time
nodeUnschedulable bool
nodeTainted bool
}
type expect struct {
retry machineutils.RetryPeriod
Expand All @@ -4114,7 +4115,7 @@ var _ = Describe("machine", func() {
machineAnnotationValue string
laNodePreserveValue string
err error
nodeUnschedulable *bool
nodeTainted bool
}
type testCase struct {
setup setup
Expand Down Expand Up @@ -4165,12 +4166,20 @@ var _ = Describe("machine", func() {
Annotations: nodeAnnotations,
},
Spec: corev1.NodeSpec{
Unschedulable: tc.setup.nodeUnschedulable,
Taints: []corev1.Taint{},
},
Status: corev1.NodeStatus{
Conditions: []corev1.NodeCondition{},
},
}
if tc.setup.nodeTainted {
node.Spec.Taints = []corev1.Taint{
{
Key: machineutils.NodePreservedTaintKey,
Effect: corev1.TaintEffectNoSchedule,
},
}
}
targetCoreObjects = append(targetCoreObjects, node)
}
c, trackers := createController(stop, testNamespace, controlMachineObjects, nil, targetCoreObjects, nil, false)
Expand Down Expand Up @@ -4211,9 +4220,7 @@ var _ = Describe("machine", func() {
} else {
Expect(found).To(BeFalse())
}
if tc.expect.nodeUnschedulable != nil {
Expect(updatedNode.Spec.Unschedulable).To(Equal(*tc.expect.nodeUnschedulable))
}
Expect(taintutils.TaintExists(updatedNode.Spec.Taints, &corev1.Taint{Key: machineutils.NodePreservedTaintKey, Effect: corev1.TaintEffectNoSchedule})).To(Equal(tc.expect.nodeTainted))
}
Expect(updatedMachine.Annotations[machineutils.PreserveMachineAnnotationKey]).To(Equal(tc.expect.machineAnnotationValue))
Expect(updatedMachine.Annotations[machineutils.LastAppliedNodePreserveValueAnnotationKey]).To(Equal(tc.expect.laNodePreserveValue))
Expand Down Expand Up @@ -4271,7 +4278,8 @@ var _ = Describe("machine", func() {
nodeCondition: &corev1.NodeCondition{
Type: v1alpha1.NodePreserved,
Status: corev1.ConditionTrue},
retry: machineutils.LongRetry,
retry: machineutils.LongRetry,
nodeTainted: true,
},
}),
Entry("when node of preserved machine is annotated with preserve value 'false', should stop preservation", testCase{
Expand Down Expand Up @@ -4303,6 +4311,7 @@ var _ = Describe("machine", func() {
Status: corev1.ConditionTrue},
retry: machineutils.LongRetry,
machineAnnotationValue: machineutils.PreserveMachineAnnotationValueAutoPreserved,
nodeTainted: true,
},
}),
Entry("when machine is annotated with preserve=now and preservation times out, should stop preservation, and remove annotation", testCase{
Expand All @@ -4326,6 +4335,7 @@ var _ = Describe("machine", func() {
nodeName: "node-1",
machinePhase: v1alpha1.MachineFailed,
preserveExpiryTime: &metav1.Time{Time: metav1.Now().Add(-1 * time.Minute)},
nodeTainted: true,
},
expect: expect{
preserveExpiryTimeIsSet: false,
Expand Down Expand Up @@ -4414,11 +4424,13 @@ var _ = Describe("machine", func() {
nodeName: "node-1",
machinePhase: v1alpha1.MachineRunning,
preserveExpiryTime: &metav1.Time{Time: metav1.Now().Add(1 * time.Hour)},
nodeTainted: true,
},
expect: expect{
preserveExpiryTimeIsSet: false,
nodeCondition: &corev1.NodeCondition{Type: v1alpha1.NodePreserved, Status: corev1.ConditionFalse},
machineAnnotationValue: "",
nodeTainted: false,
retry: machineutils.LongRetry,
err: nil,
},
Expand Down Expand Up @@ -4462,81 +4474,77 @@ var _ = Describe("machine", func() {
err: nil,
},
}),
Entry("when preserve=when-failed machine with cordoned node recovers to Running, should stop preservation and uncordon node", func() testCase {
uncordoned := false
Entry("when preserved machine with preserve=when-failed recovers to Running, should stop preservation and untaint node", func() testCase {
return testCase{
setup: setup{
machineAnnotationValue: machineutils.PreserveMachineAnnotationValueWhenFailed,
machineAnnotated: true,
nodeName: "node-1",
machinePhase: v1alpha1.MachineRunning,
preserveExpiryTime: &metav1.Time{Time: metav1.Now().Add(1 * time.Hour)},
nodeUnschedulable: true,
nodeTainted: true,
},
expect: expect{
preserveExpiryTimeIsSet: false,
nodeCondition: &corev1.NodeCondition{Type: v1alpha1.NodePreserved, Status: corev1.ConditionFalse},
machineAnnotationValue: machineutils.PreserveMachineAnnotationValueWhenFailed,
retry: machineutils.LongRetry,
nodeUnschedulable: &uncordoned,
nodeTainted: false,
},
}
}()),
Entry("when preserve=when-failed machine with cordoned node has expired preservation while Running, should stop preservation and uncordon node", func() testCase {
uncordoned := false
Entry("when preserved machine with preserve=when-failed has expired preservation while in Failed phase, should stop preservation and untaint node", func() testCase {
return testCase{
setup: setup{
machineAnnotationValue: machineutils.PreserveMachineAnnotationValueWhenFailed,
machineAnnotated: true,
nodeName: "node-1",
machinePhase: v1alpha1.MachineRunning,
machinePhase: v1alpha1.MachineFailed,
preserveExpiryTime: &metav1.Time{Time: metav1.Now().Add(-1 * time.Minute)},
nodeUnschedulable: true,
nodeTainted: true,
},
expect: expect{
preserveExpiryTimeIsSet: false,
nodeCondition: &corev1.NodeCondition{Type: v1alpha1.NodePreserved, Status: corev1.ConditionFalse},
machineAnnotationValue: "",
retry: machineutils.LongRetry,
nodeUnschedulable: &uncordoned,
nodeTainted: false,
},
}
}()),
Entry("when preserve=when-failed machine is Failed with active preservation and cordoned node, node should stay cordoned", func() testCase {
cordoned := true
Entry("when preserve=when-failed machine is in Failed phase with active preservation and tainted node, node should stay tainted", func() testCase {
return testCase{
setup: setup{
nodeAnnotationValue: machineutils.PreserveMachineAnnotationValueWhenFailed,
nodeAnnotated: true,
nodeName: "node-1",
machinePhase: v1alpha1.MachineFailed,
nodeUnschedulable: true,
nodeTainted: true,
},
expect: expect{
laNodePreserveValue: machineutils.PreserveMachineAnnotationValueWhenFailed,
preserveExpiryTimeIsSet: true,
nodeCondition: &corev1.NodeCondition{Type: v1alpha1.NodePreserved, Status: corev1.ConditionTrue},
retry: machineutils.LongRetry,
nodeUnschedulable: &cordoned,
nodeTainted: true,
},
}
}()),
Entry("when preserve=now machine is Failed with active preservation and cordoned node, node should stay cordoned", func() testCase {
cordoned := true
Entry("when preserve=now machine is Failed with active preservation and tainted node, node should stay tainted", func() testCase {
return testCase{
setup: setup{
machineAnnotationValue: machineutils.PreserveMachineAnnotationValueNow,
machineAnnotated: true,
nodeName: "node-1",
machinePhase: v1alpha1.MachineFailed,
nodeUnschedulable: true,
nodeTainted: true,
},
expect: expect{
preserveExpiryTimeIsSet: true,
nodeCondition: &corev1.NodeCondition{Type: v1alpha1.NodePreserved, Status: corev1.ConditionTrue},
machineAnnotationValue: machineutils.PreserveMachineAnnotationValueNow,
retry: machineutils.LongRetry,
nodeUnschedulable: &cordoned,
nodeTainted: true,
},
}
}()),
Expand Down Expand Up @@ -4588,8 +4596,8 @@ var _ = Describe("machine", func() {
Expect(updatedNode.Spec.Unschedulable).To(Equal(nodeUnschedulable))
}
},
Entry("node is cordoned", true, true),
Entry("node is uncordoned", false, true),
Entry("node is tainted", true, true),
Entry("node is untainted", false, true),
Entry("node retrieval fails (node not found)", false, false),
)
})
Expand Down
Loading
Loading