k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/plugin/pkg/admission/defaulttolerationseconds/admission.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package defaulttolerationseconds 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "io" 24 25 v1 "k8s.io/api/core/v1" 26 "k8s.io/apimachinery/pkg/api/errors" 27 "k8s.io/apiserver/pkg/admission" 28 api "k8s.io/kubernetes/pkg/apis/core" 29 ) 30 31 // PluginName indicates name of admission plugin. 32 const PluginName = "DefaultTolerationSeconds" 33 34 var ( 35 defaultNotReadyTolerationSeconds = flag.Int64("default-not-ready-toleration-seconds", 300, 36 "Indicates the tolerationSeconds of the toleration for notReady:NoExecute"+ 37 " that is added by default to every pod that does not already have such a toleration.") 38 39 defaultUnreachableTolerationSeconds = flag.Int64("default-unreachable-toleration-seconds", 300, 40 "Indicates the tolerationSeconds of the toleration for unreachable:NoExecute"+ 41 " that is added by default to every pod that does not already have such a toleration.") 42 43 notReadyToleration = api.Toleration{ 44 Key: v1.TaintNodeNotReady, 45 Operator: api.TolerationOpExists, 46 Effect: api.TaintEffectNoExecute, 47 TolerationSeconds: defaultNotReadyTolerationSeconds, 48 } 49 50 unreachableToleration = api.Toleration{ 51 Key: v1.TaintNodeUnreachable, 52 Operator: api.TolerationOpExists, 53 Effect: api.TaintEffectNoExecute, 54 TolerationSeconds: defaultUnreachableTolerationSeconds, 55 } 56 ) 57 58 // Register registers a plugin 59 func Register(plugins *admission.Plugins) { 60 plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { 61 return NewDefaultTolerationSeconds(), nil 62 }) 63 } 64 65 // Plugin contains the client used by the admission controller 66 // It will add default tolerations for every pod 67 // that tolerate taints `notReady:NoExecute` and `unreachable:NoExecute`, 68 // with tolerationSeconds of 300s. 69 // If the pod already specifies a toleration for taint `notReady:NoExecute` 70 // or `unreachable:NoExecute`, the plugin won't touch it. 71 type Plugin struct { 72 *admission.Handler 73 } 74 75 var _ admission.MutationInterface = &Plugin{} 76 77 // NewDefaultTolerationSeconds creates a new instance of the DefaultTolerationSeconds admission controller 78 func NewDefaultTolerationSeconds() *Plugin { 79 return &Plugin{ 80 Handler: admission.NewHandler(admission.Create, admission.Update), 81 } 82 } 83 84 // Admit makes an admission decision based on the request attributes 85 func (p *Plugin) Admit(ctx context.Context, attributes admission.Attributes, o admission.ObjectInterfaces) (err error) { 86 if attributes.GetResource().GroupResource() != api.Resource("pods") { 87 return nil 88 } 89 90 if len(attributes.GetSubresource()) > 0 { 91 // only run the checks below on pods proper and not subresources 92 return nil 93 } 94 95 pod, ok := attributes.GetObject().(*api.Pod) 96 if !ok { 97 return errors.NewBadRequest(fmt.Sprintf("expected *api.Pod but got %T", attributes.GetObject())) 98 } 99 100 tolerations := pod.Spec.Tolerations 101 102 toleratesNodeNotReady := false 103 toleratesNodeUnreachable := false 104 for _, toleration := range tolerations { 105 if (toleration.Key == v1.TaintNodeNotReady || len(toleration.Key) == 0) && 106 (toleration.Effect == api.TaintEffectNoExecute || len(toleration.Effect) == 0) { 107 toleratesNodeNotReady = true 108 } 109 110 if (toleration.Key == v1.TaintNodeUnreachable || len(toleration.Key) == 0) && 111 (toleration.Effect == api.TaintEffectNoExecute || len(toleration.Effect) == 0) { 112 toleratesNodeUnreachable = true 113 } 114 } 115 116 if !toleratesNodeNotReady { 117 pod.Spec.Tolerations = append(pod.Spec.Tolerations, notReadyToleration) 118 } 119 120 if !toleratesNodeUnreachable { 121 pod.Spec.Tolerations = append(pod.Spec.Tolerations, unreachableToleration) 122 } 123 124 return nil 125 }