mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +00:00
Merge pull request #111194 from ravisantoshgudimetla/promote-maxSurge-ga
Promote DS max surge to GA
This commit is contained in:
commit
7156c96e5d
2
api/openapi-spec/swagger.json
generated
2
api/openapi-spec/swagger.json
generated
@ -1178,7 +1178,7 @@
|
||||
"properties": {
|
||||
"maxSurge": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString",
|
||||
"description": "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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate."
|
||||
"description": "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."
|
||||
},
|
||||
"maxUnavailable": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString",
|
||||
|
@ -860,7 +860,7 @@
|
||||
"$ref": "#/components/schemas/io.k8s.apimachinery.pkg.util.intstr.IntOrString"
|
||||
}
|
||||
],
|
||||
"description": "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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate."
|
||||
"description": "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."
|
||||
},
|
||||
"maxUnavailable": {
|
||||
"allOf": [
|
||||
|
@ -625,7 +625,6 @@ type RollingUpdateDaemonSet struct {
|
||||
// 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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
|
||||
// +optional
|
||||
MaxSurge intstr.IntOrString
|
||||
}
|
||||
|
@ -28,11 +28,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// ValidateStatefulSetName can be used to check whether the given StatefulSet name is valid.
|
||||
@ -373,34 +371,25 @@ func ValidateDaemonSetSpec(spec *apps.DaemonSetSpec, fldPath *field.Path, opts a
|
||||
// ValidateRollingUpdateDaemonSet validates a given RollingUpdateDaemonSet.
|
||||
func ValidateRollingUpdateDaemonSet(rollingUpdate *apps.RollingUpdateDaemonSet, fldPath *field.Path) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.DaemonSetUpdateSurge) {
|
||||
// Validate both fields are positive ints or have a percentage value
|
||||
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
|
||||
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
|
||||
|
||||
// Validate that MaxUnavailable and MaxSurge are not more than 100%.
|
||||
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
|
||||
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
|
||||
// Validate both fields are positive ints or have a percentage value
|
||||
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
|
||||
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
|
||||
|
||||
// Validate exactly one of MaxSurge or MaxUnavailable is non-zero
|
||||
hasUnavailable := getIntOrPercentValue(rollingUpdate.MaxUnavailable) != 0
|
||||
hasSurge := getIntOrPercentValue(rollingUpdate.MaxSurge) != 0
|
||||
switch {
|
||||
case hasUnavailable && hasSurge:
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxSurge"), rollingUpdate.MaxSurge, "may not be set when maxUnavailable is non-zero"))
|
||||
case !hasUnavailable && !hasSurge:
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("maxUnavailable"), "cannot be 0 when maxSurge is 0"))
|
||||
}
|
||||
// Validate that MaxUnavailable and MaxSurge are not more than 100%.
|
||||
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
|
||||
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
|
||||
|
||||
} else {
|
||||
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
|
||||
if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 {
|
||||
// MaxUnavailable cannot be 0.
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "cannot be 0"))
|
||||
}
|
||||
// Validate that MaxUnavailable is not more than 100%.
|
||||
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
|
||||
// Validate exactly one of MaxSurge or MaxUnavailable is non-zero
|
||||
hasUnavailable := getIntOrPercentValue(rollingUpdate.MaxUnavailable) != 0
|
||||
hasSurge := getIntOrPercentValue(rollingUpdate.MaxSurge) != 0
|
||||
switch {
|
||||
case hasUnavailable && hasSurge:
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxSurge"), rollingUpdate.MaxSurge, "may not be set when maxUnavailable is non-zero"))
|
||||
case !hasUnavailable && !hasSurge:
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("maxUnavailable"), "cannot be 0 when maxSurge is 0"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -3591,7 +3591,6 @@ func TestValidateReplicaSet(t *testing.T) {
|
||||
func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
ds *apps.RollingUpdateDaemonSet
|
||||
enableSurge bool
|
||||
expectError bool
|
||||
}{
|
||||
"invalid: unset": {
|
||||
@ -3637,45 +3636,40 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
MaxUnavailable: intstr.FromString("1%"),
|
||||
MaxSurge: intstr.FromString("1%"),
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
|
||||
"invalid: surge enabled, unavailable zero percent": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: intstr.FromString("0%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
"invalid: surge enabled, unavailable zero": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: intstr.FromInt(0),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
"valid: surge enabled, unavailable one": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: intstr.FromInt(1),
|
||||
},
|
||||
enableSurge: true,
|
||||
},
|
||||
"valid: surge enabled, unavailable one percent": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: intstr.FromString("1%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
},
|
||||
"valid: surge enabled, unavailable 100%": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: intstr.FromString("100%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
},
|
||||
"invalid: surge enabled, unavailable greater than 100%": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: intstr.FromString("101%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
|
||||
@ -3683,39 +3677,33 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxSurge: intstr.FromString("0%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
"invalid: surge enabled, surge zero": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxSurge: intstr.FromInt(0),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
"valid: surge enabled, surge one": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxSurge: intstr.FromInt(1),
|
||||
},
|
||||
enableSurge: true,
|
||||
},
|
||||
"valid: surge enabled, surge one percent": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxSurge: intstr.FromString("1%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
},
|
||||
"valid: surge enabled, surge 100%": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxSurge: intstr.FromString("100%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
},
|
||||
"invalid: surge enabled, surge greater than 100%": {
|
||||
ds: &apps.RollingUpdateDaemonSet{
|
||||
MaxSurge: intstr.FromString("101%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
|
||||
@ -3724,7 +3712,6 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
MaxUnavailable: intstr.FromString("1%"),
|
||||
MaxSurge: intstr.FromString("1%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
|
||||
@ -3733,7 +3720,6 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
MaxUnavailable: intstr.FromString("0%"),
|
||||
MaxSurge: intstr.FromString("0%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
"invalid: surge enabled, surge and unavailable zero": {
|
||||
@ -3741,7 +3727,6 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
MaxUnavailable: intstr.FromInt(0),
|
||||
MaxSurge: intstr.FromInt(0),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
"invalid: surge enabled, surge and unavailable mixed zero": {
|
||||
@ -3749,13 +3734,11 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
|
||||
MaxUnavailable: intstr.FromInt(0),
|
||||
MaxSurge: intstr.FromString("0%"),
|
||||
},
|
||||
enableSurge: true,
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
for tcName, tc := range testCases {
|
||||
t.Run(tcName, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, tc.enableSurge)()
|
||||
errs := ValidateRollingUpdateDaemonSet(tc.ds, field.NewPath("spec", "updateStrategy", "rollingUpdate"))
|
||||
if tc.expectError && len(errs) == 0 {
|
||||
t.Errorf("Unexpected success")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,12 +27,9 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/klog/v2"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/controller/daemon/util"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
testingclock "k8s.io/utils/clock/testing"
|
||||
)
|
||||
|
||||
@ -78,7 +75,6 @@ func TestDaemonSetUpdatesPods(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonSetUpdatesPodsWithMaxSurge(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, true)()
|
||||
ds := newDaemonSet("foo")
|
||||
manager, podControl, _, err := newTestController(ds)
|
||||
if err != nil {
|
||||
@ -191,7 +187,6 @@ func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonSetUpdatesAllOldPodsNotReadyMaxSurge(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, true)()
|
||||
ds := newDaemonSet("foo")
|
||||
manager, podControl, _, err := newTestController(ds)
|
||||
if err != nil {
|
||||
@ -381,7 +376,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
Manager *daemonSetsController
|
||||
ds *apps.DaemonSet
|
||||
nodeToPods map[string][]*v1.Pod
|
||||
enableSurge bool
|
||||
maxSurge int
|
||||
maxUnavailable int
|
||||
emptyNodes int
|
||||
@ -536,7 +530,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
mapping["node-1"] = []*v1.Pod{pod1}
|
||||
return mapping
|
||||
}(),
|
||||
enableSurge: true,
|
||||
maxSurge: 1,
|
||||
maxUnavailable: 0,
|
||||
emptyNodes: 0,
|
||||
@ -566,7 +559,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
mapping["node-1"] = []*v1.Pod{pod1}
|
||||
return mapping
|
||||
}(),
|
||||
enableSurge: true,
|
||||
maxSurge: 2,
|
||||
maxUnavailable: 0,
|
||||
emptyNodes: 0,
|
||||
@ -605,8 +597,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, c.enableSurge)()
|
||||
|
||||
c.Manager.dsStore.Add(c.ds)
|
||||
nodeList, err := c.Manager.nodeLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
|
@ -25,9 +25,7 @@ import (
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
intstrutil "k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// GetTemplateGeneration gets the template generation associated with a v1.DaemonSet by extracting it from the
|
||||
@ -137,9 +135,7 @@ func SurgeCount(ds *apps.DaemonSet, numberToSchedule int) (int, error) {
|
||||
if ds.Spec.UpdateStrategy.Type != apps.RollingUpdateDaemonSetStrategyType {
|
||||
return 0, nil
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DaemonSetUpdateSurge) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
r := ds.Spec.UpdateStrategy.RollingUpdate
|
||||
if r == nil {
|
||||
return 0, nil
|
||||
|
@ -215,6 +215,7 @@ const (
|
||||
// owner: @smarterclayton
|
||||
// alpha: v1.21
|
||||
// beta: v1.22
|
||||
// GA: v1.25
|
||||
// DaemonSets allow workloads to maintain availability during update per node
|
||||
DaemonSetUpdateSurge featuregate.Feature = "DaemonSetUpdateSurge"
|
||||
|
||||
@ -862,7 +863,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
CronJobTimeZone: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
DaemonSetUpdateSurge: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.22
|
||||
DaemonSetUpdateSurge: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
|
||||
|
||||
DefaultPodTopologySpread: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||
|
||||
|
4
pkg/generated/openapi/zz_generated.openapi.go
generated
4
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -3728,7 +3728,7 @@ func schema_k8sio_api_apps_v1_RollingUpdateDaemonSet(ref common.ReferenceCallbac
|
||||
},
|
||||
"maxSurge": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.",
|
||||
Description: "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.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/util/intstr.IntOrString"),
|
||||
},
|
||||
},
|
||||
@ -6376,7 +6376,7 @@ func schema_k8sio_api_apps_v1beta2_RollingUpdateDaemonSet(ref common.ReferenceCa
|
||||
},
|
||||
"maxSurge": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.",
|
||||
Description: "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.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/util/intstr.IntOrString"),
|
||||
},
|
||||
},
|
||||
|
@ -24,17 +24,14 @@ import (
|
||||
apivalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/pod"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/apps/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
@ -82,7 +79,6 @@ func (daemonSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Objec
|
||||
daemonSet.Spec.TemplateGeneration = 1
|
||||
}
|
||||
|
||||
dropDaemonSetDisabledFields(daemonSet, nil)
|
||||
pod.DropDisabledTemplateFields(&daemonSet.Spec.Template, nil)
|
||||
}
|
||||
|
||||
@ -91,7 +87,6 @@ func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
||||
newDaemonSet := obj.(*apps.DaemonSet)
|
||||
oldDaemonSet := old.(*apps.DaemonSet)
|
||||
|
||||
dropDaemonSetDisabledFields(newDaemonSet, oldDaemonSet)
|
||||
pod.DropDisabledTemplateFields(&newDaemonSet.Spec.Template, &oldDaemonSet.Spec.Template)
|
||||
|
||||
// update is not allowed to set status
|
||||
@ -121,35 +116,6 @@ func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
||||
}
|
||||
}
|
||||
|
||||
// dropDaemonSetDisabledFields drops fields that are not used if their associated feature gates
|
||||
// are not enabled. The typical pattern is:
|
||||
// if !utilfeature.DefaultFeatureGate.Enabled(features.MyFeature) && !myFeatureInUse(oldSvc) {
|
||||
// newSvc.Spec.MyFeature = nil
|
||||
// }
|
||||
func dropDaemonSetDisabledFields(newDS *apps.DaemonSet, oldDS *apps.DaemonSet) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DaemonSetUpdateSurge) {
|
||||
if r := newDS.Spec.UpdateStrategy.RollingUpdate; r != nil {
|
||||
if daemonSetSurgeFieldsInUse(oldDS) {
|
||||
// we need to ensure that MaxUnavailable is non-zero to preserve previous behavior
|
||||
if r.MaxUnavailable.IntVal == 0 && r.MaxUnavailable.StrVal == "0%" {
|
||||
r.MaxUnavailable = intstr.FromInt(1)
|
||||
}
|
||||
} else {
|
||||
// clear the MaxSurge field and let validation deal with MaxUnavailable
|
||||
r.MaxSurge = intstr.IntOrString{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// daemonSetSurgeFieldsInUse returns true if fields related to daemonset update surge are set
|
||||
func daemonSetSurgeFieldsInUse(ds *apps.DaemonSet) bool {
|
||||
if ds == nil {
|
||||
return false
|
||||
}
|
||||
return ds.Spec.UpdateStrategy.RollingUpdate != nil && (ds.Spec.UpdateStrategy.RollingUpdate.MaxSurge.IntVal != 0 || ds.Spec.UpdateStrategy.RollingUpdate.MaxSurge.StrVal != "")
|
||||
}
|
||||
|
||||
// Validate validates a new daemon set.
|
||||
func (daemonSetStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||
daemonSet := obj.(*apps.DaemonSet)
|
||||
|
@ -21,15 +21,10 @@ import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -139,207 +134,3 @@ func newDaemonSetWithSelectorLabels(selectorLabels map[string]string, templateGe
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeDaemonSetWithSurge(unavailable intstr.IntOrString, surge intstr.IntOrString) *apps.DaemonSet {
|
||||
return &apps.DaemonSet{
|
||||
Spec: apps.DaemonSetSpec{
|
||||
UpdateStrategy: apps.DaemonSetUpdateStrategy{
|
||||
Type: apps.RollingUpdateDaemonSetStrategyType,
|
||||
RollingUpdate: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: unavailable,
|
||||
MaxSurge: surge,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropDisabledField(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
enableSurge bool
|
||||
ds *apps.DaemonSet
|
||||
old *apps.DaemonSet
|
||||
expect *apps.DaemonSet
|
||||
}{
|
||||
{
|
||||
name: "not surge, no update",
|
||||
enableSurge: false,
|
||||
ds: &apps.DaemonSet{},
|
||||
old: nil,
|
||||
expect: &apps.DaemonSet{},
|
||||
},
|
||||
{
|
||||
name: "not surge, field not used",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, field not used in old and new",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used and cleared",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used and cleared, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, field not used",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, field not used in old and new",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, field used",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "surge, field used, percent",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
},
|
||||
{
|
||||
name: "surge, field used in old and new",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "surge, allows both fields (validation must catch)",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "surge, allows change from unavailable to surge",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, allows change from surge to unvailable",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from unavailable to surge",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from surge to unvailable",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from unavailable to surge, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("2%"), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromString("2%"), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from surge to unvailable, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromString("2%"), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, resets zero percent, one percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.FromString("1%")),
|
||||
},
|
||||
{
|
||||
name: "not surge, resets and clears when zero percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, sets zero percent, one percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, sets and clears zero percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, tc.enableSurge)()
|
||||
old := tc.old.DeepCopy()
|
||||
|
||||
dropDaemonSetDisabledFields(tc.ds, tc.old)
|
||||
|
||||
// old obj should never be changed
|
||||
if !reflect.DeepEqual(tc.old, old) {
|
||||
t.Fatalf("old ds changed: %v", diff.ObjectReflectDiff(tc.old, old))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.ds, tc.expect) {
|
||||
t.Fatalf("unexpected ds spec: %v", diff.ObjectReflectDiff(tc.expect, tc.ds))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -513,7 +513,6 @@ message RollingUpdateDaemonSet {
|
||||
// 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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2;
|
||||
}
|
||||
|
@ -596,7 +596,6 @@ type RollingUpdateDaemonSet struct {
|
||||
// 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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
|
||||
// +optional
|
||||
MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"`
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ func (ReplicaSetStatus) SwaggerDoc() map[string]string {
|
||||
var map_RollingUpdateDaemonSet = map[string]string{
|
||||
"": "Spec to control the desired behavior of daemon set rolling update.",
|
||||
"maxUnavailable": "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 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.",
|
||||
"maxSurge": "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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.",
|
||||
"maxSurge": "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.",
|
||||
}
|
||||
|
||||
func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string {
|
||||
|
@ -519,7 +519,6 @@ message RollingUpdateDaemonSet {
|
||||
// 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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2;
|
||||
}
|
||||
|
@ -648,7 +648,6 @@ type RollingUpdateDaemonSet struct {
|
||||
// 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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
|
||||
// +optional
|
||||
MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"`
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ func (ReplicaSetStatus) SwaggerDoc() map[string]string {
|
||||
var map_RollingUpdateDaemonSet = map[string]string{
|
||||
"": "Spec to control the desired behavior of daemon set rolling update.",
|
||||
"maxUnavailable": "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 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.",
|
||||
"maxSurge": "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 beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.",
|
||||
"maxSurge": "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.",
|
||||
}
|
||||
|
||||
func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string {
|
||||
|
Loading…
Reference in New Issue
Block a user