mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 02:09:56 +00:00
Merge pull request #50180 from k82cn/k8s_42001-2
Automatic merge from submit-queue Task 3: Add MemoryPressure toleration for no BestEffort pod. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: part of #42001 **Release note**: ```release-note After 1.8, admission controller will add 'MemoryPressure' toleration to Guaranteed and Burstable pods. ```
This commit is contained in:
commit
f8eed144f5
@ -18,8 +18,11 @@ go_test(
|
|||||||
"//pkg/kubeapiserver/admission:go_default_library",
|
"//pkg/kubeapiserver/admission:go_default_library",
|
||||||
"//pkg/util/tolerations:go_default_library",
|
"//pkg/util/tolerations:go_default_library",
|
||||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||||
|
"//plugin/pkg/scheduler/algorithm:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||||
|
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,6 +34,7 @@ go_library(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
|
"//pkg/api/helper/qos:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||||
@ -41,6 +45,7 @@ go_library(
|
|||||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:go_default_library",
|
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:go_default_library",
|
||||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library",
|
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library",
|
||||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation:go_default_library",
|
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation:go_default_library",
|
||||||
|
"//plugin/pkg/scheduler/algorithm:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
qoshelper "k8s.io/kubernetes/pkg/api/helper/qos"
|
||||||
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
|
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||||
@ -35,6 +36,7 @@ import (
|
|||||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||||
"k8s.io/kubernetes/pkg/util/tolerations"
|
"k8s.io/kubernetes/pkg/util/tolerations"
|
||||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register registers a plugin
|
// Register registers a plugin
|
||||||
@ -162,6 +164,16 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if qoshelper.GetPodQOS(pod) != api.PodQOSBestEffort {
|
||||||
|
finalTolerations = tolerations.MergeTolerations(finalTolerations, []api.Toleration{
|
||||||
|
{
|
||||||
|
Key: algorithm.TaintNodeMemoryPressure,
|
||||||
|
Operator: api.TolerationOpExists,
|
||||||
|
Effect: api.TaintEffectNoSchedule,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pod.Spec.Tolerations = finalTolerations
|
pod.Spec.Tolerations = finalTolerations
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -21,8 +21,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||||
@ -30,6 +32,7 @@ import (
|
|||||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||||
"k8s.io/kubernetes/pkg/util/tolerations"
|
"k8s.io/kubernetes/pkg/util/tolerations"
|
||||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestPodAdmission verifies various scenarios involving pod/namespace tolerations
|
// TestPodAdmission verifies various scenarios involving pod/namespace tolerations
|
||||||
@ -50,11 +53,56 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
defer close(stopCh)
|
defer close(stopCh)
|
||||||
informerFactory.Start(stopCh)
|
informerFactory.Start(stopCh)
|
||||||
|
|
||||||
pod := &api.Pod{
|
CPU1000m := resource.MustParse("1000m")
|
||||||
|
CPU500m := resource.MustParse("500m")
|
||||||
|
|
||||||
|
burstablePod := &api.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"},
|
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "test",
|
||||||
|
Resources: api.ResourceRequirements{
|
||||||
|
Limits: api.ResourceList{api.ResourceCPU: CPU1000m},
|
||||||
|
Requests: api.ResourceList{api.ResourceCPU: CPU500m},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
guaranteedPod := &api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "test",
|
||||||
|
Resources: api.ResourceRequirements{
|
||||||
|
Limits: api.ResourceList{api.ResourceCPU: CPU1000m},
|
||||||
|
Requests: api.ResourceList{api.ResourceCPU: CPU1000m},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
bestEffortPod := &api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := utilfeature.DefaultFeatureGate.Set("TaintNodesByCondition=true"); err != nil {
|
||||||
|
t.Errorf("Failed to enable TaintByCondition feature: %v.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
pod *api.Pod
|
||||||
defaultClusterTolerations []api.Toleration
|
defaultClusterTolerations []api.Toleration
|
||||||
namespaceTolerations []api.Toleration
|
namespaceTolerations []api.Toleration
|
||||||
whitelist []api.Toleration
|
whitelist []api.Toleration
|
||||||
@ -65,6 +113,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName string
|
testName string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
namespaceTolerations: []api.Toleration{},
|
namespaceTolerations: []api.Toleration{},
|
||||||
podTolerations: []api.Toleration{},
|
podTolerations: []api.Toleration{},
|
||||||
@ -73,6 +122,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "default cluster tolerations with empty pod tolerations",
|
testName: "default cluster tolerations with empty pod tolerations",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
namespaceTolerations: []api.Toleration{},
|
namespaceTolerations: []api.Toleration{},
|
||||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
@ -81,6 +131,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "default cluster tolerations with pod tolerations specified",
|
testName: "default cluster tolerations with pod tolerations specified",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{},
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
@ -89,6 +140,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "namespace tolerations",
|
testName: "namespace tolerations",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{},
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
podTolerations: []api.Toleration{},
|
podTolerations: []api.Toleration{},
|
||||||
@ -97,6 +149,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "no pod tolerations",
|
testName: "no pod tolerations",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{},
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
@ -104,6 +157,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "conflicting pod and namespace tolerations",
|
testName: "conflicting pod and namespace tolerations",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue2", Effect: "NoSchedule", TolerationSeconds: nil}},
|
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue2", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
namespaceTolerations: []api.Toleration{},
|
namespaceTolerations: []api.Toleration{},
|
||||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
@ -111,6 +165,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "conflicting pod and default cluster tolerations",
|
testName: "conflicting pod and default cluster tolerations",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{},
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
@ -120,6 +175,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
testName: "merged pod tolerations satisfy whitelist",
|
testName: "merged pod tolerations satisfy whitelist",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
pod: bestEffortPod,
|
||||||
defaultClusterTolerations: []api.Toleration{},
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
@ -127,6 +183,32 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
admit: false,
|
admit: false,
|
||||||
testName: "merged pod tolerations conflict with the whitelist",
|
testName: "merged pod tolerations conflict with the whitelist",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
pod: burstablePod,
|
||||||
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
|
whitelist: []api.Toleration{},
|
||||||
|
podTolerations: []api.Toleration{},
|
||||||
|
mergedTolerations: []api.Toleration{
|
||||||
|
{Key: algorithm.TaintNodeMemoryPressure, Operator: api.TolerationOpExists, Effect: api.TaintEffectNoSchedule, TolerationSeconds: nil},
|
||||||
|
{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil},
|
||||||
|
},
|
||||||
|
admit: true,
|
||||||
|
testName: "added memoryPressure/DiskPressure for Burstable pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pod: guaranteedPod,
|
||||||
|
defaultClusterTolerations: []api.Toleration{},
|
||||||
|
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||||
|
whitelist: []api.Toleration{},
|
||||||
|
podTolerations: []api.Toleration{},
|
||||||
|
mergedTolerations: []api.Toleration{
|
||||||
|
{Key: algorithm.TaintNodeMemoryPressure, Operator: api.TolerationOpExists, Effect: api.TaintEffectNoSchedule, TolerationSeconds: nil},
|
||||||
|
{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil},
|
||||||
|
},
|
||||||
|
admit: true,
|
||||||
|
testName: "added memoryPressure/DiskPressure for Guaranteed pod",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if len(test.namespaceTolerations) > 0 {
|
if len(test.namespaceTolerations) > 0 {
|
||||||
@ -148,6 +230,7 @@ func TestPodAdmission(t *testing.T) {
|
|||||||
informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace)
|
informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace)
|
||||||
|
|
||||||
handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist}
|
handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist}
|
||||||
|
pod := test.pod
|
||||||
pod.Spec.Tolerations = test.podTolerations
|
pod.Spec.Tolerations = test.podTolerations
|
||||||
|
|
||||||
err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||||
|
Loading…
Reference in New Issue
Block a user