De-couple cordoning and draining#1119
Conversation
0a04d6a to
5299319
Compare
- Add a new function `cordonNode()` and call it in the callers of `RunDrain()``. - For preservation of failed machines, use custom taint to cordon. - Remove function `RunCordonOrUncordon` - Add helper function `updateMachineStatusForDrain` to update machine status during drain across all drain-xxx functions.
5299319 to
49ad362
Compare
takoverflow
left a comment
There was a problem hiding this comment.
Thanks for the changes, would it be possible as part of this PR to combine the three separate drain methods? Since it's getting harder to keep track of which one does what specifically.
There was a problem hiding this comment.
Since you've gotten rid of this skipDrain check elsewhere by returning early, why not do it here as well, this would allow for removal of another if-else at L1612. WDYT?
There was a problem hiding this comment.
Addressed in 6f42253. The function returns early now when the node name is empty.
| return nil | ||
| } | ||
| if node.Spec.Unschedulable { | ||
| klog.V(3).Infof("Scheduling state for node %q is already in desired state", node.Name) |
There was a problem hiding this comment.
| klog.V(3).Infof("Scheduling state for node %q is already in desired state", node.Name) | |
| klog.V(3).Infof("Node %q is already marked as Unschedulable", node.Name) |
The log stating desired state without context doesn't really inform what the desired state actually is.
There was a problem hiding this comment.
I've tried not to deviate from original behaviour. Will make this change since two of you feel this should be done 👍
There was a problem hiding this comment.
Shall I make it "Node %q is already cordoned"? To maintain consistency with the remaining logs and comments?
|
|
||
| // Step 4: remove preservation-related taint regardless of machine phase. | ||
| // If machine is in Running, workload can get scheduled onto it. | ||
| err = nodeops.RemoveTaintOffNode(ctx, c.targetCoreClient, updatedNode.Name, updatedNode, &v1.Taint{Key: machineutils.NodePreservedTaintKey, Effect: v1.TaintEffectNoSchedule}) |
There was a problem hiding this comment.
| err = nodeops.RemoveTaintOffNode(ctx, c.targetCoreClient, updatedNode.Name, updatedNode, &v1.Taint{Key: machineutils.NodePreservedTaintKey, Effect: v1.TaintEffectNoSchedule}) | |
| err = nodeops.RemoveTaintOffNode(ctx, c.targetCoreClient, updatedNode.Name, updatedNode, &v1.Taint{ | |
| Key: machineutils.NodePreservedTaintKey, | |
| Effect: v1.TaintEffectNoSchedule, | |
| }) |
There was a problem hiding this comment.
What happens if c.targetCoreClient is nil?
| // If machine is in Running, workload can get scheduled onto it. | ||
| err = nodeops.RemoveTaintOffNode(ctx, c.targetCoreClient, updatedNode.Name, updatedNode, &v1.Taint{Key: machineutils.NodePreservedTaintKey, Effect: v1.TaintEffectNoSchedule}) | ||
| if err != nil { | ||
| return true, err |
There was a problem hiding this comment.
Why is this returning true?
There was a problem hiding this comment.
Should not be returning true. Will make the change.
There was a problem hiding this comment.
Changed return value to false. Addressed in b036aac.
| } | ||
| } | ||
|
|
||
| if nodeName == "" { |
There was a problem hiding this comment.
This can be moved above the conditions check, since that is useless if the nodeName is ""
| if err == nil { | ||
| klog.V(3).Infof("(drainNode) For node %q, machine %q, nodeReadyCondition: %s, readOnlyFileSystemCondition: %s", nodeName, machine.Name, nodeReadyCondition, readOnlyFileSystemCondition) | ||
| } else if apierrors.IsNotFound(err) { | ||
| klog.Warningf("(drainNode) Node %q for machine %q doesn't exist, so drain will finish instantly", nodeName, machine.Name) |
There was a problem hiding this comment.
| klog.Warningf("(drainNode) Node %q for machine %q doesn't exist, so drain will finish instantly", nodeName, machine.Name) | |
| klog.Warningf("(drainNode) Node %q for machine %q doesn't exist. Skipping drain.", nodeName, machine.Name) |
There was a problem hiding this comment.
Addressed in 96309f2. I've made the changes across all drain functions.
| } | ||
|
|
||
| // since we do not wish to accidentally uncordon a user-cordoned node after preservation stops, | ||
| // we add a taint with effect NoSchedule, before draining the node, instead of setting Spec.Unschedulable = true |
There was a problem hiding this comment.
| // we add a taint with effect NoSchedule, before draining the node, instead of setting Spec.Unschedulable = true | |
| // we add a taint with effect 'NoSchedule' before draining the node, instead of cordoning it. |
|
/assign |
| } else { // regular drain already waits for vol detach and attach for another node. | ||
| description = fmt.Sprintf("Drain successful. %s", machineutils.InitiateVMDeletion) | ||
| } | ||
| err = fmt.Errorf("%s", description) |
There was a problem hiding this comment.
I do not see this err value being used anywhere, and it seems odd (or rather wrong) that a "Drain successful" message is added to an error
There was a problem hiding this comment.
This is the original behaviour, if I am not wrong:
This is aligned with the other functions called in triggerDeletionFlow :
There was a problem hiding this comment.
In the original behaviour this was needed because err was returned. Since the final return uses fmt.Errorf("%s", description) now, err ends up not being used
There was a problem hiding this comment.
You're right. The assignment is useless. Will make the change 👍
| if err != nil { | ||
| // Deletion could be triggered when machine is just being created, no node present then | ||
| return nil | ||
| } |
There was a problem hiding this comment.
Use apierrors.IsNotFound(err) to filter out cases where node is not found. For all other errors, return the error
There was a problem hiding this comment.
This is the behaviour of the earlier cordoning function:
machine-controller-manager/pkg/util/provider/drain/drain.go
Lines 1169 to 1174 in 59134c3
I can change this if you like.
There was a problem hiding this comment.
Yes, please, I would like this change to be added.
Any other error should be caught and returned
There was a problem hiding this comment.
Have changed cordonNode() (now moved to node.go) to return all errors except for NotFound errors. Addressed in : cbdbb69
This is needed, but I think it should not be done in this PR. The scope and complexity will increase considerably. Not to mention additional time to properly test it. |
- Replace "Cordoning" in descriptions with "Drain" on failure of `cordonNode()`. - Correct return value from `stopPreservationIfActive()`. - Move warning and early return due to empty node above condition check. - Change comment as per reviewer's suggestion. - Change error message on preservation-related taint failure to say "tainting" instead of "cordoning".
Alright, fair enough. That can be tackled later. |
- Improve readability of `RemoveTaintOffNode` function call in `stopPreservationIfActive`. - Correct warning on `NotFound` errors in drain functions. - Change log in `cordonNode` to improve clarity. - Add node details to warning when cordoning fails for the force-deletion case.
- Return early from `drainNode` when nodename is empty. Remove `skipDrain`.
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
- Remove unnecessary assignment to `err`. - Move `cordonNode()` to `node.go` - Return `err` from `cordonNode()` for errors other than NotFound errors.
| } | ||
|
|
||
| // cordonNode sets `node.Spec.Unschedulable` to true, if not already set to true | ||
| func (c *controller) cordonNode(ctx context.Context, nodeName string) error { |
There was a problem hiding this comment.
The function below this one, uncordonNodeIfCordoned sets the value for spec.Unschedulable = false.
This could remove a manually set value, as manageMachinePreservation() calls this function when a machine goes from Failed back into Running.
There was a problem hiding this comment.
Thanks. Will make the change. I think I'll put this PR on hold until #1118 gets merged. After that will take all this into consideration.
| if err != nil { | ||
| return err | ||
| } | ||
| return nil |
There was a problem hiding this comment.
| if err != nil { | |
| return err | |
| } | |
| return nil | |
| return err |
Nit
There was a problem hiding this comment.
Ha ha. Thanks! Good catch!
There was a problem hiding this comment.
Ha ha. Thanks! Good catch!
There was a problem hiding this comment.
Ha ha. Thanks! Good catch!
What this PR does / why we need it:
This PR removes the cordoning activity from
RunDrainallowing us to control the two activities separately. This also enables the cordoning during machine preservation's drain to be done without alteringspec.Unschedulable, thereby ensuring a user's manual cordoning/uncordoning is always honoured.The changes in the PR are:
RunCordonOrUncordoncordonNode()and call it in the callers ofRunDrain().updateMachineStatusForDrainto update machine status during drain across all drain-xxx functions.Which issue(s) this PR fixes:
Fixes #1114
Special notes for your reviewer:
IT was run with provider-AWS
The changes were tested by running mcm and mcm-provider-aws locally, targeting a shoot cluster.
Scenarios tested:
Release note: