Code change:
} return allErrs } <ins> func validateNodeSelectorMutation(fldPath *field.Path, newNodeSelector, oldNodeSelector map[string]string) field.ErrorList { var allErrs field.ErrorList // Validate no existing node selectors were deleted or mutated. for k, v1 := range oldNodeSelector { if v2, ok := newNodeSelector[k]; !ok || v1 != v2 { allErrs = append(allErrs, field.Invalid(fldPath, newNodeSelector, "only additions to spec.nodeSelector are allowed (no mutations or deletions)")) return allErrs } } return allErrs } func validateNodeAffinityMutation(nodeAffinityPath *field.Path, newNodeAffinity, oldNodeAffinity *core.NodeAffinity) field.ErrorList { var allErrs field.ErrorList // If old node affinity was nil, anything can be set. if oldNodeAffinity == nil || oldNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { return allErrs } oldTerms := oldNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms var newTerms []core.NodeSelectorTerm if newNodeAffinity != nil && newNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil { newTerms = newNodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms } // If there are no old terms, we can set the new terms to anything. // If there are old terms, we cannot add any new ones. if len(oldTerms) > 0 && len(oldTerms) != len(newTerms) { return append(allErrs, field.Invalid(nodeAffinityPath.Child("requiredDuringSchedulingIgnoredDuringExecution").Child("nodeSelectorTerms"), newTerms, "no additions/deletions to non-empty NodeSelectorTerms list are allowed")) } // For requiredDuringSchedulingIgnoredDuringExecution, if old NodeSelectorTerms // was empty, anything can be set. If non-empty, only additions of NodeSelectorRequirements // to matchExpressions or fieldExpressions are allowed. for i := range oldTerms { if !validateNodeSelectorTermHasOnlyAdditions(newTerms[i], oldTerms[i]) { allErrs = append(allErrs, field.Invalid(nodeAffinityPath.Child("requiredDuringSchedulingIgnoredDuringExecution").Child("nodeSelectorTerms").Index(i), newTerms[i], "only additions are allowed (no mutations or deletions)")) } } return allErrs } func validateNodeSelectorTermHasOnlyAdditions(newTerm, oldTerm core.NodeSelectorTerm) bool { if len(oldTerm.MatchExpressions) == 0 && len(oldTerm.MatchFields) == 0 { if len(newTerm.MatchExpressions) > 0 || len(newTerm.MatchFields) > 0 { return false } } // Validate MatchExpressions only has additions (no deletions or mutations) if l := len(oldTerm.MatchExpressions); l > 0 { if len(newTerm.MatchExpressions) < l { return false } if !apiequality.Semantic.DeepEqual(newTerm.MatchExpressions[:l], oldTerm.MatchExpressions) { return false } } // Validate MatchFields only has additions (no deletions or mutations) if l := len(oldTerm.MatchFields); l > 0 { if len(newTerm.MatchFields) < l { return false } if !apiequality.Semantic.DeepEqual(newTerm.MatchFields[:l], oldTerm.MatchFields) { return false } } return true } </ins>

Related discussion:
text: See for context. This issue is creating to track work on the API validation changes. Validation relaxation of certain fields in the pod spec to allow for mutable scheduling directives.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/assign
/sig scheduling
Docs PR: