Automate TLS certificates with cert-manager

Deployment Platform
Related Documentation
TL;DR

Annotate your Gateway with cert-manager.io/issuer and reference the resulting Secret in your Gateway listeners.

Integrating Kong Operator with cert-manager allows you to automatically provision and rotate TLS certificates for your Gateway listeners. This integration follows the standard Kubernetes Gateway API pattern.

When you annotate a Gateway resource with a cert-manager issuer, cert-manager automatically creates a Certificate and a corresponding Secret containing the TLS key pair. The Operator then configures the managed Data Planes to use this secret for TLS termination.

Create the kong namespace

Create the kong namespace in your Kubernetes cluster, which is where the demo will run:

kubectl create namespace kong

Install Kong Operator with cert-manager enabled

  1. Add the Kong Helm charts:

    helm repo add kong https://charts.konghq.com
    helm repo update
    
  2. Install cert-manager on your cluster:

    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.2/cert-manager.yaml
    
  3. Install Kong Operator using Helm:

    helm upgrade --install kong-operator kong/kong-operator -n kong-system \
      --create-namespace \
      --set image.tag=2.1.0 \
      --set global.webhooks.options.certManager.enabled=true
    
    helm upgrade --install kong-operator kong/kong-operator -n kong-system \
      --create-namespace \
      --set image.tag=2.1.0 \
      --set global.webhooks.options.certManager.enabled=true \
      --set env.ENABLE_CONTROLLER_KONNECT=true
    

Create a cert-manager issuer

The cert-manager Issuer resource represents a certificate authority. For more information, see the cert-manager documentation.

echo '
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
  namespace: kong
spec:
  selfSigned: {}' | kubectl apply -f -

In this example, we’re using a simple self-signed issuer. In a production environment, you would typically use an ACME issuer like Let’s Encrypt, or a CA issuer.

Configure the Gateway with cert-manager

Create the following resources:

  • A GatewayConfiguration and a GatewayClass to configure your gateway with the latest Kong Gateway version and Kong Operator as the controller.
  • A Gateway with the cert-manager.io/issuer: "selfsigned-issuer" annotation and the tls.certificateRefs pointing to the name of the Secret to provision.
  • A Certificate that references the cert-manager issuer and the provisioned Secret.
echo '
apiVersion: gateway-operator.konghq.com/v2beta1
kind: GatewayConfiguration
metadata:
  name: kong-gateway-configuration
  namespace: kong
spec:
  dataPlaneOptions:
    deployment:
      podTemplateSpec:
        spec:
          containers:
            - image: kong/kong-gateway:3.13
              name: proxy
---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: kong-cert-manager
spec:
  controllerName: konghq.com/gateway-operator
  parametersRef:
    group: gateway-operator.konghq.com
    kind: GatewayConfiguration
    name: kong-gateway-configuration
    namespace: kong
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: kong-gateway
  namespace: kong
  annotations:
    cert-manager.io/issuer: "selfsigned-issuer"
spec:
  gatewayClassName: kong-cert-manager
  listeners:
    - name: https
      port: 443
      protocol: HTTPS
      hostname: example.localdomain.dev
      tls:
        mode: Terminate
        certificateRefs:
          - group: ""
            kind: Secret
            name: example-tls-secret
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-tls-certificate
  namespace: kong
spec:
  secretName: example-tls-secret
  issuerRef:
    name: selfsigned-issuer
    kind: Issuer
  dnsNames:
    - example.localdomain.dev
  secretTemplate:
    labels:
      konghq.com/secret: "true"' | kubectl apply -f -

Create an echo Service

Run the following command to create a sample echo Service:

kubectl apply -f https://developer.konghq.com/manifests/kic/echo-service.yaml -n kong

Create a Route

Deploy a sample HTTPRoute to verify that TLS termination is working:

echo '
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: echo-route
  namespace: kong
spec:
  parentRefs:
    - name: kong-gateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /echo
      backendRefs:
        - name: echo
          kind: Service
          port: 1027' | kubectl apply -f -

Validate

  1. Check that cert-manager has created the Certificate resource and that the Secret has been provisioned:

    kubectl get certificate -n kong
    kubectl get secret example-tls-secret -n kong
    
  2. Get the Gateway’s external IP:

    export PROXY_IP=$(kubectl get gateway kong-gateway -n kong -o jsonpath='{.status.addresses[0].value}')
    
  3. Test the connection:

    curl -ivk --resolve example.localdomain.dev:443:$PROXY_IP https://example.localdomain.dev/echo
    

    You should get TLS handshake and a 200 response.

Something wrong?

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!