Skip to content

Commit 8fd35d1

Browse files
author
Nic Cope
committed
Make pod eviction filters configurable
This changes the default behaviour in that Draino would previously evict unreplicated pods and pods with local storage, and now will not. This is not ideal, but alecthomas/kingpin#243 would result in a confusing user experience if we used a mix of default true and default false boolean flags. Given the project is about 10 minutes old it seems acceptable to make this change.
1 parent f3c4258 commit 8fd35d1

File tree

2 files changed

+29
-25
lines changed

2 files changed

+29
-25
lines changed

README.md

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,24 @@ usage: draino [<flags>] [<node-conditions>...]
2727
Automatically cordons and drains nodes that match the supplied conditions.
2828
2929
Flags:
30-
--help Show context-sensitive help (also try --help-long
31-
and --help-man).
32-
-d, --debug Run with debug logging.
33-
--listen=":10002" Address at which to expose /metrics and /healthz.
34-
--kubeconfig=KUBECONFIG Path to kubeconfig file. Leave unset to use
35-
in-cluster config.
36-
--master=MASTER Address of Kubernetes API server. Leave unset to
37-
use in-cluster config.
38-
--dry-run Emit an event without cordoning or draining
39-
matching nodes.
40-
--max-grace-period=8m0s Maximum time evicted pods will be given to
41-
terminate gracefully.
42-
--eviction-headroom=30s Additional time to wait after a pod's termination
43-
grace period for it to have been deleted.
44-
--drain-buffer=10m0s Minimum time between starting each drain. Nodes
45-
are always cordoned immediately.
30+
--help Show context-sensitive help (also try --help-long and --help-man).
31+
-d, --debug Run with debug logging.
32+
--listen=":10002" Address at which to expose /metrics and /healthz.
33+
--kubeconfig=KUBECONFIG Path to kubeconfig file. Leave unset to use in-cluster config.
34+
--master=MASTER Address of Kubernetes API server. Leave unset to use in-cluster config.
35+
--dry-run Emit an event without cordoning or draining matching nodes.
36+
--max-grace-period=8m0s Maximum time evicted pods will be given to terminate gracefully.
37+
--eviction-headroom=30s Additional time to wait after a pod's termination grace period for it to have been deleted.
38+
--drain-buffer=10m0s Minimum time between starting each drain. Nodes are always cordoned immediately.
4639
--node-label=KEY=VALUE ...
47-
Only nodes with this label will be eligible for
48-
cordoning and draining. May be specified multiple
49-
times.
40+
Only nodes with this label will be eligible for cordoning and draining. May be specified multiple times.
41+
--evict-daemonset-pods Evict pods that were created by an extant DaemonSet.
42+
--evict-emptydir-pods Evict pods with local storage, i.e. with emptyDir volumes.
43+
--evict-unreplicated-pods Evict pods that were not created by a replication controller.
5044
5145
Args:
52-
[<node-conditions>] Nodes for which any of these conditions are true will be
53-
cordoned and drained.
46+
[<node-conditions>] Nodes for which any of these conditions are true will be cordoned and drained.
47+
5448
```
5549

5650
## Considerations
@@ -59,9 +53,6 @@ Keep the following in mind before deploying Draino:
5953
* Always run Draino in `--dry-run` mode first to ensure it would drain the nodes
6054
you expect it to. In dry run mode Draino will emit logs, metrics, and events
6155
but will not actually cordon or drain nodes.
62-
* Draino will not evict [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)
63-
or [mirror](https://kubernetes.io/docs/tasks/administer-cluster/static-pod/)
64-
pods. It _will_ evict pods with local storage, and unreplicated pods.
6556
* Draino immediately cordons nodes that match its configured labels and node
6657
conditions, but will wait a configurable amount of time (10 minutes by default)
6758
between draining nodes. i.e. If two nodes begin exhibiting a node condition

cmd/draino/draino.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ func main() {
3838
drainBuffer = app.Flag("drain-buffer", "Minimum time between starting each drain. Nodes are always cordoned immediately.").Default(kubernetes.DefaultDrainBuffer.String()).Duration()
3939
nodeLabels = app.Flag("node-label", "Only nodes with this label will be eligible for cordoning and draining. May be specified multiple times.").PlaceHolder("KEY=VALUE").StringMap()
4040

41+
evictDaemonSetPods = app.Flag("evict-daemonset-pods", "Evict pods that were created by an extant DaemonSet.").Bool()
42+
evictLocalStoragePods = app.Flag("evict-emptydir-pods", "Evict pods with local storage, i.e. with emptyDir volumes.").Bool()
43+
evictUnreplicatedPods = app.Flag("evict-unreplicated-pods", "Evict pods that were not created by a replication controller.").Bool()
44+
4145
conditions = app.Arg("node-conditions", "Nodes for which any of these conditions are true will be cordoned and drained.").Strings()
4246
)
4347
kingpin.MustParse(app.Parse(os.Args[1:]))
@@ -82,11 +86,20 @@ func main() {
8286
cs, err := client.NewForConfig(c)
8387
kingpin.FatalIfError(err, "cannot create Kubernetes client")
8488

89+
pf := []kubernetes.PodFilterFunc{kubernetes.MirrorPodFilter}
90+
switch {
91+
case !*evictLocalStoragePods:
92+
pf = append(pf, kubernetes.LocalStoragePodFilter)
93+
case !*evictUnreplicatedPods:
94+
pf = append(pf, kubernetes.UnreplicatedPodFilter)
95+
case !*evictDaemonSetPods:
96+
pf = append(pf, kubernetes.NewDaemonSetPodFilter(cs))
97+
}
8598
var h cache.ResourceEventHandler = kubernetes.NewDrainingResourceEventHandler(
8699
kubernetes.NewAPICordonDrainer(cs,
87100
kubernetes.MaxGracePeriod(*maxGracePeriod),
88101
kubernetes.EvictionHeadroom(*evictionHeadroom),
89-
kubernetes.WithPodFilter(kubernetes.NewPodFilters(kubernetes.MirrorPodFilter, kubernetes.NewDaemonSetPodFilter(cs)))),
102+
kubernetes.WithPodFilter(kubernetes.NewPodFilters(pf...))),
90103
kubernetes.NewEventRecorder(cs),
91104
kubernetes.WithLogger(log),
92105
kubernetes.WithDrainBuffer(*drainBuffer))

0 commit comments

Comments
 (0)