CKSKubernetes 1.35

Lessons

Ingress with TLS termination

updated 2026-10-22 by seed

The three objects

# 1. a key and a certificate (self-signed is fine unless the task provides a CA)
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
  -keyout /tmp/tls.key -out /tmp/tls.crt \
  -subj "/CN=shop.example.com/O=lab"

# 2. a TLS-typed Secret — the type matters, `kubectl create secret tls` sets it
kubectl create secret tls shop-tls --cert=/tmp/tls.crt --key=/tmp/tls.key -n shop
# 3. the Ingress: host, backend, and the secret that terminates TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
  namespace: shop
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
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
            port: {number: 80}

Prove it

kubectl get ingress -n shop
kubectl describe ingress -n shop shop    # the TLS column must show the secret

# talk to the ingress controller directly, bypassing DNS
curl -vk --resolve shop.example.com:443:$(kubectl get svc -n ingress-nginx ingress-nginx-controller \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}') https://shop.example.com/

Look for SSL certificate verify ok and a HTTP/1.1 200. A 404 means the
Ingress matched but the backend Service or port is wrong; a 503 means the Service
has no ready endpoints.

Details that are worth marks

  • secretName, not secret. A typo here silently gives you the default self-signed certificate and the task fails on the certificate check.
  • ingressClassName — without it the Ingress sits there doing nothing on a cluster with more than one controller.
  • The secret must live in the same namespace as the Ingress.
  • pathType is required in networking.k8s.io/v1. Prefix unless the task says Exact.
  • A certificate with the wrong CN/SAN still "works" but fails a verify check. Match the host in the task exactly.
  • If the controller is not installed, the task cannot be about terminating traffic — it is about the objects. Create them and show describe.

Faster: imperative form

kubectl create ingress shop --class=nginx \
  --rule="shop.example.com/*=shop:80,tls=shop-tls" -n shop

Worth knowing because it is 40 seconds instead of two minutes, and you can then
kubectl get ingress -o yaml to check what it produced.