Amazon EKS — TLS and ACM Integration

1 minute read

AWS Certificate Manager (ACM) provides free, auto-renewing TLS certificates. On EKS, you terminate TLS at the load balancer (ALB or NLB) using ACM certificates.


Provision an ACM Certificate

aws acm request-certificate \
  --domain-name "*.example.com" \
  --subject-alternative-names "example.com" \
  --validation-method DNS \
  --region us-east-1

Validate the certificate via DNS (add the CNAME record to Route 53):

aws acm describe-certificate --certificate-arn arn:aws:acm:us-east-1:123456789:certificate/abc-123 \
  --query "Certificate.DomainValidationOptions[0].ResourceRecord"

TLS on ALB (Ingress)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  namespace: production
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-east-1:123456789:certificate/abc-123"
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    alb.ingress.kubernetes.io/ssl-policy: "ELBSecurityPolicy-TLS13-1-2-2021-06"
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type":"redirect","RedirectConfig":{"Protocol":"HTTPS","Port":"443","StatusCode":"HTTP_301"}}'
spec:
  ingressClassName: alb
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-app
                port:
                  number: 80

HTTP to HTTPS Redirect

Add both HTTP and HTTPS listeners, then redirect HTTP:

annotations:
  alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]'
  alb.ingress.kubernetes.io/ssl-redirect: "443"
  alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-east-1:123456789:certificate/abc-123"

TLS on NLB (Service)

apiVersion: v1
kind: Service
metadata:
  name: secure-api
  namespace: production
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "external"
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
    service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-east-1:123456789:certificate/abc-123"
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
    service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: "ELBSecurityPolicy-TLS13-1-2-2021-06"
spec:
  type: LoadBalancer
  selector:
    app: api
  ports:
    - name: https
      port: 443
      targetPort: 8080
      protocol: TCP

SSL Policies

Policy TLS Versions Use Case
ELBSecurityPolicy-TLS13-1-2-2021-06 TLS 1.2 + 1.3 Modern browsers
ELBSecurityPolicy-TLS-1-2-2017-01 TLS 1.2 only PCI compliance
ELBSecurityPolicy-TLS13-1-3-2021-06 TLS 1.3 only Maximum security
ELBSecurityPolicy-2016-08 TLS 1.0+ Legacy clients (not recommended)

End-to-End Encryption

For compliance requirements, encrypt traffic all the way to the pod:

Client → HTTPS → ALB → HTTPS → Pod
annotations:
  alb.ingress.kubernetes.io/backend-protocol: "HTTPS"
  alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:..."

Your pods must serve HTTPS on their target port. Use cert-manager or mounted certificates.


cert-manager as Alternative

For certificates inside the cluster (pod-level TLS):

helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager --create-namespace \
  --set crds.enabled=true
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - dns01:
          route53:
            region: us-east-1

Recommendation: Use ACM for load balancer TLS (free, auto-renewing). Use cert-manager only when you need pod-level certificates (mTLS, service mesh).


Best Practices

  1. Use ACM for ALB/NLB TLS — free, automatic renewal, no manual certificate management
  2. Enforce HTTPS with HTTP→HTTPS redirect
  3. Use TLS 1.2+ policies — disable older protocols
  4. Use wildcard certificates for multi-service domains
  5. End-to-end encryption only when compliance requires it — adds complexity and CPU overhead

Updated: