Documentation navigation
Certificate Renewal Stuck
Runbook for a cert-manager Certificate whose scheduled renewal is overdue, the early signal that renewal is failing. This fires before 09-certificate-expiring-soon.md (the expiry alert) — the existing cert may still be Ready and valid, so the expiry alert will not fire yet. This alert catches the renewal failure early, while there is still lead time.
Meaning
cert-manager schedules a renewal at ~2/3 of a cert's lifetime (a 90-day cert starts renewing at ~60 days). certmanager_certificate_renewal_timestamp_seconds is the renewalTime from the Certificate status — the moment cert-manager will attempt to renew. When that timestamp is in the past and the Certificate has not transitioned to Ready=True with a new Not After, the renewal is stuck.
The one-zero sentinel: like the expiry metric, cert-manager exports renewal_timestamp_seconds = 0 for a Certificate with no issued Secret (first issuance in flight, or permanent failure — a zombie resource). Unguarded this read as "renewal overdue by ~20,700 days", which held both runbook certificate alerts permanently firing on 4 never-issued resources (2026-10-16 investigation). The expr filters > 0 before comparing: this alert now covers only certificates that have a real cert whose renewal is overdue; the no-secret state is 07-kubernetes/18-certificate-never-issued.md.
The alert fires when (renewal_time - now) / 24 / 3600 < 0 for 1h — i.e. the scheduled renewal time has been in the past for at least 1h. The 1h window rides out a healthy renewal (which completes in minutes). A renewal stuck for 1h+ means the renewal is actively failing, not just in progress.
Because the existing cert is still valid (the renewal hasn't broken it yet), 09-certificate-expiring-soon.md does not fire — this is the only signal at this stage. If the renewal stays stuck and the cert eventually nears expiry, the expiry alert fires too.
Impact
- The renewal has failed for 1h+ but the existing cert is still valid — there is lead time. If the renewal does not complete before the cert expires, the endpoint becomes unreachable (TLS handshake failure). See
09-certificate-expiring-soon.md§ Impact for the full outage scenarios. - cert-manager webhooks — a stuck renewal on a webhook cert can cascade into cert-manager itself being unable to issue any certs. This is the most dangerous case.
Diagnosis
The alert labels carry k8s_cluster_name, exported_namespace (the Certificate's namespace — the scraped namespace label always reads cert-manager, the controller pod's namespace), name (the Certificate CR name), issuer_name, environment.
1. Confirm the Certificate's status and renewal time
export KUBECONFIG=~/.kube/<cluster>.yaml # e.g. prd-par01.yaml
NS=<exported_namespace>
CERT=<name>
kubectl -n $NS get certificate $CERT -o wide
kubectl -n $NS describe certificate $CERT | sed -n '/^Status:/,$p'
The Ready condition tells you the state:
Ready=True— the cert is valid. If the renewal is stuck, the status showsIssuingor therenewalTimeis past without a new cert. Check the Order/Challenge (step 2).Ready=False / Issuing— cert-manager is actively trying to renew. If this has beenIssuingfor 1h+, the renewal is stuck at the Order/Challenge stage.Ready=False / Failed— the renewal failed. Thereasonandmessagetell you why.
2. Check the Order and Challenge
See 07-kubernetes/09-certificate-expiring-soon.md § Diagnosis step 2 for the full ACME Order/Challenge diagnosis (HTTP-01 self-check, DNS-01, rate limits, wrong issuer). The same failures apply here — the renewal is stuck because the ACME challenge is failing.
3. Check cert-manager controller health
See 07-kubernetes/09-certificate-expiring-soon.md § Diagnosis step 3.
Mitigation
Step 1 — Activate PIM
Activate the required Azure Privileged Identity Management roles before touching production (MultiTenantEuOnlyAccessPimRoles / DevOpsPimRoles / Platform Team (privileged)), as in 03-kafka/01-consumer-lag.md.
Step 2 — Fix the renewal blocker
See 07-kubernetes/09-certificate-expiring-soon.md § Mitigation step 2 (HTTP-01, DNS-01, rate limit, issuer, controller).
Step 3 — Force a renewal
Once the blocker is fixed, force cert-manager to retry immediately:
kubectl -n $NS certificate $CERT renew # triggers a renewal now
kubectl -n $NS get certificate $CERT -w # watch Ready flip to Issuing -> True
See 07-kubernetes/09-certificate-expiring-soon.md § Mitigation step 3.
Verify
- The alert clears once
(certmanager_certificate_renewal_timestamp_seconds - time()) / 24 / 3600 >= 0— i.e. the renewal time is in the future again (a new cert was issued with a new renewal time), sustained for thefor: 1hwindow. Note the 1hfor: the alert takes up to 1h to clear after the renewal completes. kubectl -n $NS get certificate $CERTshowsReady=Trueand a newNot After/renewalTimein the future.kubectl -n $NS get ordersshows the most recent OrderValid/Ready=True.
Notes
- Early signal — fires BEFORE
07-kubernetes/09-certificate-expiring-soon.md(the expiry alert). The existing cert is still valid; this catches the renewal failure with lead time. - 1h
forwindow — rides out a healthy renewal (minutes). A renewal stuck for 1h+ is actively failing. - Same diagnosis/mitigation as
07-kubernetes/09-certificate-expiring-soon.md— the root causes (ACME challenge, rate limit, issuer, controller) are identical; only the signal timing differs. > 0guard (2026-10-16) — added after this alert fired permanently on never-issued certificates (renewal = 0 read as "overdue by ~20,700 days"). Certificates with no issued secret now alert via07-kubernetes/18-certificate-never-issued.mdinstead.- Related —
07-kubernetes/09-certificate-expiring-soon.md(the expiry alert) and07-kubernetes/18-certificate-never-issued.md(no issued secret), samekubernetes.securitygroup.