How Does TLS Termination Work with Ingress?

intermediate|ingressdevopssrebackend developerCKACKAD
TL;DR

TLS termination in Ingress decrypts HTTPS traffic at the Ingress controller, forwarding plain HTTP to backend Services. You store TLS certificates in Kubernetes Secrets and reference them in the Ingress spec. Most setups use cert-manager to automate certificate issuance from Let's Encrypt.

Detailed Answer

TLS termination at the Ingress layer is the standard approach for serving HTTPS in Kubernetes. The Ingress controller decrypts incoming TLS connections and forwards plain HTTP traffic to backend Services.

Setting Up TLS

Step 1: Create a TLS Secret

Store the certificate and private key in a Kubernetes Secret:

kubectl create secret tls app-tls-secret \
  --cert=fullchain.pem \
  --key=privkey.pem

Or declaratively:

apiVersion: v1
kind: Secret
metadata:
  name: app-tls-secret
type: kubernetes.io/tls
data:
  tls.crt: <base64-encoded-certificate>
  tls.key: <base64-encoded-private-key>

Step 2: Reference the Secret in the Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-app
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
        - api.example.com
      secretName: app-tls-secret
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80

Automating with cert-manager

Manually managing certificates is error-prone. cert-manager automates the entire lifecycle:

# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml

Create a 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: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
      - http01:
          ingress:
            class: nginx

Then annotate the Ingress for automatic certificate management:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-app
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  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: web-service
                port:
                  number: 80

cert-manager automatically:

  1. Requests a certificate from Let's Encrypt
  2. Completes the HTTP-01 challenge
  3. Creates the app-tls-auto Secret with the certificate
  4. Renews the certificate before expiry (default: 30 days before)

TLS Passthrough

For applications that need end-to-end encryption (e.g., mutual TLS), use TLS passthrough:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: passthrough-app
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  rules:
    - host: secure.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: secure-service
                port:
                  number: 443

With passthrough, the Ingress controller forwards the raw TLS connection to the backend without decryption.

Multiple Certificates

Use separate TLS entries for different domains:

spec:
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls
    - hosts:
        - api.partner.com
      secretName: partner-tls

The Ingress controller uses Server Name Indication (SNI) to select the correct certificate based on the requested hostname.

Forcing HTTPS Redirect

Redirect HTTP to HTTPS to ensure all traffic is encrypted:

metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

This returns a 308 redirect for any HTTP request, sending clients to the HTTPS version of the URL.

Why Interviewers Ask This

Interviewers ask this to confirm you understand how HTTPS is handled in Kubernetes and can configure secure external access to applications.

Common Follow-Up Questions

What is the difference between TLS termination and TLS passthrough?
TLS termination decrypts at the Ingress controller. TLS passthrough forwards encrypted traffic directly to the backend Pod, which handles decryption. Passthrough is used when the backend must see the original TLS connection.
How does cert-manager work with Ingress?
cert-manager watches Ingress resources for TLS annotations, automatically requests certificates from a CA (like Let's Encrypt), stores them in Secrets, and handles renewal.
Can you use different certificates for different hosts?
Yes, the tls section supports multiple entries, each with its own hosts list and secretName. The Ingress controller selects the correct certificate based on SNI.

Key Takeaways

  • TLS certificates are stored as Kubernetes Secrets of type kubernetes.io/tls.
  • The Ingress controller handles decryption, so backend Services receive plain HTTP.
  • cert-manager automates certificate lifecycle including issuance and renewal.

Related Questions

You Might Also Like