CKA — TLS Termination

4 minute read

CKA Exam Domain

Services & Networking — 20%

TLS termination at the Ingress layer is a common CKA exam task. You’ll be asked to create a TLS Secret, configure an Ingress to use it, and verify HTTPS is working. Know the commands and YAML by heart.

Creating TLS Secrets

Before configuring TLS on an Ingress, you need a Kubernetes Secret of type kubernetes.io/tls containing the certificate and private key.

Generate a Self-Signed Certificate

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt -subj "/CN=app.example.com"

This creates:

  • tls.key — the private key
  • tls.crt — the self-signed certificate valid for 365 days

Create the Secret

kubectl create secret tls app-tls --cert=tls.crt --key=tls.key

Verify:

kubectl get secret app-tls
kubectl describe secret app-tls

The Secret will have two data keys: tls.crt and tls.key.

Secret YAML (for reference)

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

Exam tip: Use the kubectl create secret tls command — it’s faster and less error-prone than writing YAML with base64-encoded values.

Configuring TLS in Ingress

Add the tls section to your Ingress spec to enable HTTPS:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com              # Must match a host in rules
    secretName: app-tls            # The TLS Secret we created
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-svc
            port:
              number: 80

Key points:

  • The tls[].hosts must match the host in the rules section
  • secretName references the TLS Secret
  • The certificate’s CN (Common Name) should match the hostname
  • You can have multiple tls entries for different hosts

Multiple Hosts with TLS

spec:
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  - hosts:
    - api.example.com
    secretName: api-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-svc
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 8080

TLS Flow

Understanding the traffic flow is important for both the exam and troubleshooting:

Client (HTTPS) → Ingress Controller → TLS Terminates Here → Service (HTTP) → Pod
  1. Client sends an HTTPS request to the Ingress Controller’s external IP
  2. Ingress Controller receives the encrypted traffic, uses the certificate from the TLS Secret to decrypt it
  3. TLS terminates at the controller — from here, traffic is plain HTTP
  4. Controller forwards the unencrypted request to the backend Service
  5. Service routes to the Pod

This means your backend applications don’t need to handle TLS themselves — the Ingress Controller takes care of it.

Certificate Management

For the CKA exam, you’ll use self-signed certificates or certificates provided in the question. In production, you’d typically use cert-manager for automated certificate management:

  • Automatically provisions certificates from Let’s Encrypt or other CAs
  • Handles certificate renewal before expiry
  • Integrates with Ingress via annotations
# Production example (not needed for CKA, but good to know)
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod

For the exam: Stick to openssl + kubectl create secret tls. That’s all you need.

Redirect HTTP to HTTPS

By default, the NGINX Ingress Controller redirects HTTP to HTTPS when TLS is configured. You can control this behavior with annotations:

# Force HTTPS redirect (default when TLS is configured)
nginx.ingress.kubernetes.io/ssl-redirect: "true"

# Disable HTTPS redirect (serve both HTTP and HTTPS)
nginx.ingress.kubernetes.io/ssl-redirect: "false"

# Force SSL using a 308 redirect
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

Exam tip: If the question says “configure HTTPS” but doesn’t mention redirects, adding ssl-redirect: "true" is a safe default.

Verifying TLS

After configuring TLS, verify it’s working:

# Test HTTPS connection (-v for verbose, -k to skip cert verification for self-signed)
curl -vk https://app.example.com

# Check Ingress TLS configuration
kubectl describe ingress app-ingress | grep -i tls

# Verify the Secret exists and has the right type
kubectl get secret app-tls -o yaml

# Check certificate details
openssl x509 -in tls.crt -text -noout | head -20

# Test from inside the cluster
kubectl run curl-test --image=curlimages/curl --rm -it -- \
  curl -vk https://app.example.com

Expected output from kubectl describe ingress:

TLS:
  app-tls terminates app.example.com

If you see TLS: <none>, the TLS configuration isn’t applied correctly — check the Secret name and host matching.

Practice Questions

Q1. Create a TLS Secret named web-tls from certificate file web.crt and key file web.key.

Show Answer
kubectl create secret tls web-tls --cert=web.crt --key=web.key

Verify: kubectl get secret web-tls — it should show type kubernetes.io/tls.

Q2. Write an Ingress resource that terminates TLS for shop.example.com using Secret shop-tls, routing all traffic to shop-svc on port 80.

Show Answer
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - shop.example.com
    secretName: shop-tls
  rules:
  - host: shop.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: shop-svc
            port:
              number: 80

Q3. Where does TLS terminate in a standard Ingress setup?

Show Answer

TLS terminates at the Ingress Controller. The controller decrypts the HTTPS traffic using the certificate from the TLS Secret, then forwards plain HTTP to the backend Service. This means backend Pods receive unencrypted traffic.

Q4. How do you generate a self-signed certificate for api.example.com and create the corresponding Secret?

Show Answer
# Generate the certificate and key
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt -subj "/CN=api.example.com"

# Create the Kubernetes Secret
kubectl create secret tls api-tls --cert=tls.crt --key=tls.key

Q5. An Ingress has TLS configured but kubectl describe ingress shows TLS: <none>. What could be wrong?

Show Answer

Common causes:

  1. Secret doesn’t exist — check kubectl get secret <secret-name> in the same namespace
  2. Secret name mismatch — the secretName in the Ingress doesn’t match the actual Secret
  3. Wrong namespace — the Secret must be in the same namespace as the Ingress
  4. Secret type is wrong — must be kubernetes.io/tls, not Opaque
  5. Host mismatch — the hosts under tls doesn’t match any host in rules

Updated: