mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 23:15:14 +00:00
update podtolerations admission to mutate and validate separately
This commit is contained in:
parent
ef8746af3d
commit
84e6251046
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user