Kubernetes TLS Termination & Managing Certificates Lab

The Manual Approach: Using Kubernetes Secrets

Before automating, it’s crucial to understand how Kubernetes handles certificates natively. Kubernetes stores TLS certificates as a specific type of Secret (kubernetes.io/tls).

Step 1: Create the TLS Secret

If you already have a certificate (tls.crt) and a private key (tls.key), you can store them in your cluster using kubectl:

kubectl create secret tls my-website-tls \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key \
  -n my-namespace

Step 2: Configure the Ingress Resource

Once the secret exists, you reference it in your Ingress manifest under the tls section:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-website-ingress
  namespace: my-namespace
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - www.mywebsite.com
    secretName: my-website-tls # Matches the secret created above
  rules:
  - host: www.mywebsite.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-website-service
            port:
              number: 80

The Automated Approach: Mastering cert-manager

To truly master certificate management in Kubernetes, you must automate it. cert-manager is the industry-standard Kubernetes add-on that automates the issuance and renewal of TLS certificates.

Core Components of cert-manager

  • Issuer / ClusterIssuer: Resources that represent certificate authorities (CAs) like Let’s Encrypt. An Issuer is scoped to a single namespace, while a ClusterIssuer works across the entire cluster.
  • Certificate: A resource that requests a certificate from an Issuer and ensures it is kept up to date.
  • CertificateRequest: Used internally by cert-manager to request the actual signed certificate.

Step 1: Install cert-manager

The easiest way to install it is via Helm:

Bash

helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

Step 2: Create a Let’s Encrypt ClusterIssuer

We’ll use Let’s Encrypt with an HTTP-01 challenge. This tells Let’s Encrypt to verify your domain ownership by placing a specific file on your web server.

YAML

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: admin@mywebsite.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod-account-key
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx

Step 3: Automate the Ingress

Now, simply add an annotation to your Ingress resource. cert-manager will automatically detect it, talk to Let’s Encrypt, complete the challenge, create the secret, and keep it renewed!

YAML

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-website-ingress
  namespace: my-namespace
  annotations:
    # This triggers cert-manager to use our ClusterIssuer
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - www.mywebsite.com
    secretName: my-website-tls-auto # cert-manager creates this secret for you
  rules:
  - host: www.mywebsite.com
    http:
      # ... backend service config ...

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top