helm upgrade --install kong-operator kong/kong-operator -n kong-system \
--create-namespace \
--set image.tag=2.2 \
--set env.ENABLE_CONTROLLER_KONNECT=trueConfigure load balancing with KongUpstreamPolicy
Create a KongUpstreamPolicy resource with your desired load balancing settings, then attach it to the Kubernetes Service using the konghq.com/upstream-policy annotation.
Prerequisites
Kong Konnect
If you don’t have a Konnect account, you can get started quickly with our onboarding wizard.
- The following Konnect items are required to complete this tutorial:
- Personal access token (PAT): Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.
-
Set the personal access token as an environment variable:
export KONNECT_TOKEN='YOUR KONNECT TOKEN'
Kong Operator running
-
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com helm repo update -
Install Kong Operator using Helm:
helm upgrade --install kong-operator kong/kong-operator -n kong-system \ --create-namespace \ --set image.tag=2.2If you want cert-manager to issue and rotate the admission and conversion webhook certificates, install cert-manager to your cluster and enable cert-manager integration by passing the following argument while installing, in the next step:
--set global.webhooks.options.certManager.enabled=trueIf you do not enable this, the chart will generate and inject self-signed certificates automatically. We recommend enabling cert-manager to manage the lifecycle of these certificates. Kong Operator needs a certificate authority to sign the certificate for mTLS communication between the control plane and the data plane. This is handled automatically by the Helm chart. If you need to provide a custom CA certificate, refer to the
certificateAuthoritysection in thevalues.yamlof the Helm chart to learn how to create and reference your own CA certificate.
This tutorial doesn’t require a license, but you can add one using KongLicense. This assumes that your license is available in ./license.json.
echo "
apiVersion: configuration.konghq.com/v1alpha1
kind: KongLicense
metadata:
name: kong-license
rawLicenseString: '$(cat ./license.json)'
" | kubectl apply -f -Create a KonnectAPIAuthConfiguration resource
kubectl create namespace kong --dry-run=client -o yaml | kubectl apply -f -
echo '
kind: KonnectAPIAuthConfiguration
apiVersion: konnect.konghq.com/v1alpha1
metadata:
name: konnect-api-auth
namespace: kong
spec:
type: token
token: "'$KONNECT_TOKEN'"
serverURL: us.api.konghq.com
' | kubectl apply -f -Create a KonnectGatewayControlPlane resource
echo '
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha2
metadata:
name: gateway-control-plane
namespace: kong
spec:
createControlPlaneRequest:
name: gateway-control-plane
konnect:
authRef:
name: konnect-api-auth
' | kubectl apply -f -Create Gateway resources
Create the kong namespace:
kubectl create namespace kongCreate the GatewayConfiguration, GatewayClass, and Gateway resources with basic configuration:
echo '
apiVersion: gateway-operator.konghq.com/v2beta1
kind: GatewayConfiguration
metadata:
name: gateway-configuration
namespace: kong
spec:
dataPlaneOptions:
deployment:
podTemplateSpec:
spec:
containers:
- image: kong/kong-gateway:3.14
name: proxy
---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: gateway-class
spec:
controllerName: konghq.com/gateway-operator
parametersRef:
group: gateway-operator.konghq.com
kind: GatewayConfiguration
name: gateway-configuration
namespace: kong
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: kong
namespace: kong
spec:
gatewayClassName: gateway-class
listeners:
- name: http
port: 80
protocol: HTTP' | kubectl apply -f -Create a Service and a Route
-
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 an
HTTPRouteresource:echo ' apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: echo-route namespace: kong spec: parentRefs: - name: kong rules: - matches: - path: type: PathPrefix value: /echo backendRefs: - name: echo kind: Service port: 1027' | kubectl apply -f -
By default, Kong Gateway distributes requests across the Pods of a Kubernetes Service using round-robin load balancing. For production workloads, you may need sticky sessions, consistent routing based on request attributes, or health check integration.
The konghq.com/upstream-policy annotation lets you attach a KongUpstreamPolicy resource to a Service, giving you full control over Kong Gateway’s upstream load balancing behavior.
This guide demonstrates consistent-hashing load balancing, which routes requests with the same header value to the same upstream Pod — a common pattern for session affinity.
Scale the Service
Scale the echo Deployment to three replicas so there are multiple Pods to route between:
kubectl scale deployment echo -n kong --replicas=3Wait for all Pods to be ready:
kubectl rollout status deployment echo -n kongCreate a KongUpstreamPolicy
Create a KongUpstreamPolicy that configures consistent-hashing by a request header:
echo '
apiVersion: configuration.konghq.com/v1beta1
kind: KongUpstreamPolicy
metadata:
name: session-affinity
namespace: kong
spec:
algorithm: consistent-hashing
hashOn:
header: x-session-id
hashOnFallback:
input: ip' | kubectl apply -f -With this policy, requests that carry the same x-session-id header value are always forwarded to the same upstream Pod. When the header is absent, Kong Gateway falls back to hashing on the client IP.
Annotate the Service
Attach the KongUpstreamPolicy to the echo Service:
kubectl annotate service echo -n kong \
konghq.com/upstream-policy="session-affinity"Validate
-
Get the Gateway’s external IP address:
export PROXY_IP=$(kubectl get gateway kong -n kong -o jsonpath='{.status.addresses[0].value}') -
Send several requests with the same
x-session-idheader value and observe that all responses come from the same Pod:for i in {1..5}; do curl -s -H "x-session-id: user-alice" $PROXY_IP/echo | grep "Running on Pod" doneAll five responses should report the same Pod name:
Running on Pod echo-6d8f4c9b7-xk2vt. Running on Pod echo-6d8f4c9b7-xk2vt. Running on Pod echo-6d8f4c9b7-xk2vt. Running on Pod echo-6d8f4c9b7-xk2vt. Running on Pod echo-6d8f4c9b7-xk2vt.
-
Send requests with a different header value to confirm they land on a different Pod:
for i in {1..5}; do curl -s -H "x-session-id: user-bob" $PROXY_IP/echo | grep "Running on Pod" doneRequests for
user-bobconsistently hit a different Pod than requests foruser-alice.