How to restart Kong Gateway on Kubernetes

Uses: Kong Gateway
TL;DR

Run kubectl rollout restart on the Deployment, so the new configuration comes from the manifest and survives a reschedule.

Prerequisites

You need a running Kubernetes cluster with kubectl configured to point at it. Any cluster works, whether it runs locally or in a cloud provider.

If you don’t have one, create a local cluster with minikube:

minikube start -p kong-demo

You will need Helm, a package manager for Kubernetes.

Deploy a standalone DB-less Kong Gateway data plane into the kong namespace. The rest of this guide uses the kong-dp release and the values-dp.yaml file created here.

  1. Add the Kong Helm charts:

    helm repo add kong https://charts.konghq.com
    helm repo update
  2. Create the kong namespace:

    kubectl create namespace kong --dry-run=client -o yaml | kubectl apply -f -
  3. Create a file named license.json containing your Kong Gateway Enterprise license and store it in a Kubernetes secret:

    kubectl create secret generic kong-enterprise-license --from-file=license=./license.json -n kong
  4. Create a values-dp.yaml file:

    cat <<EOF > values-dp.yaml
    # Do not use Kong Ingress Controller
    ingressController:
      enabled: false
    
    image:
      repository: kong/kong-gateway
      tag: "3.15"
    
    env:
      # Run without a database
      database: "off"
      LICENSE_DATA:
        valueFrom:
          secretKeyRef:
            name: kong-enterprise-license
            key: license
    
    # In DB-less mode, Kong Gateway only reports itself ready once it has
    # built a router, which requires at least one Route in the declarative config.
    dblessConfig:
      config: |
        _format_version: "3.0"
        services:
          - name: example
            url: http://example.internal
            routes:
              - name: example-route
                paths:
                  - /example
    
    # The data plane handles proxy traffic only
    proxy:
      enabled: true
      # This guide reaches the proxy with kubectl port-forward, so it doesn't
      # need an external address
      type: ClusterIP
    
    admin:
      enabled: false
    
    manager:
      enabled: false
    EOF
  5. Install the release and wait for it to become ready:

    helm upgrade --install kong-dp kong/kong -n kong --values ./values-dp.yaml --wait
  6. Confirm that the data plane is running:

    kubectl get pods -n kong -l app.kubernetes.io/instance=kong-dp

    You should see one pod with a Running status:

    NAME                            READY   STATUS    RESTARTS   AGE
    kong-dp-kong-7cfbc49585-2v4qr   1/1     Running   0          45s

kong.conf values are rendered into the NGINX configuration when a node boots, so Kong Gateway has to be restarted before it picks up a change to one of them. On Kubernetes, that means replacing the pods rather than reloading the process inside them.

Don’t run kong reload in a pod. kong reload does pick up the new value, and it does so without dropping connections, but it changes only the container that you ran it in. That container no longer matches its manifest, the other replicas are untouched, and the change is lost the next time the pod is rescheduled, scaled, or upgraded.

Replacing the pods keeps the change in the manifest, where it survives all of those events. To avoid the gap in service that a rolling restart causes, run more than one replica with readiness probes configured instead of using kong reload.

Change a kong.conf value

Set a kong.conf parameter so we have something to apply. This example raises the log level.

  1. Create a values-log-level.yaml file that adds log_level to the env block:

    cat <<EOF > values-log-level.yaml
    env:
      # Added for this guide
      log_level: debug
    EOF

    Keep this in a separate file and layer it on top of values-dp.yaml rather than editing values-dp.yaml in place. Helm merges multiple --values files from left to right, so the data plane keeps the settings it was installed with.

  2. Apply the change:

    helm upgrade kong-dp kong/kong -n kong --values ./values-dp.yaml --values ./values-log-level.yaml --wait

    Setting log_level changes the pod template, so Helm replaces the pods on its own and the new value is already in effect. Nothing else is needed for this kind of change.

Restart the data plane without a template change

Not every change edits the pod template. When a kong.conf parameter points at a file and something outside Helm rewrites that file, the deployment spec is byte-for-byte identical, so helm upgrade has nothing to replace and the pods keep running with the old contents loaded. A rotated Secret is the common case.

Use kubectl rollout restart to replace the pods in this situation. Run it here against the data plane you just upgraded, so you can see what it does before you need it for a rotation:

  1. Record the current pod names and ages so you can compare afterwards:

    kubectl get pods -n kong -l app.kubernetes.io/instance=kong-dp
  2. Trigger a rolling restart of the deployment:

    kubectl rollout restart deployment/kong-dp-kong -n kong
  3. Wait for the rollout to finish:

    kubectl rollout status deployment/kong-dp-kong -n kong --timeout=300s

Validate

  1. Confirm that the pods were replaced:

    kubectl get pods -n kong -l app.kubernetes.io/instance=kong-dp

    The pod names and AGE values have changed, and RESTARTS is 0, because the pods are new rather than restarted in place.

  2. Confirm that the new configuration is in effect:

    export DP_POD=$(kubectl get pods -n kong -l app.kubernetes.io/instance=kong-dp --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1:].metadata.name}')
    kubectl exec -n kong $DP_POD -- printenv KONG_LOG_LEVEL

    The value should be debug.

  3. Confirm that Kong Gateway is serving traffic again:

    kubectl port-forward -n kong $DP_POD 8000:8000 > /dev/null &
    sleep 3
    curl -i localhost:8000
    kill %1

    Kong Gateway returns HTTP 404 with no Route matched with those values, because no Route matches /. This confirms the proxy is listening.

If you have more than one replica and correctly configured readiness probes, the rolling restart replaces pods one at a time and requests keep succeeding. If you have a single replica, like in this guide, expect a gap in service while the pod is replaced.

To trigger this rollout automatically whenever a mounted ConfigMap or Secret changes, see Restart Kong Gateway when a mounted certificate changes.

Cleanup

helm uninstall kong-dp -n kong
kubectl delete namespace kong

FAQs

No. When you change a DataPlane or GatewayConfiguration spec, Kong Operator rolls the data plane pods out itself.

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!