TLS termination

By default, NGINX Ingress Controller generates default TLS certificates for TLS termination. You can, though, generate and configure your own TLS certificates for TLS termination purposes.

Note

Prior to setting up TLS termination, verify that you have correctly configured kubectl.

  1. Generate a self-signed certificate and a private key for the TLS connection.

    Note

    The Common Name (CN) in the certificate must match the host name of the server.

    mkdir -p example_certs
    
    openssl req \
    -new \
    -newkey rsa:2048 \
    -x509 \
    -sha256 \
    -days 365 \
    -nodes \
    -subj "/O=echo/CN=echo.example.com" \
    -keyout example_certs/echo.example.com.key \
    -out example_certs/echo.example.com.crt
    
  2. Create a Kubernetes Secret that contains the generated certificate:

    kubectl create secret tls echo-tls-secret --key example_certs/echo.example.com.key --cert example_certs/echo.example.com.crt
    
  3. Deploy a sample application:

    cat <<EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-svc
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: echo-svc
      template:
        metadata:
          labels:
            app: echo-svc
        spec:
          containers:
          - name: echo-svc
            image: registry.k8s.io/e2e-test-images/echoserver:2.3
            ports:
            - containerPort: 8080
            env:
              - name: NODE_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: spec.nodeName
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: POD_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              - name: POD_IP
                valueFrom:
                  fieldRef:
                    fieldPath: status.podIP
    
    ---
    
    apiVersion: v1
    kind: Service
    metadata:
      name: echo-svc
      labels:
        app: echo-svc
    spec:
      ports:
      - port: 80
        targetPort: 8080
        protocol: TCP
        name: http
      selector:
        app: echo-svc
    EOF
    
  4. Deploy the Ingress.

    Create an Ingress for the sample application, inserting the Kubernets Secret you created in the tls section as the host for which the TLS connection will terminate:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: echo-test
    spec:
      tls:
        - hosts:
          - echo.example.com
          secretName: echo-tls-secret
      ingressClassName: nginx-default
      rules:
        - host: echo.example.com
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: echo-svc
                    port:
                      number: 80
    EOF
    
  5. Test the TLS termination by connecting to the application using HTTPS.

    export MKE_HOST=<mke host>
    export NODE_PORT=33001
    
    curl -k -v --resolve "echo.example.com:$NODE_PORT:$MKE_HOST"
    "https://echo.example.com:$NODE_PORT"
    
    Example output:
    
    * Added echo.example.com:33001:54.218.145.62 to DNS cache
    * Hostname echo.example.com was found in DNS cache
    *   Trying 54.218.145.62:33001...
    * Connected to echo.example.com (54.218.145.62) port 33001 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *  CAfile: /etc/ssl/cert.pem
    *  CApath: none
    * (304) (OUT), TLS handshake, Client hello (1):
    * (304) (IN), TLS handshake, Server hello (2):
    * (304) (IN), TLS handshake, Unknown (8):
    * (304) (IN), TLS handshake, Certificate (11):
    * (304) (IN), TLS handshake, CERT verify (15):
    * (304) (IN), TLS handshake, Finished (20):
    * (304) (OUT), TLS handshake, Finished (20):
    * SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=echo; CN=echo.example.com
    *  start date: Nov 29 19:58:22 2022 GMT
    *  expire date: Nov 29 19:58:22 2023 GMT
    *  issuer: O=echo; CN=echo.example.com
    *  SSL certificate verify result: self signed certificate (18), continuing anyway.
    
    ...
    

    The output shows that the TLS connection is being negotiated using the provided certficate.

  6. Clean up Kubernetes resources that are no longer needed:

    kubectl delete ingress echo-test
    kubectl delete service echo-svc
    kubectl delete deployment echo-svc
    kubectl delete secret echo-tls-secret