QCecuring - Enterprise Security Solutions

What is cert-manager

Shivam Sharma

Key Takeaways

  • cert-manager is a Kubernetes controller that automates certificate lifecycle: request, issue, store as Secret, and renew before expiry
  • Supports multiple issuers: Let's Encrypt (ACME), HashiCorp Vault, AWS PCA, Venafi, self-signed, and private CAs
  • Certificates are declared as Kubernetes resources — cert-manager handles the rest (challenges, CSR, renewal, Secret updates)
  • Renewal happens at 2/3 of certificate lifetime by default — but failures are silent unless you monitor cert-manager events

cert-manager is a Kubernetes-native certificate management controller that automates the issuance and renewal of TLS certificates. You declare a Certificate resource specifying what you need (domain names, issuer, key algorithm), and cert-manager handles everything: generating the private key, creating the CSR, completing ACME challenges (or calling the CA API), storing the certificate as a Kubernetes Secret, and renewing it before expiry. It turns certificate management from an operational task into a declarative configuration.


Why it matters

  • Declarative certificates — define what certificate you need in YAML. cert-manager ensures it exists, is valid, and stays renewed. No scripts, no cron jobs, no manual intervention.
  • Multi-issuer support — one cluster can use Let’s Encrypt for public certs, HashiCorp Vault for internal certs, and AWS PCA for service mesh certs — all through the same interface.
  • Automatic renewal — cert-manager renews certificates at 2/3 of their lifetime (configurable). For 90-day Let’s Encrypt certs, renewal happens at day 60 automatically.
  • Kubernetes-native — certificates are Custom Resources with status, events, and conditions. Standard K8s tooling (kubectl, monitoring, GitOps) works naturally.
  • Ingress integration — annotate an Ingress with cert-manager.io/cluster-issuer and cert-manager automatically provisions the certificate. Zero additional configuration per service.

How it works

  1. Install cert-manager — deploy the controller, webhook, and CRDs into the cluster
  2. Configure Issuer/ClusterIssuer — define how certificates are obtained (ACME server URL, CA credentials, Vault endpoint)
  3. Create Certificate resource — specify: secret name, DNS names, issuer reference, key algorithm, duration, renewal threshold
  4. cert-manager processes — creates a CertificateRequest, then an Order (for ACME), then Challenge resources
  5. Challenge solved — for ACME: cert-manager creates temporary pods/ingress rules for HTTP-01, or DNS records for DNS-01
  6. Certificate issued — cert-manager stores the certificate + key in the specified Kubernetes Secret
  7. Renewal loop — cert-manager watches certificate expiry and triggers renewal at the configured threshold

In real systems

ClusterIssuer for Let’s Encrypt:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: ops@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
    - http01:
        ingress:
          class: nginx
    - dns01:
        cloudDNS:
          project: my-gcp-project
      selector:
        dnsNames:
        - "*.example.com"

Certificate resource:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: api-tls
  namespace: production
spec:
  secretName: api-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - api.example.com
  - api-v2.example.com
  privateKey:
    algorithm: ECDSA
    size: 256
  duration: 2160h    # 90 days
  renewBefore: 720h  # Renew 30 days before expiry

Ingress annotation (automatic provisioning):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls-auto  # cert-manager creates this Secret
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app
            port:
              number: 80

Checking certificate status:

kubectl get certificates -A
# NAME      READY   SECRET          AGE
# api-tls   True    api-tls-secret  5d

kubectl describe certificate api-tls -n production
# Shows: conditions, events, renewal time, last issuance

Where it breaks

DNS-01 challenge permissions — cert-manager needs API access to create DNS TXT records for DNS-01 challenges. If the service account credentials are wrong, expired, or lack the right IAM permissions, challenges fail silently. The Certificate resource shows Ready: False with a cryptic event like “error presenting challenge.” Check cert-manager pod logs and the Challenge resource status for the actual error.

Rate limits exhausted — a misconfiguration causes cert-manager to repeatedly request certificates (e.g., invalid DNS name that always fails validation, triggering retries). Let’s Encrypt rate limits are hit (50 certs/domain/week). All certificate issuance for that domain is blocked for a week. Use the staging issuer (acme-staging-v02) for testing and monitor cert-manager’s failed order count.

Renewal succeeds but ingress doesn’t reload — cert-manager updates the Secret with the new certificate. Most ingress controllers (nginx-ingress, Traefik) watch Secrets and hot-reload. But some older versions or custom controllers don’t. The Secret has the new cert, but the ingress still serves the old one from memory. Verify by checking the actual served certificate: openssl s_client -connect endpoint:443.


Operational insight

cert-manager’s biggest operational gap is observability. By default, certificate renewal failures are only visible as Kubernetes events (which expire after 1 hour) and conditions on the Certificate resource. If nobody is watching, a certificate can fail to renew for days before anyone notices — and by then it may have expired. Set up Prometheus monitoring with cert-manager’s built-in metrics: certmanager_certificate_ready_status, certmanager_certificate_expiration_timestamp_seconds, and certmanager_certificate_renewal_timestamp_seconds. Alert when any certificate has Ready != True for more than 1 hour, or when expiry is less than 7 days away. Without this monitoring, cert-manager gives you a false sense of security.


Ready to Secure Your Enterprise?

Experience how our cryptographic solutions simplify, centralize, and automate identity management for your entire organization.

Stay ahead on cryptography & PKI

Get monthly insights on certificate management, post-quantum readiness, and enterprise security. No spam.

We respect your privacy. Unsubscribe anytime.