mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Merge pull request #41818 from aveshagarwal/master-taints-tolerations-api-fields-pod-spec-updates
Automatic merge from submit-queue (batch tested with PRs 41701, 41818, 41897, 41119, 41562) Allow updates to pod tolerations. Opening this PR to continue discussion for pod spec tolerations updates when a pod has been scheduled already. This PR is built on top of https://github.com/kubernetes/kubernetes/pull/38957. @kubernetes/sig-scheduling-pr-reviews @liggitt @davidopp @derekwaynecarr @kubernetes/rh-cluster-infra
This commit is contained in:
commit
1359ffc502
@ -1848,6 +1848,29 @@ func validateTaintEffect(effect *api.TaintEffect, allowEmpty bool, fldPath *fiel
|
|||||||
return allErrors
|
return allErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateOnlyAddedTolerations validates updated pod tolerations.
|
||||||
|
func validateOnlyAddedTolerations(newTolerations []api.Toleration, oldTolerations []api.Toleration, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
for _, old := range oldTolerations {
|
||||||
|
found := false
|
||||||
|
old.TolerationSeconds = nil
|
||||||
|
for _, new := range newTolerations {
|
||||||
|
new.TolerationSeconds = nil
|
||||||
|
if reflect.DeepEqual(old, new) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(fldPath, "existing toleration can not be modified except its tolerationSeconds"))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allErrs = append(allErrs, validateTolerations(newTolerations, fldPath)...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
// validateTolerations tests if given tolerations have valid data.
|
// validateTolerations tests if given tolerations have valid data.
|
||||||
func validateTolerations(tolerations []api.Toleration, fldPath *field.Path) field.ErrorList {
|
func validateTolerations(tolerations []api.Toleration, fldPath *field.Path) field.ErrorList {
|
||||||
allErrors := field.ErrorList{}
|
allErrors := field.ErrorList{}
|
||||||
@ -2348,9 +2371,14 @@ func ValidatePodUpdate(newPod, oldPod *api.Pod) field.ErrorList {
|
|||||||
activeDeadlineSeconds := *oldPod.Spec.ActiveDeadlineSeconds
|
activeDeadlineSeconds := *oldPod.Spec.ActiveDeadlineSeconds
|
||||||
mungedPod.Spec.ActiveDeadlineSeconds = &activeDeadlineSeconds
|
mungedPod.Spec.ActiveDeadlineSeconds = &activeDeadlineSeconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow only additions to tolerations updates.
|
||||||
|
mungedPod.Spec.Tolerations = oldPod.Spec.Tolerations
|
||||||
|
allErrs = append(allErrs, validateOnlyAddedTolerations(newPod.Spec.Tolerations, oldPod.Spec.Tolerations, specPath.Child("tolerations"))...)
|
||||||
|
|
||||||
if !apiequality.Semantic.DeepEqual(mungedPod.Spec, oldPod.Spec) {
|
if !apiequality.Semantic.DeepEqual(mungedPod.Spec, oldPod.Spec) {
|
||||||
//TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff
|
//TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff
|
||||||
allErrs = append(allErrs, field.Forbidden(specPath, "pod updates may not change fields other than `containers[*].image` or `spec.activeDeadlineSeconds`"))
|
allErrs = append(allErrs, field.Forbidden(specPath, "pod updates may not change fields other than `containers[*].image` or `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
|
@ -4506,7 +4506,6 @@ func TestValidatePodUpdate(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
"activeDeadlineSeconds change to nil from positive",
|
"activeDeadlineSeconds change to nil from positive",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
api.Pod{
|
api.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||||
@ -4587,6 +4586,157 @@ func TestValidatePodUpdate(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
"bad label change",
|
"bad label change",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value2"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
"existing toleration value modified in pod spec updates",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value2", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: nil}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{10}[0]}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
"existing toleration value modified in pod spec updates with modified tolerationSeconds",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{10}[0]}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{20}[0]}},
|
||||||
|
}},
|
||||||
|
true,
|
||||||
|
"modified tolerationSeconds in existing toleration value in pod spec updates",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value2"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
"toleration modified in updates to an unscheduled pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
"tolerations unmodified in updates to a scheduled pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{
|
||||||
|
{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{20}[0]},
|
||||||
|
{Key: "key2", Value: "value2", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{30}[0]},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{10}[0]}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
"added valid new toleration to existing tolerations in pod spec updates",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{
|
||||||
|
NodeName: "node1",
|
||||||
|
Tolerations: []api.Toleration{
|
||||||
|
{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{20}[0]},
|
||||||
|
{Key: "key2", Value: "value2", Operator: "Equal", Effect: "NoSchedule", TolerationSeconds: &[]int64{30}[0]},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
NodeName: "node1", Tolerations: []api.Toleration{{Key: "key1", Value: "value1", Operator: "Equal", Effect: "NoExecute", TolerationSeconds: &[]int64{10}[0]}},
|
||||||
|
}},
|
||||||
|
false,
|
||||||
|
"added invalid new toleration to existing tolerations in pod spec updates",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -1171,7 +1171,7 @@ func PodToleratesNodeTaints(pod *v1.Pod, meta interface{}, nodeInfo *schedulerca
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v1.TolerationsTolerateTaintsWithFilter(pod.Spec.Tolerations, taints, func(t *v1.Taint) bool {
|
if v1.TolerationsTolerateTaintsWithFilter(pod.Spec.Tolerations, taints, func(t *v1.Taint) bool {
|
||||||
// PodToleratesNodeTaints is only interested in NoSchedule taints.
|
// PodToleratesNodeTaints is only interested in NoSchedule and NoExecute taints.
|
||||||
return t.Effect == v1.TaintEffectNoSchedule || t.Effect == v1.TaintEffectNoExecute
|
return t.Effect == v1.TaintEffectNoSchedule || t.Effect == v1.TaintEffectNoExecute
|
||||||
}) {
|
}) {
|
||||||
return true, nil, nil
|
return true, nil, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user