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

Commit 77ac24a

Browse files
committed
Fix pod deletion to be compatible with Kubernetes 1.9
* Check each pod's OwnerReferences to determine whether it is owned by an existing Daemonset. If so, exclude it from deletion as the pod would just be recreated by the Daemonset controller * Drop usage of CreatedByAnnotation to deserialize the owner object of a pod when listing pods to delete during agent drains
1 parent 66f71a4 commit 77ac24a

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)