Skip to content

Commit ab7d367

Browse files
authored
Merge pull request #850 from SchSeba/skip_drain_on_reboot_single_node
Allow to drain on single node
2 parents e9b1c77 + a145133 commit ab7d367

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

controllers/drain_controller_helper.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,24 @@ func (dr *DrainReconcile) handleNodeDrainOrReboot(ctx context.Context,
8686
}
8787
}
8888

89+
// Check if we are on a single node, and we require a reboot/full-drain we just return
90+
fullNodeDrain := nodeDrainAnnotation == constants.RebootRequired
91+
singleNode := false
92+
if fullNodeDrain {
93+
nodeList := &corev1.NodeList{}
94+
err := dr.Client.List(ctx, nodeList)
95+
if err != nil {
96+
reqLogger.Error(err, "failed to list nodes")
97+
return ctrl.Result{}, err
98+
}
99+
if len(nodeList.Items) == 1 {
100+
reqLogger.Info("drainNode(): FullNodeDrain requested and we are on Single node")
101+
singleNode = true
102+
}
103+
}
104+
89105
// call the drain function that will also call drain to other platform providers like openshift
90-
drained, err := dr.drainer.DrainNode(ctx, node, nodeDrainAnnotation == constants.RebootRequired)
106+
drained, err := dr.drainer.DrainNode(ctx, node, fullNodeDrain, singleNode)
91107
if err != nil {
92108
reqLogger.Error(err, "error trying to drain the node")
93109
dr.recorder.Event(nodeNetworkState,

controllers/drain_controller_test.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ var _ = Describe("Drain Controller", Ordered, func() {
113113

114114
Context("when there is only one node", func() {
115115

116-
It("should drain", func(ctx context.Context) {
116+
It("should drain single node on drain require", func(ctx context.Context) {
117117
node, nodeState := createNode(ctx, "node1")
118118

119119
simulateDaemonSetAnnotation(node, constants.DrainRequired)
@@ -126,6 +126,33 @@ var _ = Describe("Drain Controller", Ordered, func() {
126126
expectNodeStateAnnotation(nodeState, constants.DrainIdle)
127127
expectNodeIsSchedulable(node)
128128
})
129+
130+
It("should not drain on reboot for single node", func(ctx context.Context) {
131+
node, nodeState := createNode(ctx, "node1")
132+
133+
simulateDaemonSetAnnotation(node, constants.RebootRequired)
134+
135+
expectNodeStateAnnotation(nodeState, constants.DrainComplete)
136+
expectNodeIsSchedulable(node)
137+
138+
simulateDaemonSetAnnotation(node, constants.DrainIdle)
139+
expectNodeStateAnnotation(nodeState, constants.DrainIdle)
140+
expectNodeIsSchedulable(node)
141+
})
142+
143+
It("should drain on reboot for multiple node", func(ctx context.Context) {
144+
node, nodeState := createNode(ctx, "node1")
145+
createNode(ctx, "node2")
146+
147+
simulateDaemonSetAnnotation(node, constants.RebootRequired)
148+
149+
expectNodeStateAnnotation(nodeState, constants.DrainComplete)
150+
expectNodeIsNotSchedulable(node)
151+
152+
simulateDaemonSetAnnotation(node, constants.DrainIdle)
153+
expectNodeStateAnnotation(nodeState, constants.DrainIdle)
154+
expectNodeIsSchedulable(node)
155+
})
129156
})
130157

131158
Context("when there are multiple nodes", func() {

pkg/drain/drainer.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (w writer) Write(p []byte) (n int, err error) {
2929
}
3030

3131
type DrainInterface interface {
32-
DrainNode(context.Context, *corev1.Node, bool) (bool, error)
32+
DrainNode(context.Context, *corev1.Node, bool, bool) (bool, error)
3333
CompleteDrainNode(context.Context, *corev1.Node) (bool, error)
3434
}
3535

@@ -53,7 +53,7 @@ func NewDrainer(platformHelpers platforms.Interface) (DrainInterface, error) {
5353
// DrainNode the function cordon a node and drain pods from it
5454
// if fullNodeDrain true all the pods on the system will get drained
5555
// for openshift system we also pause the machine config pool this machine is part of it
56-
func (d *Drainer) DrainNode(ctx context.Context, node *corev1.Node, fullNodeDrain bool) (bool, error) {
56+
func (d *Drainer) DrainNode(ctx context.Context, node *corev1.Node, fullNodeDrain, singleNode bool) (bool, error) {
5757
reqLogger := log.FromContext(ctx).WithValues("drain node", node.Name)
5858
reqLogger.Info("drainNode(): Node drain requested", "node", node.Name)
5959

@@ -68,6 +68,11 @@ func (d *Drainer) DrainNode(ctx context.Context, node *corev1.Node, fullNodeDrai
6868
return false, nil
6969
}
7070

71+
// Check if we are on a single node, and we require a reboot/full-drain we just return
72+
if fullNodeDrain && singleNode {
73+
return true, nil
74+
}
75+
7176
drainHelper := createDrainHelper(d.kubeClient, ctx, fullNodeDrain)
7277
backoff := wait.Backoff{
7378
Steps: 5,

0 commit comments

Comments
 (0)