/
delete_pods.go
160 lines (123 loc) · 3.69 KB
/
delete_pods.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
import (
"context"
"fmt"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
"k8s.io/api/policy/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/types"
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sort"
"strconv"
"sync"
"time"
//v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
)
func deletePods(c client.Client, c2 v1.CoreV1Interface, log logr.Logger, node corev1.Node) error {
prioritizedPods := map[int][]corev1.Pod{}
var pods corev1.PodList
if err := c.List(context.Background(), &pods, &client.ListOptions{
FieldSelector: fields.OneTermEqualSelector("spec.nodeName", node.Name),
}); err != nil {
return err
}
if len(pods.Items) == 0 {
log.Info("No pods scheduled on this node")
return nil
}
for _, pod := range pods.Items {
var pri int
priStr, ok := pod.Annotations[PodAnnotationKeyPodDeletionPriority]
if ok {
var err error
pri, err = strconv.Atoi(priStr)
if err != nil {
return err
}
} else {
log.V(1).Info(fmt.Sprintf("Skipping pod without %q annotation", PodAnnotationKeyPodDeletionPriority), "pod", types.NamespacedName{
Namespace: pod.Namespace,
Name: pod.Name,
})
continue
}
if _, ok := prioritizedPods[pri]; !ok {
prioritizedPods[pri] = []corev1.Pod{}
}
prioritizedPods[pri] = append(prioritizedPods[pri], pod)
}
decreasingPriorities := []int{}
for pri := range prioritizedPods {
decreasingPriorities = append(decreasingPriorities, pri)
}
sort.Slice(decreasingPriorities, func(i, j int) bool {
return i > j
})
for _, pri := range decreasingPriorities {
pods := prioritizedPods[pri]
var wg sync.WaitGroup
for i := range pods {
po := pods[i]
mylog := log.WithValues("priority", pri, "pod_namespace", po.Namespace, "pod_name", po.Name)
if po.DeletionTimestamp == nil {
mylog.Info("deletionTimestamp not set. Deleting pod")
var evict bool
if po.Annotations == nil || po.Annotations[PodAnnotationDisableEviction] != "true" {
evict = true
}
if evict {
mylog.Info("evicting pod due to that the disable-eviction annotation is set to true")
eviction := &v1beta1.Eviction{
ObjectMeta: metav1.ObjectMeta{
Namespace: po.Namespace,
Name: po.Name,
},
}
GracePeriod := 30 * time.Second
gracePeriod := &GracePeriod
if gracePeriod != nil {
gracePeriodSeconds := int64(gracePeriod.Seconds())
eviction.DeleteOptions = &metav1.DeleteOptions{
GracePeriodSeconds: &gracePeriodSeconds,
}
}
if err := c2.Pods(po.Namespace).Evict(eviction); err != nil {
mylog.Error(err, "evicting pod")
if !apierrors.IsNotFound(err) {
return err
}
}
} else {
mylog.Info("deleting pod without taking PDB into account due to that the disable-eviction annotation is not set")
if err := c.Delete(context.Background(), &po); err != nil {
return err
}
}
} else {
mylog.Info("deletionTimestamp already set. Skipped deleting pod")
}
wg.Add(1)
go func() {
defer wg.Done()
var latestPo corev1.Pod
for {
mylog.Info("Waiting for pod to disappear")
if err := c.Get(context.Background(), types.NamespacedName{Namespace: po.Namespace, Name: po.Name}, &latestPo); apierrors.IsNotFound(err) {
mylog.Info("Waiting for pod to disappear... Done")
break
}
time.Sleep(3 * time.Second)
}
}()
}
wg.Wait()
}
return nil
}
func DeletePods(c client.Client, c2 v1.CoreV1Interface, log logr.Logger, node corev1.Node) error {
return deletePods(c, c2, log, node)
}