mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-28 06:29:29 +01:00
Owner ref switch
Signed-off-by: ravisantoshgudimetla <ravisantoshgudimetla@gmail.com>
This commit is contained in:
@@ -19,7 +19,6 @@ package pod
|
|||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1/helper/qos"
|
"k8s.io/kubernetes/pkg/api/v1/helper/qos"
|
||||||
@@ -54,11 +53,8 @@ func IsLatencySensitivePod(pod *v1.Pod) bool {
|
|||||||
|
|
||||||
// IsEvictable checks if a pod is evictable or not.
|
// IsEvictable checks if a pod is evictable or not.
|
||||||
func IsEvictable(pod *v1.Pod) bool {
|
func IsEvictable(pod *v1.Pod) bool {
|
||||||
sr, err := CreatorRef(pod)
|
ownerRefList := OwnerRef(pod)
|
||||||
if err != nil {
|
if IsMirrorPod(pod) || IsPodWithLocalStorage(pod) || len(ownerRefList) == 0 || IsDaemonsetPod(ownerRefList) || IsCriticalPod(pod) {
|
||||||
sr = nil
|
|
||||||
}
|
|
||||||
if IsMirrorPod(pod) || IsPodWithLocalStorage(pod) || sr == nil || IsDaemonsetPod(sr) || IsCriticalPod(pod) || IsLatencySensitivePod(pod) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -116,9 +112,11 @@ func IsGuaranteedPod(pod *v1.Pod) bool {
|
|||||||
return qos.GetPodQOS(pod) == v1.PodQOSGuaranteed
|
return qos.GetPodQOS(pod) == v1.PodQOSGuaranteed
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsDaemonsetPod(sr *v1.SerializedReference) bool {
|
func IsDaemonsetPod(ownerRefList []metav1.OwnerReference) bool {
|
||||||
if sr != nil {
|
for _, ownerRef := range ownerRefList {
|
||||||
return sr.Reference.Kind == "DaemonSet"
|
if ownerRef.Kind == "DaemonSet" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -139,15 +137,7 @@ func IsPodWithLocalStorage(pod *v1.Pod) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatorRef returns the kind of the creator reference of the pod.
|
// OwnerRef returns the ownerRefList for the pod.
|
||||||
func CreatorRef(pod *v1.Pod) (*v1.SerializedReference, error) {
|
func OwnerRef(pod *v1.Pod) []metav1.OwnerReference {
|
||||||
creatorRef, found := pod.ObjectMeta.Annotations[v1.CreatedByAnnotation]
|
return pod.ObjectMeta.GetOwnerReferences()
|
||||||
if !found {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
var sr v1.SerializedReference
|
|
||||||
if err := runtime.DecodeInto(api.Codecs.UniversalDecoder(), []byte(creatorRef), &sr); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &sr, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,14 +35,16 @@ func TestPodTypes(t *testing.T) {
|
|||||||
p5 := test.BuildTestPod("p5", 400, 0, n1.Name)
|
p5 := test.BuildTestPod("p5", 400, 0, n1.Name)
|
||||||
p6 := test.BuildTestPod("p6", 400, 0, n1.Name)
|
p6 := test.BuildTestPod("p6", 400, 0, n1.Name)
|
||||||
p6.Spec.Containers[0].Resources.Requests[v1.ResourceNvidiaGPU] = *resource.NewMilliQuantity(3, resource.DecimalSI)
|
p6.Spec.Containers[0].Resources.Requests[v1.ResourceNvidiaGPU] = *resource.NewMilliQuantity(3, resource.DecimalSI)
|
||||||
p6.Annotations = test.GetNormalPodAnnotation()
|
|
||||||
|
|
||||||
p1.Annotations = test.GetReplicaSetAnnotation()
|
p6.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
|
||||||
|
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
// The following 4 pods won't get evicted.
|
// The following 4 pods won't get evicted.
|
||||||
// A daemonset.
|
// A daemonset.
|
||||||
p2.Annotations = test.GetDaemonSetAnnotation()
|
//p2.Annotations = test.GetDaemonSetAnnotation()
|
||||||
|
p2.ObjectMeta.OwnerReferences = test.GetDaemonSetOwnerRefList()
|
||||||
// A pod with local storage.
|
// A pod with local storage.
|
||||||
p3.Annotations = test.GetNormalPodAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p3.Spec.Volumes = []v1.Volume{
|
p3.Spec.Volumes = []v1.Volume{
|
||||||
{
|
{
|
||||||
Name: "sample",
|
Name: "sample",
|
||||||
@@ -67,12 +69,12 @@ func TestPodTypes(t *testing.T) {
|
|||||||
if !IsPodWithLocalStorage(p3) {
|
if !IsPodWithLocalStorage(p3) {
|
||||||
t.Errorf("Expected p3 to be a pod with local storage.")
|
t.Errorf("Expected p3 to be a pod with local storage.")
|
||||||
}
|
}
|
||||||
sr, _ := CreatorRef(p2)
|
ownerRefList := OwnerRef(p2)
|
||||||
if !IsDaemonsetPod(sr) {
|
if !IsDaemonsetPod(ownerRefList) {
|
||||||
t.Errorf("Expected p2 to be a daemonset pod.")
|
t.Errorf("Expected p2 to be a daemonset pod.")
|
||||||
}
|
}
|
||||||
sr, _ = CreatorRef(p1)
|
ownerRefList = OwnerRef(p1)
|
||||||
if IsDaemonsetPod(sr) || IsPodWithLocalStorage(p1) || IsCriticalPod(p1) || IsMirrorPod(p1) {
|
if IsDaemonsetPod(ownerRefList) || IsPodWithLocalStorage(p1) || IsCriticalPod(p1) || IsMirrorPod(p1) {
|
||||||
t.Errorf("Expected p1 to be a normal pod.")
|
t.Errorf("Expected p1 to be a normal pod.")
|
||||||
}
|
}
|
||||||
if !IsLatencySensitivePod(p6) {
|
if !IsLatencySensitivePod(p6) {
|
||||||
|
|||||||
@@ -83,9 +83,12 @@ func FindDuplicatePods(pods []*v1.Pod) DuplicatePodsMap {
|
|||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
// Ignoring the error here as in the ListDuplicatePodsOnNode function we call ListEvictablePodsOnNode
|
// Ignoring the error here as in the ListDuplicatePodsOnNode function we call ListEvictablePodsOnNode
|
||||||
// which checks for error.
|
// which checks for error.
|
||||||
sr, _ := podutil.CreatorRef(pod)
|
ownerRefList := podutil.OwnerRef(pod)
|
||||||
s := strings.Join([]string{sr.Reference.Kind, sr.Reference.Namespace, sr.Reference.Name}, "/")
|
for _, ownerRef := range ownerRefList {
|
||||||
dpm[s] = append(dpm[s], pod)
|
// ownerRef doesn't need namespace since the assumption is owner needs to be in the same namespace.
|
||||||
|
s := strings.Join([]string{ownerRef.Kind, ownerRef.Name}, "/")
|
||||||
|
dpm[s] = append(dpm[s], pod)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return dpm
|
return dpm
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,15 +39,15 @@ func TestFindDuplicatePods(t *testing.T) {
|
|||||||
p7 := test.BuildTestPod("p7", 100, 0, node.Name)
|
p7 := test.BuildTestPod("p7", 100, 0, node.Name)
|
||||||
|
|
||||||
// All the following pods expect for one will be evicted.
|
// All the following pods expect for one will be evicted.
|
||||||
p1.Annotations = test.GetReplicaSetAnnotation()
|
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p2.Annotations = test.GetReplicaSetAnnotation()
|
p2.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p3.Annotations = test.GetReplicaSetAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
|
|
||||||
// The following 4 pods won't get evicted.
|
// The following 4 pods won't get evicted.
|
||||||
// A daemonset.
|
// A daemonset.
|
||||||
p4.Annotations = test.GetDaemonSetAnnotation()
|
p4.ObjectMeta.OwnerReferences = test.GetDaemonSetOwnerRefList()
|
||||||
// A pod with local storage.
|
// A pod with local storage.
|
||||||
p5.Annotations = test.GetNormalPodAnnotation()
|
p5.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p5.Spec.Volumes = []v1.Volume{
|
p5.Spec.Volumes = []v1.Volume{
|
||||||
{
|
{
|
||||||
Name: "sample",
|
Name: "sample",
|
||||||
|
|||||||
@@ -55,16 +55,16 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
p7 := test.BuildTestPod("p7", 400, 0, n1.Name)
|
p7 := test.BuildTestPod("p7", 400, 0, n1.Name)
|
||||||
p8 := test.BuildTestPod("p8", 400, 0, n1.Name)
|
p8 := test.BuildTestPod("p8", 400, 0, n1.Name)
|
||||||
|
|
||||||
p1.Annotations = test.GetReplicaSetAnnotation()
|
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p2.Annotations = test.GetReplicaSetAnnotation()
|
p2.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p3.Annotations = test.GetReplicaSetAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p4.Annotations = test.GetReplicaSetAnnotation()
|
p4.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p5.Annotations = test.GetReplicaSetAnnotation()
|
p5.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
// The following 4 pods won't get evicted.
|
// The following 4 pods won't get evicted.
|
||||||
// A daemonset.
|
// A daemonset.
|
||||||
p6.Annotations = test.GetDaemonSetAnnotation()
|
p6.ObjectMeta.OwnerReferences = test.GetDaemonSetOwnerRefList()
|
||||||
// A pod with local storage.
|
// A pod with local storage.
|
||||||
p7.Annotations = test.GetNormalPodAnnotation()
|
p7.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p7.Spec.Volumes = []v1.Volume{
|
p7.Spec.Volumes = []v1.Volume{
|
||||||
{
|
{
|
||||||
Name: "sample",
|
Name: "sample",
|
||||||
@@ -81,7 +81,7 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
p8.Namespace = "kube-system"
|
p8.Namespace = "kube-system"
|
||||||
p8.Annotations = test.GetCriticalPodAnnotation()
|
p8.Annotations = test.GetCriticalPodAnnotation()
|
||||||
p9 := test.BuildTestPod("p9", 400, 0, n1.Name)
|
p9 := test.BuildTestPod("p9", 400, 0, n1.Name)
|
||||||
p9.Annotations = test.GetReplicaSetAnnotation()
|
p9.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
list := action.(core.ListAction)
|
list := action.(core.ListAction)
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ func TestPodAntiAffinity(t *testing.T) {
|
|||||||
p2 := test.BuildTestPod("p2", 100, 0, node.Name)
|
p2 := test.BuildTestPod("p2", 100, 0, node.Name)
|
||||||
p3 := test.BuildTestPod("p3", 100, 0, node.Name)
|
p3 := test.BuildTestPod("p3", 100, 0, node.Name)
|
||||||
p3.Labels = map[string]string{"foo": "bar"}
|
p3.Labels = map[string]string{"foo": "bar"}
|
||||||
p1.Annotations = test.GetNormalPodAnnotation()
|
p1.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p2.Annotations = test.GetNormalPodAnnotation()
|
p2.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p3.Annotations = test.GetNormalPodAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p1.Spec.Affinity = &v1.Affinity{
|
p1.Spec.Affinity = &v1.Affinity{
|
||||||
PodAntiAffinity: &v1.PodAntiAffinity{
|
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||||
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
||||||
|
|||||||
@@ -62,25 +62,25 @@ func GetMirrorPodAnnotation() map[string]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNormalPodAnnotation returns the annotation needed for a pod.
|
// GetNormalPodOwnerRefList returns the ownerRef needed for a pod.
|
||||||
func GetNormalPodAnnotation() map[string]string {
|
func GetNormalPodOwnerRefList() []metav1.OwnerReference {
|
||||||
return map[string]string{
|
ownerRefList := make([]metav1.OwnerReference, 0)
|
||||||
"kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Pod\"}}",
|
ownerRefList = append(ownerRefList, metav1.OwnerReference{Kind: "Pod", APIVersion: "v1"})
|
||||||
}
|
return ownerRefList
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReplicaSetAnnotation returns the annotation needed for replicaset pod.
|
// GetReplicaSetOwnerRefList returns the ownerRef needed for replicaset pod.
|
||||||
func GetReplicaSetAnnotation() map[string]string {
|
func GetReplicaSetOwnerRefList() []metav1.OwnerReference {
|
||||||
return map[string]string{
|
ownerRefList := make([]metav1.OwnerReference, 0)
|
||||||
"kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"ReplicaSet\"}}",
|
ownerRefList = append(ownerRefList, metav1.OwnerReference{Kind: "ReplicaSet", APIVersion: "v1"})
|
||||||
}
|
return ownerRefList
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDaemonSetAnnotation returns the annotation needed for daemonset pod.
|
// GetDaemonSetOwnerRefList returns the ownerRef needed for daemonset pod.
|
||||||
func GetDaemonSetAnnotation() map[string]string {
|
func GetDaemonSetOwnerRefList() []metav1.OwnerReference {
|
||||||
return map[string]string{
|
ownerRefList := make([]metav1.OwnerReference, 0)
|
||||||
"kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"DaemonSet\"}}",
|
ownerRefList = append(ownerRefList, metav1.OwnerReference{Kind: "DaemonSet", APIVersion: "v1"})
|
||||||
}
|
return ownerRefList
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCriticalPodAnnotation returns the annotation needed for critical pod.
|
// GetCriticalPodAnnotation returns the annotation needed for critical pod.
|
||||||
|
|||||||
Reference in New Issue
Block a user