ACM doesn’t actually issue your EKS TLS certificates directly; cert-manager is the real workhorse, using ACM only to store the certificate secrets.

Let’s see cert-manager in action. Imagine you have a Kubernetes service my-app-service exposed via an Ingress my-app-ingress. You want a TLS certificate for myapp.example.com.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: myapp-tls
  namespace: default
spec:
  secretName: myapp-tls-secret # This is where the cert will be stored
  dnsNames:
  - myapp.example.com
  issuerRef:
    name: acme-http01-solver # Or acme-tls01-solver, or a Vault issuer, etc.
    kind: Issuer
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx" # Or your chosen ingress controller
    cert-manager.io/cluster-issuer: "letsencrypt-prod" # Reference to your Issuer object
spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls-secret # This secret will be populated by cert-manager
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80

When this Certificate resource is applied, cert-manager notices it. It then orchestrates a challenge with an ACME server (like Let’s Encrypt). For http01 challenges, it spins up a temporary pod that responds to HTTP requests on port 80 for myapp.example.com with a specific token. The Ingress controller routes the challenge request to this temporary pod. Once the ACME server verifies ownership, cert-manager retrieves the certificate and stores it in the myapp-tls-secret Kubernetes Secret. Your Ingress then uses this secret for TLS termination.

The problem cert-manager solves is the manual, error-prone process of obtaining, renewing, and distributing TLS certificates. Before cert-manager, you’d manually generate a CSR, send it to a CA, download the certificate, and then manually update your Ingress or LoadBalancer. This was a pain point, especially for dynamic environments where services and domains change frequently. Cert-manager automates this entire lifecycle.

Internally, cert-manager operates as a controller. It watches for Certificate resources. For each Certificate, it creates Order and Challenge resources. These resources represent the steps in the ACME protocol. The Challenge resource is what actually interacts with your Ingress controller or a dedicated solver pod to prove domain ownership. Once the challenges are satisfied, the Order resource transitions to a "ready" state, and cert-manager then requests the final certificate from the ACME server, storing it in the specified secretName. It also has built-in renewal logic, periodically checking if certificates are nearing expiration and initiating the renewal process.

The exact levers you control are primarily within the Issuer or ClusterIssuer resource and the Certificate resource itself. The Issuer defines how cert-manager will obtain certificates (e.g., using Let’s Encrypt staging or production ACME endpoints, or integrating with other CAs like HashiCorp Vault). The Certificate resource specifies what you want: the domain names (dnsNames), the Kubernetes Secret to store the certificate in (secretName), and which Issuer to use. You can also configure ACME challenge types (http01, tls01) and even use specialized solvers for environments where direct HTTP/TLS access to pods is tricky.

The one thing most people don’t realize is that cert-manager doesn’t need an Ingress resource to exist to create a certificate. It can create the secretName secret for any purpose, and your Ingress or other controllers can simply reference it. This means you can pre-provision certificates for services that aren’t even running yet, or use them for things like internal-only services that don’t have an Ingress but still need TLS. The Certificate resource is the core driver, and the Ingress is just one consumer of the resulting secret.

The next concept you’ll likely explore is how to manage certificates across multiple clusters or namespaces using ClusterIssuer resources and how to handle different ACME challenge types effectively.

Want structured learning?

Take the full Eks course →