diff --git a/kube/certs/certs.go b/kube/certs/certs.go index 551b9178f..e76d6e188 100644 --- a/kube/certs/certs.go +++ b/kube/certs/certs.go @@ -94,6 +94,16 @@ func (cm *CertManager) EnsureCertLoops(ctx context.Context, sc *ipn.ServeConfig) return nil } +// retrySchedule is the wait between successive failed issuance attempts, +// following LE's recommended schedule. +// https://letsencrypt.org/docs/integration-guide/#retrying-failures +var retrySchedule = []time.Duration{ + 1 * time.Minute, + 10 * time.Minute, + 100 * time.Minute, + 24 * time.Hour, +} + // runCertLoop: // - calls localAPI certificate endpoint to ensure that certs are issued for the // given domain name @@ -103,13 +113,8 @@ func (cm *CertManager) EnsureCertLoops(ctx context.Context, sc *ipn.ServeConfig) // Note that renewal check also happens when the node receives an HTTPS request and it is possible that certs get // renewed at that point. Renewal here is needed to prevent the shared certs from expiry in edge cases where the 'write' // replica does not get any HTTPS requests. -// https://letsencrypt.org/docs/integration-guide/#retrying-failures func (cm *CertManager) runCertLoop(ctx context.Context, domain string) { - const ( - normalInterval = 24 * time.Hour // regular renewal check - initialRetry = 1 * time.Minute // initial backoff after a failure - maxRetryInterval = 24 * time.Hour // max backoff period - ) + const normalInterval = 24 * time.Hour // regular renewal check if err := cm.waitForCertDomain(ctx, domain); err != nil { // Best-effort, log and continue with the issuing loop. @@ -153,15 +158,11 @@ func (cm *CertManager) runCertLoop(ctx context.Context, domain string) { nextInterval = normalInterval } else { retryCount++ - // Calculate backoff: initialRetry * 2^(retryCount-1) - // For retryCount=1: 1min * 2^0 = 1min - // For retryCount=2: 1min * 2^1 = 2min - // For retryCount=3: 1min * 2^2 = 4min - backoff := initialRetry * time.Duration(1<<(retryCount-1)) - if backoff > maxRetryInterval { - backoff = maxRetryInterval + idx := retryCount - 1 + if idx >= len(retrySchedule) { + idx = len(retrySchedule) - 1 } - nextInterval = backoff + nextInterval = retrySchedule[idx] cm.logf("Error refreshing certificate for %s (retry %d): %v. Will retry in %v\n", domain, retryCount, err, nextInterval) }