mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +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:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user