Skip to content

Commit ae67234

Browse files
Merge pull request #8893 from lunarwhite/max-backoff-duration
feat: Add configurable CertificateRequest max backoff duration as controller option
2 parents 21c067f + 35e46aa commit ae67234

18 files changed

Lines changed: 278 additions & 43 deletions

File tree

‎cmd/controller/app/controller.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ func buildControllerContextFactory(ctx context.Context, opts *config.ControllerC
370370
EnableOwnerRef: opts.EnableCertificateOwnerRef,
371371
CopiedAnnotationPrefixes: opts.CopiedAnnotationPrefixes,
372372
CertificateRequestMinimumBackoffDuration: opts.CertificateRequestMinimumBackoffDuration,
373+
CertificateRequestMaximumBackoffDuration: opts.CertificateRequestMaximumBackoffDuration,
373374
},
374375

375376
ConfigOptions: controller.ConfigOptions{

‎cmd/controller/app/options/options.go‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,13 @@ func AddConfigFlags(fs *pflag.FlagSet, c *config.ControllerConfiguration) {
256256
"Maximum size in bytes for PEM-encoded certificate bundles.")
257257

258258
fs.DurationVar(&c.CertificateRequestMinimumBackoffDuration, "certificate-request-minimum-backoff-duration", c.CertificateRequestMinimumBackoffDuration, ""+
259-
"Duration of the initial certificate request backoff when a certificate request fails. "+
260-
"The backoff duration is exponentially increased based on consecutive failures, up to a maximum of 32 hours.")
259+
"Minimum duration to back off when a certificate request fails (default 1h). "+
260+
"The backoff delay starts at this value and is exponentially increased "+
261+
"with each consecutive failure, up to the configured maximum backoff duration.")
262+
fs.DurationVar(&c.CertificateRequestMaximumBackoffDuration, "certificate-request-maximum-backoff-duration", c.CertificateRequestMaximumBackoffDuration, ""+
263+
"Maximum duration to back off when a certificate request fails. "+
264+
"The backoff delay starts at the minimum backoff duration and is exponentially increased "+
265+
"with each consecutive failure, but will never exceed this maximum (default 32h).")
261266

262267
logf.AddFlags(&c.Logging, fs)
263268
}

‎deploy/charts/cert-manager/README.template.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,9 @@ config:
483483
maxPrivateKeySize: 13000 # Maximum size in bytes for private keys (default: 13000)
484484
maxChainLength: 95000 # Maximum size in bytes for certificate chains (default: 95000)
485485
maxBundleSize: 330000 # Maximum size in bytes for certificate bundles (default: 330000)
486+
# Configure certificate request backoff durations
487+
certificateRequestMinimumBackoffDuration: 1h
488+
certificateRequestMaximumBackoffDuration: 32h
486489
```
487490
#### **dns01RecursiveNameservers** ~ `string`
488491
> Default value:

‎deploy/charts/cert-manager/values.schema.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@
694694
},
695695
"helm-values.config": {
696696
"default": {},
697-
"description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n gatewayAPI:\n enable: true\n # Feature gates as of v1.20.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ACMEHTTP01IngressPathTypeExact: true # BETA - default=true\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: true # BETA - default=true\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics\n # Configure PEM size limits for certificate validation\n # Useful for certificates with many DNS names (e.g., Istio gateways with 100+ DNS names)\n pemSizeLimitsConfig:\n maxCertificateSize: 36500 # Maximum size in bytes for individual certificates (default: 36500)\n maxPrivateKeySize: 13000 # Maximum size in bytes for private keys (default: 13000)\n maxChainLength: 95000 # Maximum size in bytes for certificate chains (default: 95000)\n maxBundleSize: 330000 # Maximum size in bytes for certificate bundles (default: 330000)",
697+
"description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n gatewayAPI:\n enable: true\n # Feature gates as of v1.20.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ACMEHTTP01IngressPathTypeExact: true # BETA - default=true\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: true # BETA - default=true\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics\n # Configure PEM size limits for certificate validation\n # Useful for certificates with many DNS names (e.g., Istio gateways with 100+ DNS names)\n pemSizeLimitsConfig:\n maxCertificateSize: 36500 # Maximum size in bytes for individual certificates (default: 36500)\n maxPrivateKeySize: 13000 # Maximum size in bytes for private keys (default: 13000)\n maxChainLength: 95000 # Maximum size in bytes for certificate chains (default: 95000)\n maxBundleSize: 330000 # Maximum size in bytes for certificate bundles (default: 330000)\n # Configure certificate request backoff durations\n certificateRequestMinimumBackoffDuration: 1h\n certificateRequestMaximumBackoffDuration: 32h",
698698
"type": "object"
699699
},
700700
"helm-values.containerSecurityContext": {

‎deploy/charts/cert-manager/values.yaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ enableCertificateOwnerRef: false
327327
# maxPrivateKeySize: 13000 # Maximum size in bytes for private keys (default: 13000)
328328
# maxChainLength: 95000 # Maximum size in bytes for certificate chains (default: 95000)
329329
# maxBundleSize: 330000 # Maximum size in bytes for certificate bundles (default: 330000)
330+
# # Configure certificate request backoff durations
331+
# certificateRequestMinimumBackoffDuration: 1h
332+
# certificateRequestMaximumBackoffDuration: 32h
330333
config: {}
331334

332335
# Setting Nameservers for DNS01 Self Check.

‎internal/apis/config/controller/types.go‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,17 @@ type ControllerConfiguration struct {
149149
// GatewayAPIConfig configures the behaviour of the Gateway API integration
150150
GatewayAPIConfig GatewayAPIConfig
151151

152-
// CertificateRequestMinimumBackoffDuration configures the initial backoff duration
153-
// when a certificate request fails. This duration is exponentially increased (up to
154-
// a maximum of 32 hours) based on the number of consecutive failures and represents
155-
// the minimum backoff applied.
152+
// CertificateRequestMinimumBackoffDuration configures the minimum backoff duration
153+
// when a certificate request fails (default 1h). The backoff delay starts at
154+
// this value and is exponentially increased with each consecutive failure,
155+
// up to the configured maximum backoff duration.
156156
CertificateRequestMinimumBackoffDuration time.Duration
157+
158+
// CertificateRequestMaximumBackoffDuration configures the maximum backoff duration
159+
// when a certificate request fails. The backoff delay starts at
160+
// the minimum backoff duration and is exponentially increased with
161+
// each consecutive failure, but will never exceed this maximum (default 32h).
162+
CertificateRequestMaximumBackoffDuration time.Duration
157163
}
158164

159165
type LeaderElectionConfig struct {

‎internal/apis/config/controller/v1alpha1/defaults.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ var (
101101
defaultACMEHTTP01SolverNameservers = []string{}
102102

103103
defaultCertificateRequestMinimumBackoffDuration = 1 * time.Hour
104+
defaultCertificateRequestMaximumBackoffDuration = 32 * time.Hour
104105

105106
defaultAutoCertificateAnnotations = []string{"kubernetes.io/tls-acme"}
106107
defaultExtraCertificateAnnotations = []string{}
@@ -291,6 +292,10 @@ func SetDefaults_ControllerConfiguration(obj *v1alpha1.ControllerConfiguration)
291292
obj.CertificateRequestMinimumBackoffDuration = sharedv1alpha1.DurationFromTime(defaultCertificateRequestMinimumBackoffDuration)
292293
}
293294

295+
if obj.CertificateRequestMaximumBackoffDuration.IsZero() {
296+
obj.CertificateRequestMaximumBackoffDuration = sharedv1alpha1.DurationFromTime(defaultCertificateRequestMaximumBackoffDuration)
297+
}
298+
294299
logsapi.SetRecommendedLoggingConfiguration(&obj.Logging)
295300
}
296301

‎internal/apis/config/controller/v1alpha1/testdata/defaults.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,6 @@
7878
"enabled": false,
7979
"enableListenerSet": false
8080
},
81-
"certificateRequestMinimumBackoffDuration": "1h0m0s"
81+
"certificateRequestMinimumBackoffDuration": "1h0m0s",
82+
"certificateRequestMaximumBackoffDuration": "32h0m0s"
8283
}

‎internal/apis/config/controller/v1alpha1/zz_generated.conversion.go‎

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎internal/apis/config/controller/validation/validation.go‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"net"
2121
"net/url"
2222
"strings"
23+
"time"
2324

2425
"k8s.io/apimachinery/pkg/util/sets"
2526
"k8s.io/apimachinery/pkg/util/validation/field"
@@ -95,6 +96,8 @@ func ValidateControllerConfiguration(cfg *config.ControllerConfiguration, fldPat
9596

9697
allErrors = append(allErrors, validatePEMSizeLimitsConfig(&cfg.PEMSizeLimitsConfig, fldPath.Child("pemSizeLimitsConfig"))...)
9798

99+
allErrors = append(allErrors, validateCertificateRequestBackoffConfig(&cfg.CertificateRequestMinimumBackoffDuration, &cfg.CertificateRequestMaximumBackoffDuration, fldPath)...)
100+
98101
return allErrors
99102
}
100103

@@ -129,3 +132,38 @@ func validatePEMSizeLimitsConfig(cfg *config.PEMSizeLimitsConfig, fldPath *field
129132

130133
return allErrors
131134
}
135+
136+
func validateCertificateRequestBackoffConfig(minBackoff, maxBackoff *time.Duration, fldPath *field.Path) field.ErrorList {
137+
var allErrors field.ErrorList
138+
139+
// Validate minimum backoff. Negative values are rejected; zero is
140+
// handled by SetDefaults_ControllerConfiguration before validation runs.
141+
if *minBackoff < 0 {
142+
allErrors = append(allErrors, field.Invalid(
143+
fldPath.Child("certificateRequestMinimumBackoffDuration"),
144+
minBackoff.String(),
145+
"must not be negative",
146+
))
147+
}
148+
149+
// Validate maximum backoff. Negative values are rejected; zero is
150+
// handled by SetDefaults_ControllerConfiguration before validation runs.
151+
if *maxBackoff < 0 {
152+
allErrors = append(allErrors, field.Invalid(
153+
fldPath.Child("certificateRequestMaximumBackoffDuration"),
154+
maxBackoff.String(),
155+
"must not be negative",
156+
))
157+
}
158+
159+
// Validate max >= min (only if both are individually valid)
160+
if *minBackoff > 0 && *maxBackoff > 0 && *maxBackoff < *minBackoff {
161+
allErrors = append(allErrors, field.Invalid(
162+
fldPath.Child("certificateRequestMaximumBackoffDuration"),
163+
maxBackoff.String(),
164+
"must be greater than or equal to certificateRequestMinimumBackoffDuration",
165+
))
166+
}
167+
168+
return allErrors
169+
}

0 commit comments

Comments
 (0)