From 5aa53f885c980873087cbc86e1eccdf342e775b5 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Thu, 5 Nov 2020 14:54:52 -0500 Subject: [PATCH] api: Add DaemonSet MaxSurge The MaxSurge field on DaemonSet rolling updates allows a daemonset workload to have two pods running simultaneously on a node during an update in order to perform zero-disruption handoffs of client traffic. --- pkg/apis/apps/fuzzer/fuzzer.go | 6 ++- pkg/apis/apps/types.go | 38 +++++++++++++++---- pkg/apis/apps/v1/conversion_test.go | 7 ++-- pkg/apis/apps/v1/defaults.go | 5 +++ pkg/apis/apps/v1/defaults_test.go | 6 ++- pkg/apis/apps/v1beta2/conversion_test.go | 7 ++-- pkg/apis/apps/v1beta2/defaults.go | 5 +++ pkg/apis/apps/v1beta2/defaults_test.go | 6 ++- pkg/apis/extensions/v1beta1/defaults.go | 7 +++- staging/src/k8s.io/api/apps/v1/types.go | 38 +++++++++++++++---- staging/src/k8s.io/api/apps/v1beta2/types.go | 38 +++++++++++++++---- .../k8s.io/api/extensions/v1beta1/types.go | 38 +++++++++++++++---- 12 files changed, 158 insertions(+), 43 deletions(-) diff --git a/pkg/apis/apps/fuzzer/fuzzer.go b/pkg/apis/apps/fuzzer/fuzzer.go index 952dbe64dc9..5f7858560ba 100644 --- a/pkg/apis/apps/fuzzer/fuzzer.go +++ b/pkg/apis/apps/fuzzer/fuzzer.go @@ -118,11 +118,13 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { rollingUpdate := apps.RollingUpdateDaemonSet{} if c.RandBool() { if c.RandBool() { - rollingUpdate.MaxUnavailable = intstr.FromInt(1 + int(c.Rand.Int31())) + rollingUpdate.MaxUnavailable = intstr.FromInt(int(c.Rand.Int31())) + rollingUpdate.MaxSurge = intstr.FromInt(int(c.Rand.Int31())) } else { - rollingUpdate.MaxUnavailable = intstr.FromString(fmt.Sprintf("%d%%", 1+c.Rand.Int31())) + rollingUpdate.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.Rand.Int31())) } } + j.RollingUpdate = &rollingUpdate } }, diff --git a/pkg/apis/apps/types.go b/pkg/apis/apps/types.go index c42ea2b6215..6866540baf0 100644 --- a/pkg/apis/apps/types.go +++ b/pkg/apis/apps/types.go @@ -532,19 +532,41 @@ type RollingUpdateDaemonSet struct { // The maximum number of DaemonSet pods that can be unavailable during the // update. Value can be an absolute number (ex: 5) or a percentage of total // number of DaemonSet pods at the start of the update (ex: 10%). Absolute - // number is calculated from percentage by rounding up. - // This cannot be 0. + // number is calculated from percentage by rounding down to a minimum of one. + // This cannot be 0 if MaxSurge is 0 // Default value is 1. // Example: when this is set to 30%, at most 30% of the total number of nodes // that should be running the daemon pod (i.e. status.desiredNumberScheduled) - // can have their pods stopped for an update at any given - // time. The update starts by stopping at most 30% of those DaemonSet pods - // and then brings up new DaemonSet pods in their place. Once the new pods - // are available, it then proceeds onto other DaemonSet pods, thus ensuring - // that at least 70% of original number of DaemonSet pods are available at - // all times during the update. + // can have their pods stopped for an update at any given time. The update + // starts by stopping at most 30% of those DaemonSet pods and then brings + // up new DaemonSet pods in their place. Once the new pods are available, + // it then proceeds onto other DaemonSet pods, thus ensuring that at least + // 70% of original number of DaemonSet pods are available at all times during + // the update. // +optional MaxUnavailable intstr.IntOrString + + // The maximum number of nodes with an existing available DaemonSet pod that + // can have an updated DaemonSet pod during during an update. + // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + // This can not be 0 if MaxUnavailable is 0. + // Absolute number is calculated from percentage by rounding up to a minimum of 1. + // Default value is 0. + // Example: when this is set to 30%, at most 30% of the total number of nodes + // that should be running the daemon pod (i.e. status.desiredNumberScheduled) + // can have their a new pod created before the old pod is marked as deleted. + // The update starts by launching new pods on 30% of nodes. Once an updated + // pod is available (Ready for at least minReadySeconds) the old DaemonSet pod + // on that node is marked deleted. If the old pod becomes unavailable for any + // reason (Ready transitions to false, is evicted, or is drained) an updated + // pod is immediatedly created on that node without considering surge limits. + // Allowing surge implies the possibility that the resources consumed by the + // daemonset on any given node can double if the readiness check fails, and + // so resource intensive daemonsets should take into account that they may + // cause evictions during disruption. + // This is an alpha field and requires enabling DaemonSetUpdateSurge feature gate. + // +optional + MaxSurge intstr.IntOrString } // DaemonSetSpec is the specification of a daemon set. diff --git a/pkg/apis/apps/v1/conversion_test.go b/pkg/apis/apps/v1/conversion_test.go index 0d6b08e58f7..72957afbc19 100644 --- a/pkg/apis/apps/v1/conversion_test.go +++ b/pkg/apis/apps/v1/conversion_test.go @@ -20,7 +20,7 @@ import ( "testing" appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -226,13 +226,14 @@ func TestV1StatefulSetUpdateStrategyConversion(t *testing.T) { func TestV1RollingUpdateDaemonSetConversion(t *testing.T) { intorstr := intstr.FromInt(1) + maxSurge := intstr.FromInt(0) testcases := map[string]struct { rollingUpdateDs1 *apps.RollingUpdateDaemonSet rollingUpdateDs2 *appsv1.RollingUpdateDaemonSet }{ "RollingUpdateDaemonSet Conversion 2": { - rollingUpdateDs1: &apps.RollingUpdateDaemonSet{MaxUnavailable: intorstr}, - rollingUpdateDs2: &appsv1.RollingUpdateDaemonSet{MaxUnavailable: &intorstr}, + rollingUpdateDs1: &apps.RollingUpdateDaemonSet{MaxUnavailable: intorstr, MaxSurge: maxSurge}, + rollingUpdateDs2: &appsv1.RollingUpdateDaemonSet{MaxUnavailable: &intorstr, MaxSurge: &maxSurge}, }, } diff --git a/pkg/apis/apps/v1/defaults.go b/pkg/apis/apps/v1/defaults.go index 964c34d51be..8b3a0e9882e 100644 --- a/pkg/apis/apps/v1/defaults.go +++ b/pkg/apis/apps/v1/defaults.go @@ -84,6 +84,11 @@ func SetDefaults_DaemonSet(obj *appsv1.DaemonSet) { maxUnavailable := intstr.FromInt(1) updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable } + if updateStrategy.RollingUpdate.MaxSurge == nil { + // Set default MaxSurge as 0 by default. + maxSurge := intstr.FromInt(0) + updateStrategy.RollingUpdate.MaxSurge = &maxSurge + } } if obj.Spec.RevisionHistoryLimit == nil { obj.Spec.RevisionHistoryLimit = new(int32) diff --git a/pkg/apis/apps/v1/defaults_test.go b/pkg/apis/apps/v1/defaults_test.go index 0d44bcef56a..b1d07d47e7f 100644 --- a/pkg/apis/apps/v1/defaults_test.go +++ b/pkg/apis/apps/v1/defaults_test.go @@ -21,7 +21,7 @@ import ( "testing" appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -38,6 +38,7 @@ import ( func TestSetDefaultDaemonSetSpec(t *testing.T) { defaultLabels := map[string]string{"foo": "bar"} maxUnavailable := intstr.FromInt(1) + maxSurge := intstr.FromInt(0) period := int64(v1.DefaultTerminationGracePeriodSeconds) defaultTemplate := v1.PodTemplateSpec{ Spec: v1.PodSpec{ @@ -80,6 +81,7 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { Type: appsv1.RollingUpdateDaemonSetStrategyType, RollingUpdate: &appsv1.RollingUpdateDaemonSet{ MaxUnavailable: &maxUnavailable, + MaxSurge: &maxSurge, }, }, RevisionHistoryLimit: utilpointer.Int32Ptr(10), @@ -110,6 +112,7 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { Type: appsv1.RollingUpdateDaemonSetStrategyType, RollingUpdate: &appsv1.RollingUpdateDaemonSet{ MaxUnavailable: &maxUnavailable, + MaxSurge: &maxSurge, }, }, RevisionHistoryLimit: utilpointer.Int32Ptr(1), @@ -146,6 +149,7 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { Type: appsv1.RollingUpdateDaemonSetStrategyType, RollingUpdate: &appsv1.RollingUpdateDaemonSet{ MaxUnavailable: &maxUnavailable, + MaxSurge: &maxSurge, }, }, RevisionHistoryLimit: utilpointer.Int32Ptr(10), diff --git a/pkg/apis/apps/v1beta2/conversion_test.go b/pkg/apis/apps/v1beta2/conversion_test.go index f0f185c1f17..c7d8f9b34ec 100644 --- a/pkg/apis/apps/v1beta2/conversion_test.go +++ b/pkg/apis/apps/v1beta2/conversion_test.go @@ -20,7 +20,7 @@ import ( "testing" "k8s.io/api/apps/v1beta2" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/apps" @@ -153,13 +153,14 @@ func TestV1beta2StatefulSetUpdateStrategyConversion(t *testing.T) { func TestV1beta2RollingUpdateDaemonSetConversion(t *testing.T) { intorstr := intstr.FromInt(1) + maxSurge := intstr.FromInt(0) testcases := map[string]struct { rollingUpdateDs1 *apps.RollingUpdateDaemonSet rollingUpdateDs2 *v1beta2.RollingUpdateDaemonSet }{ "RollingUpdateDaemonSet Conversion 2": { - rollingUpdateDs1: &apps.RollingUpdateDaemonSet{MaxUnavailable: intorstr}, - rollingUpdateDs2: &v1beta2.RollingUpdateDaemonSet{MaxUnavailable: &intorstr}, + rollingUpdateDs1: &apps.RollingUpdateDaemonSet{MaxUnavailable: intorstr, MaxSurge: maxSurge}, + rollingUpdateDs2: &v1beta2.RollingUpdateDaemonSet{MaxUnavailable: &intorstr, MaxSurge: &maxSurge}, }, } diff --git a/pkg/apis/apps/v1beta2/defaults.go b/pkg/apis/apps/v1beta2/defaults.go index c93db681dad..f42b021b04e 100644 --- a/pkg/apis/apps/v1beta2/defaults.go +++ b/pkg/apis/apps/v1beta2/defaults.go @@ -41,6 +41,11 @@ func SetDefaults_DaemonSet(obj *appsv1beta2.DaemonSet) { maxUnavailable := intstr.FromInt(1) updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable } + if updateStrategy.RollingUpdate.MaxSurge == nil { + // Set default MaxSurge as 0 by default. + maxSurge := intstr.FromInt(0) + updateStrategy.RollingUpdate.MaxSurge = &maxSurge + } } if obj.Spec.RevisionHistoryLimit == nil { obj.Spec.RevisionHistoryLimit = new(int32) diff --git a/pkg/apis/apps/v1beta2/defaults_test.go b/pkg/apis/apps/v1beta2/defaults_test.go index 7c9f6c3d6a6..d28df38d4d9 100644 --- a/pkg/apis/apps/v1beta2/defaults_test.go +++ b/pkg/apis/apps/v1beta2/defaults_test.go @@ -21,7 +21,7 @@ import ( "testing" appsv1beta2 "k8s.io/api/apps/v1beta2" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -38,6 +38,7 @@ import ( func TestSetDefaultDaemonSetSpec(t *testing.T) { defaultLabels := map[string]string{"foo": "bar"} maxUnavailable := intstr.FromInt(1) + maxSurge := intstr.FromInt(0) period := int64(v1.DefaultTerminationGracePeriodSeconds) defaultTemplate := v1.PodTemplateSpec{ Spec: v1.PodSpec{ @@ -80,6 +81,7 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { Type: appsv1beta2.RollingUpdateDaemonSetStrategyType, RollingUpdate: &appsv1beta2.RollingUpdateDaemonSet{ MaxUnavailable: &maxUnavailable, + MaxSurge: &maxSurge, }, }, RevisionHistoryLimit: utilpointer.Int32Ptr(10), @@ -110,6 +112,7 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { Type: appsv1beta2.RollingUpdateDaemonSetStrategyType, RollingUpdate: &appsv1beta2.RollingUpdateDaemonSet{ MaxUnavailable: &maxUnavailable, + MaxSurge: &maxSurge, }, }, RevisionHistoryLimit: utilpointer.Int32Ptr(1), @@ -146,6 +149,7 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { Type: appsv1beta2.RollingUpdateDaemonSetStrategyType, RollingUpdate: &appsv1beta2.RollingUpdateDaemonSet{ MaxUnavailable: &maxUnavailable, + MaxSurge: &maxSurge, }, }, RevisionHistoryLimit: utilpointer.Int32Ptr(10), diff --git a/pkg/apis/extensions/v1beta1/defaults.go b/pkg/apis/extensions/v1beta1/defaults.go index 1631dcb0eed..1ba702ccc4b 100644 --- a/pkg/apis/extensions/v1beta1/defaults.go +++ b/pkg/apis/extensions/v1beta1/defaults.go @@ -19,7 +19,7 @@ package v1beta1 import ( "math" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -58,6 +58,11 @@ func SetDefaults_DaemonSet(obj *extensionsv1beta1.DaemonSet) { maxUnavailable := intstr.FromInt(1) updateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable } + if updateStrategy.RollingUpdate.MaxSurge == nil { + // Set default MaxSurge as 0 by default. + maxSurge := intstr.FromInt(0) + updateStrategy.RollingUpdate.MaxSurge = &maxSurge + } } if obj.Spec.RevisionHistoryLimit == nil { obj.Spec.RevisionHistoryLimit = new(int32) diff --git a/staging/src/k8s.io/api/apps/v1/types.go b/staging/src/k8s.io/api/apps/v1/types.go index e003a0c4f7c..48299f18ecb 100644 --- a/staging/src/k8s.io/api/apps/v1/types.go +++ b/staging/src/k8s.io/api/apps/v1/types.go @@ -488,19 +488,41 @@ type RollingUpdateDaemonSet struct { // The maximum number of DaemonSet pods that can be unavailable during the // update. Value can be an absolute number (ex: 5) or a percentage of total // number of DaemonSet pods at the start of the update (ex: 10%). Absolute - // number is calculated from percentage by rounding up. - // This cannot be 0. + // number is calculated from percentage by rounding down to a minimum of one. + // This cannot be 0 if MaxSurge is 0 // Default value is 1. // Example: when this is set to 30%, at most 30% of the total number of nodes // that should be running the daemon pod (i.e. status.desiredNumberScheduled) - // can have their pods stopped for an update at any given - // time. The update starts by stopping at most 30% of those DaemonSet pods - // and then brings up new DaemonSet pods in their place. Once the new pods - // are available, it then proceeds onto other DaemonSet pods, thus ensuring - // that at least 70% of original number of DaemonSet pods are available at - // all times during the update. + // can have their pods stopped for an update at any given time. The update + // starts by stopping at most 30% of those DaemonSet pods and then brings + // up new DaemonSet pods in their place. Once the new pods are available, + // it then proceeds onto other DaemonSet pods, thus ensuring that at least + // 70% of original number of DaemonSet pods are available at all times during + // the update. // +optional MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` + + // The maximum number of nodes with an existing available DaemonSet pod that + // can have an updated DaemonSet pod during during an update. + // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + // This can not be 0 if MaxUnavailable is 0. + // Absolute number is calculated from percentage by rounding up to a minimum of 1. + // Default value is 0. + // Example: when this is set to 30%, at most 30% of the total number of nodes + // that should be running the daemon pod (i.e. status.desiredNumberScheduled) + // can have their a new pod created before the old pod is marked as deleted. + // The update starts by launching new pods on 30% of nodes. Once an updated + // pod is available (Ready for at least minReadySeconds) the old DaemonSet pod + // on that node is marked deleted. If the old pod becomes unavailable for any + // reason (Ready transitions to false, is evicted, or is drained) an updated + // pod is immediatedly created on that node without considering surge limits. + // Allowing surge implies the possibility that the resources consumed by the + // daemonset on any given node can double if the readiness check fails, and + // so resource intensive daemonsets should take into account that they may + // cause evictions during disruption. + // This is an alpha field and requires enabling DaemonSetUpdateSurge feature gate. + // +optional + MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` } // DaemonSetSpec is the specification of a daemon set. diff --git a/staging/src/k8s.io/api/apps/v1beta2/types.go b/staging/src/k8s.io/api/apps/v1beta2/types.go index fc542ac1c87..316a0ad24d2 100644 --- a/staging/src/k8s.io/api/apps/v1beta2/types.go +++ b/staging/src/k8s.io/api/apps/v1beta2/types.go @@ -554,19 +554,41 @@ type RollingUpdateDaemonSet struct { // The maximum number of DaemonSet pods that can be unavailable during the // update. Value can be an absolute number (ex: 5) or a percentage of total // number of DaemonSet pods at the start of the update (ex: 10%). Absolute - // number is calculated from percentage by rounding up. - // This cannot be 0. + // number is calculated from percentage by rounding down to a minimum of one. + // This cannot be 0 if MaxSurge is 0 // Default value is 1. // Example: when this is set to 30%, at most 30% of the total number of nodes // that should be running the daemon pod (i.e. status.desiredNumberScheduled) - // can have their pods stopped for an update at any given - // time. The update starts by stopping at most 30% of those DaemonSet pods - // and then brings up new DaemonSet pods in their place. Once the new pods - // are available, it then proceeds onto other DaemonSet pods, thus ensuring - // that at least 70% of original number of DaemonSet pods are available at - // all times during the update. + // can have their pods stopped for an update at any given time. The update + // starts by stopping at most 30% of those DaemonSet pods and then brings + // up new DaemonSet pods in their place. Once the new pods are available, + // it then proceeds onto other DaemonSet pods, thus ensuring that at least + // 70% of original number of DaemonSet pods are available at all times during + // the update. // +optional MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` + + // The maximum number of nodes with an existing available DaemonSet pod that + // can have an updated DaemonSet pod during during an update. + // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + // This can not be 0 if MaxUnavailable is 0. + // Absolute number is calculated from percentage by rounding up to a minimum of 1. + // Default value is 0. + // Example: when this is set to 30%, at most 30% of the total number of nodes + // that should be running the daemon pod (i.e. status.desiredNumberScheduled) + // can have their a new pod created before the old pod is marked as deleted. + // The update starts by launching new pods on 30% of nodes. Once an updated + // pod is available (Ready for at least minReadySeconds) the old DaemonSet pod + // on that node is marked deleted. If the old pod becomes unavailable for any + // reason (Ready transitions to false, is evicted, or is drained) an updated + // pod is immediatedly created on that node without considering surge limits. + // Allowing surge implies the possibility that the resources consumed by the + // daemonset on any given node can double if the readiness check fails, and + // so resource intensive daemonsets should take into account that they may + // cause evictions during disruption. + // This is an alpha field and requires enabling DaemonSetUpdateSurge feature gate. + // +optional + MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` } // DaemonSetSpec is the specification of a daemon set. diff --git a/staging/src/k8s.io/api/extensions/v1beta1/types.go b/staging/src/k8s.io/api/extensions/v1beta1/types.go index bd75c51bcca..0c22a0a69e5 100644 --- a/staging/src/k8s.io/api/extensions/v1beta1/types.go +++ b/staging/src/k8s.io/api/extensions/v1beta1/types.go @@ -357,19 +357,41 @@ type RollingUpdateDaemonSet struct { // The maximum number of DaemonSet pods that can be unavailable during the // update. Value can be an absolute number (ex: 5) or a percentage of total // number of DaemonSet pods at the start of the update (ex: 10%). Absolute - // number is calculated from percentage by rounding up. - // This cannot be 0. + // number is calculated from percentage by rounding down to a minimum of one. + // This cannot be 0 if MaxSurge is 0 // Default value is 1. // Example: when this is set to 30%, at most 30% of the total number of nodes // that should be running the daemon pod (i.e. status.desiredNumberScheduled) - // can have their pods stopped for an update at any given - // time. The update starts by stopping at most 30% of those DaemonSet pods - // and then brings up new DaemonSet pods in their place. Once the new pods - // are available, it then proceeds onto other DaemonSet pods, thus ensuring - // that at least 70% of original number of DaemonSet pods are available at - // all times during the update. + // can have their pods stopped for an update at any given time. The update + // starts by stopping at most 30% of those DaemonSet pods and then brings + // up new DaemonSet pods in their place. Once the new pods are available, + // it then proceeds onto other DaemonSet pods, thus ensuring that at least + // 70% of original number of DaemonSet pods are available at all times during + // the update. // +optional MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` + + // The maximum number of nodes with an existing available DaemonSet pod that + // can have an updated DaemonSet pod during during an update. + // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). + // This can not be 0 if MaxUnavailable is 0. + // Absolute number is calculated from percentage by rounding up to a minimum of 1. + // Default value is 0. + // Example: when this is set to 30%, at most 30% of the total number of nodes + // that should be running the daemon pod (i.e. status.desiredNumberScheduled) + // can have their a new pod created before the old pod is marked as deleted. + // The update starts by launching new pods on 30% of nodes. Once an updated + // pod is available (Ready for at least minReadySeconds) the old DaemonSet pod + // on that node is marked deleted. If the old pod becomes unavailable for any + // reason (Ready transitions to false, is evicted, or is drained) an updated + // pod is immediatedly created on that node without considering surge limits. + // Allowing surge implies the possibility that the resources consumed by the + // daemonset on any given node can double if the readiness check fails, and + // so resource intensive daemonsets should take into account that they may + // cause evictions during disruption. + // This is an alpha field and requires enabling DaemonSetUpdateSurge feature gate. + // +optional + MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` } // DaemonSetSpec is the specification of a daemon set.