From 889d45d3fb55b847b1c7ed9286d1ea83d446178c Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Mon, 8 Nov 2021 17:49:52 -0500 Subject: [PATCH] [kubelet] Reject pods with OS field mismatch Once kubernetes#104613 and kubernetes#104693 merge, we'll have OS field in pod spec. Kubelet should start rejecting pods where pod.Spec.OS and node's OS(using runtime.GOOS) won't match --- pkg/kubelet/lifecycle/predicate.go | 19 +++++++++++++++ pkg/kubelet/lifecycle/predicate_test.go | 32 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/pkg/kubelet/lifecycle/predicate.go b/pkg/kubelet/lifecycle/predicate.go index 16fb432b8d08..cee40ed59a3f 100644 --- a/pkg/kubelet/lifecycle/predicate.go +++ b/pkg/kubelet/lifecycle/predicate.go @@ -161,6 +161,14 @@ func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult Message: "Failed to admit pod as the `kubernetes.io/os` label doesn't match node label", } } + // By this time, node labels should have been synced, this helps in identifying the pod with the usage. + if rejectPodAdmissionBasedOnOSField(admitPod) { + return PodAdmitResult{ + Admit: false, + Reason: "PodOSNotSupported", + Message: "Failed to admit pod as the OS field doesn't match node OS", + } + } return PodAdmitResult{ Admit: true, } @@ -187,6 +195,17 @@ func rejectPodAdmissionBasedOnOSSelector(pod *v1.Pod, node *v1.Node) bool { return false } +// rejectPodAdmissionBasedOnOSField rejects pods if their OS field doesn't match runtime.GOOS. +// TODO: Relax this restriction when we start supporting LCOW in kubernetes where podOS may not match +// node's OS. +func rejectPodAdmissionBasedOnOSField(pod *v1.Pod) bool { + if pod.Spec.OS == nil { + return false + } + // If the pod OS doesn't match runtime.GOOS return false + return string(pod.Spec.OS.Name) != runtime.GOOS +} + func removeMissingExtendedResources(pod *v1.Pod, nodeInfo *schedulerframework.NodeInfo) *v1.Pod { podCopy := pod.DeepCopy() for i, c := range pod.Spec.Containers { diff --git a/pkg/kubelet/lifecycle/predicate_test.go b/pkg/kubelet/lifecycle/predicate_test.go index bd4d33379865..8e8f82999f23 100644 --- a/pkg/kubelet/lifecycle/predicate_test.go +++ b/pkg/kubelet/lifecycle/predicate_test.go @@ -322,3 +322,35 @@ func TestRejectPodAdmissionBasedOnOSSelector(t *testing.T) { }) } } + +func TestRejectPodAdmissionBasedOnOSField(t *testing.T) { + tests := []struct { + name string + pod *v1.Pod + expectRejection bool + }{ + { + name: "OS field match", + pod: &v1.Pod{Spec: v1.PodSpec{OS: &v1.PodOS{Name: v1.OSName(goruntime.GOOS)}}}, + expectRejection: false, + }, + { + name: "OS field mismatch", + pod: &v1.Pod{Spec: v1.PodSpec{OS: &v1.PodOS{Name: "dummyOS"}}}, + expectRejection: true, + }, + { + name: "no OS field", + pod: &v1.Pod{Spec: v1.PodSpec{}}, + expectRejection: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualResult := rejectPodAdmissionBasedOnOSField(test.pod) + if test.expectRejection != actualResult { + t.Errorf("unexpected result, expected %v but got %v", test.expectRejection, actualResult) + } + }) + } +}