Skip to content
This repository was archived by the owner on Sep 18, 2020. It is now read-only.

Commit e327c57

Browse files
authored
Merge pull request #164 from dghubble/fix-pod-drain
Fix pod deletion to be compatible with Kubernetes 1.9
2 parents 6d4ceb5 + 77ac24a commit e327c57

File tree

1 file changed

+34
-33
lines changed

1 file changed

+34
-33
lines changed

pkg/drain/drain.go

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import (
77
"k8s.io/apimachinery/pkg/api/errors"
88
v1meta "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"k8s.io/apimachinery/pkg/fields"
10-
"k8s.io/apimachinery/pkg/runtime"
1110
"k8s.io/client-go/kubernetes"
12-
"k8s.io/client-go/kubernetes/scheme"
1311
kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
1412
)
1513

@@ -26,36 +24,19 @@ func GetPodsForDeletion(kc kubernetes.Interface, node string) (pods []v1.Pod, er
2624
return pods, err
2725
}
2826

27+
// Delete pods, even if they are lone pods without a controller. As an
28+
// exception, skip mirror pods and daemonset pods with an existing
29+
// daemonset (since the daemonset owner would recreate them anyway).
2930
for _, pod := range podList.Items {
31+
3032
// skip mirror pods
3133
if _, ok := pod.Annotations[kubelettypes.ConfigMirrorAnnotationKey]; ok {
3234
continue
3335
}
3436

35-
// unlike kubelet we don't care if you have emptyDir volumes or
36-
// are not replicated via some controller. sorry.
37-
38-
// but we do skip daemonset pods, since ds controller will just restart them anyways.
39-
// As an exception, we do delete daemonset pods that have been "orphaned" by their controller.
40-
if creatorRef, ok := pod.Annotations[v1.CreatedByAnnotation]; ok {
41-
// decode ref to find kind
42-
sr := &v1.SerializedReference{}
43-
if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), []byte(creatorRef), sr); err != nil {
44-
// really shouldn't happen but at least complain verbosely if it does
45-
return nil, fmt.Errorf("failed decoding %q annotation on pod %q: %v", v1.CreatedByAnnotation, pod.Name, err)
46-
}
47-
48-
if sr.Reference.Kind == "DaemonSet" {
49-
_, err := getDaemonsetController(kc, sr)
50-
if err == nil {
51-
// it exists, skip it
52-
continue
53-
}
54-
if !errors.IsNotFound(err) {
55-
return nil, fmt.Errorf("failed to get controller of pod %q: %v", pod.Name, err)
56-
}
57-
// else the controller is gone, fall through to delete this orphan
58-
}
37+
// check if pod is a daemonset owner
38+
if _, err = getOwnerDaemonset(kc, pod); err == nil {
39+
continue
5940
}
6041

6142
pods = append(pods, pod)
@@ -64,13 +45,33 @@ func GetPodsForDeletion(kc kubernetes.Interface, node string) (pods []v1.Pod, er
6445
return pods, nil
6546
}
6647

67-
// Pared down version of
68-
// https://github.com/kubernetes/kubernetes/blob/cbbf22a7d2b06a55066b16885a4baaf4ce92d3a4/pkg/kubectl/cmd/drain.go's
69-
// getDaemonsetController().
70-
func getDaemonsetController(kc kubernetes.Interface, sr *v1.SerializedReference) (interface{}, error) {
71-
switch sr.Reference.Kind {
48+
// getOwnerDaemonset returns an existing DaemonSet owner if it exists.
49+
func getOwnerDaemonset(kc kubernetes.Interface, pod v1.Pod) (interface{}, error) {
50+
if len(pod.OwnerReferences) == 0 {
51+
return nil, fmt.Errorf("pod %q has no owner objects", pod.Name)
52+
}
53+
for _, ownerRef := range pod.OwnerReferences {
54+
// skip pod if it is owned by an existing daemonset
55+
if ownerRef.Kind == "DaemonSet" {
56+
ds, err := getDaemonsetController(kc, pod.Namespace, &ownerRef)
57+
if err == nil {
58+
// daemonset owner exists
59+
return ds, nil
60+
}
61+
if !errors.IsNotFound(err) {
62+
return nil, fmt.Errorf("failed to get controller of pod %q: %v", pod.Name, err)
63+
}
64+
}
65+
}
66+
// pod may have owners, but they don't exist or aren't daemonsets
67+
return nil, fmt.Errorf("pod %q has no existing damonset owner", pod.Name)
68+
}
69+
70+
// Stripped down version of https://github.com/kubernetes/kubernetes/blob/1bc56825a2dff06f29663a024ee339c25e6e6280/pkg/kubectl/cmd/drain.go#L272
71+
func getDaemonsetController(kc kubernetes.Interface, namespace string, controllerRef *v1meta.OwnerReference) (interface{}, error) {
72+
switch controllerRef.Kind {
7273
case "DaemonSet":
73-
return kc.ExtensionsV1beta1().DaemonSets(sr.Reference.Namespace).Get(sr.Reference.Name, v1meta.GetOptions{})
74+
return kc.ExtensionsV1beta1().DaemonSets(namespace).Get(controllerRef.Name, v1meta.GetOptions{})
7475
}
75-
return nil, fmt.Errorf("unknown controller kind %q", sr.Reference.Kind)
76+
return nil, fmt.Errorf("Unknown controller kind %q", controllerRef.Kind)
7677
}

0 commit comments

Comments
 (0)