Skip to content

Commit

Permalink
Merge pull request #50180 from k82cn/k8s_42001-2
Browse files Browse the repository at this point in the history
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.
```
  • Loading branch information
Kubernetes Submit Queue committed Aug 14, 2017
2 parents bc1a58a + 03e4394 commit f8eed14
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
5 changes: 5 additions & 0 deletions plugin/pkg/admission/podtolerationrestriction/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ go_test(
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/util/tolerations: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/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)

Expand All @@ -31,6 +34,7 @@ go_library(
],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/helper/qos:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
Expand All @@ -41,6 +45,7 @@ go_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/validation:go_default_library",
"//plugin/pkg/scheduler/algorithm:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
Expand Down
12 changes: 12 additions & 0 deletions plugin/pkg/admission/podtolerationrestriction/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
qoshelper "k8s.io/kubernetes/pkg/api/helper/qos"
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/util/tolerations"
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
)

// Register registers a plugin
Expand Down Expand Up @@ -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
return nil

Expand Down
85 changes: 84 additions & 1 deletion plugin/pkg/admission/podtolerationrestriction/admission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ import (
"testing"
"time"

"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/util/tolerations"
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
Expand All @@ -50,11 +53,56 @@ func TestPodAdmission(t *testing.T) {
defer close(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"},
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 {
pod *api.Pod
defaultClusterTolerations []api.Toleration
namespaceTolerations []api.Toleration
whitelist []api.Toleration
Expand All @@ -65,6 +113,7 @@ func TestPodAdmission(t *testing.T) {
testName string
}{
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
namespaceTolerations: []api.Toleration{},
podTolerations: []api.Toleration{},
Expand All @@ -73,6 +122,7 @@ func TestPodAdmission(t *testing.T) {
testName: "default cluster tolerations with empty pod tolerations",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
namespaceTolerations: []api.Toleration{},
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
Expand All @@ -81,6 +131,7 @@ func TestPodAdmission(t *testing.T) {
testName: "default cluster tolerations with pod tolerations specified",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{},
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}},
Expand All @@ -89,6 +140,7 @@ func TestPodAdmission(t *testing.T) {
testName: "namespace tolerations",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{},
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
podTolerations: []api.Toleration{},
Expand All @@ -97,20 +149,23 @@ func TestPodAdmission(t *testing.T) {
testName: "no pod tolerations",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{},
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}},
admit: false,
testName: "conflicting pod and namespace tolerations",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue2", Effect: "NoSchedule", TolerationSeconds: nil}},
namespaceTolerations: []api.Toleration{},
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
admit: false,
testName: "conflicting pod and default cluster tolerations",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{},
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}},
Expand All @@ -120,13 +175,40 @@ func TestPodAdmission(t *testing.T) {
testName: "merged pod tolerations satisfy whitelist",
},
{
pod: bestEffortPod,
defaultClusterTolerations: []api.Toleration{},
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}},
podTolerations: []api.Toleration{},
admit: false,
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 {
if len(test.namespaceTolerations) > 0 {
Expand All @@ -148,6 +230,7 @@ func TestPodAdmission(t *testing.T) {
informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace)

handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist}
pod := test.pod
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))
Expand Down

0 comments on commit f8eed14

Please sign in to comment.