[kubelet][podadmission]: Validate and reject pods with mismatching labels

This commit is contained in:
ravisantoshgudimetla 2021-10-26 10:43:44 -04:00
parent 02c1bac0b6
commit 21c5c2ec5c
2 changed files with 84 additions and 0 deletions

View File

@ -18,6 +18,7 @@ package lifecycle
import (
"fmt"
"runtime"
v1 "k8s.io/api/core/v1"
"k8s.io/apiserver/pkg/util/feature"
@ -153,11 +154,39 @@ func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult
Message: message,
}
}
if rejectPodAdmissionBasedOnOSSelector(admitPod, node) {
return PodAdmitResult{
Admit: false,
Reason: "PodOSSelectorNodeLabelDoesNotMatch",
Message: "Failed to admit pod as the `kubernetes.io/os` label doesn't match node label",
}
}
return PodAdmitResult{
Admit: true,
}
}
// rejectPodAdmissionBasedOnOSSelector rejects pod if it's nodeSelector doesn't match
// We expect the kubelet status reconcile which happens every 10sec to update the node labels if there is a mismatch.
func rejectPodAdmissionBasedOnOSSelector(pod *v1.Pod, node *v1.Node) bool {
labels := node.Labels
osName, osLabelExists := labels[v1.LabelOSStable]
if !osLabelExists || osName != runtime.GOOS {
if len(labels) == 0 {
labels = make(map[string]string)
}
labels[v1.LabelOSStable] = runtime.GOOS
}
podLabelSelector, podOSLabelExists := pod.Labels[v1.LabelOSStable]
if !podOSLabelExists {
// If the labelselector didn't exist, let's keep the current behavior as is
return false
} else if podOSLabelExists && podLabelSelector != labels[v1.LabelOSStable] {
return true
}
return false
}
func removeMissingExtendedResources(pod *v1.Pod, nodeInfo *schedulerframework.NodeInfo) *v1.Pod {
podCopy := pod.DeepCopy()
for i, c := range pod.Spec.Containers {

View File

@ -18,6 +18,7 @@ package lifecycle
import (
"reflect"
goruntime "runtime"
"testing"
v1 "k8s.io/api/core/v1"
@ -267,3 +268,57 @@ func TestGeneralPredicates(t *testing.T) {
})
}
}
func TestRejectPodAdmissionBasedOnOSSelector(t *testing.T) {
tests := []struct {
name string
pod *v1.Pod
node *v1.Node
expectRejection bool
}{
{
name: "OS label match",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: goruntime.GOOS}}},
node: &v1.Node{Spec: v1.NodeSpec{}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: goruntime.GOOS}}},
expectRejection: false,
},
{
name: "dummyOS label, but the underlying OS matches",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: goruntime.GOOS}}},
node: &v1.Node{Spec: v1.NodeSpec{}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
expectRejection: false,
},
{
name: "dummyOS label, but the underlying OS doesn't match",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
node: &v1.Node{Spec: v1.NodeSpec{}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
expectRejection: true,
},
{
name: "dummyOS label, but the underlying OS doesn't match",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
node: &v1.Node{Spec: v1.NodeSpec{}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
expectRejection: true,
},
{
name: "OS field mismatch, OS label on node object would be reset to correct value",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
node: &v1.Node{Spec: v1.NodeSpec{}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
expectRejection: true,
},
{
name: "No label selector on the pod, should be admitted",
pod: &v1.Pod{},
node: &v1.Node{Spec: v1.NodeSpec{}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{v1.LabelOSStable: "dummyOS"}}},
expectRejection: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualResult := rejectPodAdmissionBasedOnOSSelector(test.pod, test.node)
if test.expectRejection != actualResult {
t.Errorf("unexpected result, expected %v but got %v", test.expectRejection, actualResult)
}
})
}
}