Unverified Commit 412271d4 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #55251 from deads2k/admission-13-toleration

Automatic merge from submit-queue (batch tested with PRs 53747, 54528, 55279, 55251, 55311). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. update podtolerations admission to mutate and validate separately Updates the podtolerations admission plugin to mutate and validate separately. This also fixes the bug where the toleration whitelist isn't respected for memory pressure. ```release-note-action-required The `node.kubernetes.io/memory-pressure` taint now respects the configured whitelist. If you need to use it, you'll have to add it to the whitelist. ```
parents d1ba5447 84e62510
......@@ -77,19 +77,7 @@ type podTolerationsPlugin struct {
// scheduler.alpha.kubernetes.io/defaultTolerations and scheduler.alpha.kubernetes.io/tolerationsWhitelist
// annotations keys.
func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
resource := a.GetResource().GroupResource()
if resource != api.Resource("pods") {
return nil
}
if a.GetSubresource() != "" {
// only run the checks below on pods proper and not subresources
return nil
}
obj := a.GetObject()
pod, ok := obj.(*api.Pod)
if !ok {
glog.Errorf("expected pod but got %s", a.GetKind().Kind)
if shouldIgnore(a) {
return nil
}
......@@ -97,28 +85,14 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
}
nsName := a.GetNamespace()
namespace, err := p.namespaceLister.Get(nsName)
if errors.IsNotFound(err) {
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
namespace, err = p.client.Core().Namespaces().Get(nsName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return err
}
return errors.NewInternalError(err)
}
} else if err != nil {
return errors.NewInternalError(err)
}
pod := a.GetObject().(*api.Pod)
var finalTolerations []api.Toleration
updateUninitialized, err := util.IsUpdatingUninitializedObject(a)
if err != nil {
return err
}
if a.GetOperation() == admission.Create || updateUninitialized {
ts, err := p.getNamespaceDefaultTolerations(namespace)
ts, err := p.getNamespaceDefaultTolerations(a.GetNamespace())
if err != nil {
return err
}
......@@ -148,9 +122,32 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
finalTolerations = pod.Spec.Tolerations
}
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 p.Validate(a)
}
func (p *podTolerationsPlugin) Validate(a admission.Attributes) error {
if shouldIgnore(a) {
return nil
}
if !p.WaitForReady() {
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
}
// whitelist verification.
if len(finalTolerations) > 0 {
whitelist, err := p.getNamespaceTolerationsWhitelist(namespace)
pod := a.GetObject().(*api.Pod)
if len(pod.Spec.Tolerations) > 0 {
whitelist, err := p.getNamespaceTolerationsWhitelist(a.GetNamespace())
if err != nil {
return err
}
......@@ -163,25 +160,33 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
if len(whitelist) > 0 {
// check if the merged pod tolerations satisfy its namespace whitelist
if !tolerations.VerifyAgainstWhitelist(finalTolerations, whitelist) {
if !tolerations.VerifyAgainstWhitelist(pod.Spec.Tolerations, whitelist) {
return fmt.Errorf("pod tolerations (possibly merged with namespace default tolerations) conflict with its namespace whitelist")
}
}
}
if qoshelper.GetPodQOS(pod) != api.PodQOSBestEffort {
finalTolerations = tolerations.MergeTolerations(finalTolerations, []api.Toleration{
{
Key: algorithm.TaintNodeMemoryPressure,
Operator: api.TolerationOpExists,
Effect: api.TaintEffectNoSchedule,
},
})
return nil
}
func shouldIgnore(a admission.Attributes) bool {
resource := a.GetResource().GroupResource()
if resource != api.Resource("pods") {
return true
}
if a.GetSubresource() != "" {
// only run the checks below on pods proper and not subresources
return true
}
pod.Spec.Tolerations = finalTolerations
return nil
obj := a.GetObject()
_, ok := obj.(*api.Pod)
if !ok {
glog.Errorf("expected pod but got %s", a.GetKind().Kind)
return true
}
return false
}
func NewPodTolerationsPlugin(pluginConfig *pluginapi.Configuration) *podTolerationsPlugin {
......@@ -212,11 +217,38 @@ func (p *podTolerationsPlugin) ValidateInitialization() error {
return nil
}
func (p *podTolerationsPlugin) getNamespaceDefaultTolerations(ns *api.Namespace) ([]api.Toleration, error) {
// in exceptional cases, this can result in two live calls, but once the cache catches up, that will stop.
func (p *podTolerationsPlugin) getNamespace(nsName string) (*api.Namespace, error) {
namespace, err := p.namespaceLister.Get(nsName)
if errors.IsNotFound(err) {
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
namespace, err = p.client.Core().Namespaces().Get(nsName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return nil, err
}
return nil, errors.NewInternalError(err)
}
} else if err != nil {
return nil, errors.NewInternalError(err)
}
return namespace, nil
}
func (p *podTolerationsPlugin) getNamespaceDefaultTolerations(nsName string) ([]api.Toleration, error) {
ns, err := p.getNamespace(nsName)
if err != nil {
return nil, err
}
return extractNSTolerations(ns, NSDefaultTolerations)
}
func (p *podTolerationsPlugin) getNamespaceTolerationsWhitelist(ns *api.Namespace) ([]api.Toleration, error) {
func (p *podTolerationsPlugin) getNamespaceTolerationsWhitelist(nsName string) ([]api.Toleration, error) {
ns, err := p.getNamespace(nsName)
if err != nil {
return nil, err
}
return extractNSTolerations(ns, NSWLTolerations)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment