# Kong Helm Charts The Kong Helm Charts repository is the official source for deploying Kong on Kubernetes using Helm. It contains four charts: `kong/kong` (a flexible, low-level building block), `kong/ingress` (the recommended opinionated umbrella chart for new installations), `kong/kong-operator` (the current Kubernetes Operator for managing Kong Gateway control and data planes), and the deprecated `kong/gateway-operator` (replaced by `kong/kong-operator`). The charts support Kong Gateway 3.x (both OSS and Enterprise), Kong Ingress Controller 3.x, and the Kong Operator 2.x, covering every deployment topology from simple DB-less setups to hybrid control plane / data plane architectures. Each chart is independently versioned and released via the chart-releaser GitHub Action. `kong/ingress` is the recommended entry point for most users—it deploys a split KIC + Gateway topology with gateway discovery pre-wired. `kong/kong` remains available for advanced users who require full control over the Helm values, hybrid mode, PostgreSQL-backed deployments, Kong Enterprise features, or standalone admin-API-managed instances. The operator charts (`kong/kong-operator` and the deprecated `kong/gateway-operator`) deploy Kubernetes Operators that manage `ControlPlane`, `DataPlane`, and `GatewayConfiguration` CRDs natively. --- ## Setup ### Add the Helm repository ```bash helm repo add kong https://charts.konghq.com helm repo update ``` --- ## `kong/ingress` — Recommended Opinionated Install `kong/ingress` (chart v0.24.0, app v3.9) is an umbrella chart that deploys two instances of `kong/kong`: a `controller` sub-release running only Kong Ingress Controller and a `gateway` sub-release running only Kong Gateway. Gateway discovery is pre-wired: the controller locates all gateway pods automatically through a headless `ClusterIP: None` admin service. All `kong/kong` values are available under the `controller.*` and `gateway.*` keys. ```bash # Minimal install — creates namespace, deploys KIC + Gateway in split topology helm install kong kong/ingress -n kong --create-namespace # Verify kubectl get pods -n kong kubectl get svc -n kong ``` ```yaml # values-ingress.yaml — Gateway discovery with mTLS Admin API + Konnect sync controller: ingressController: enabled: true gatewayDiscovery: enabled: true adminApi: tls: client: enabled: true konnect: enabled: true controlPlaneID: "00000000-0000-0000-0000-000000000000" # CHANGEME tlsClientSecretName: konnect-client-tls apiHostname: "us.kic.api.konghq.com" gateway: nameOverride: gateway image: repository: kong/kong-gateway env: konnect_mode: "on" vitals: "off" cluster_mtls: pki cluster_telemetry_endpoint: "8c9700866b.us.tp0.konghq.com:443" cluster_cert: /etc/secrets/konnect-client-tls/tls.crt cluster_cert_key: /etc/secrets/konnect-client-tls/tls.key lua_ssl_trusted_certificate: system secretVolumes: - konnect-client-tls ``` ```bash helm install kong kong/ingress -n kong --create-namespace -f values-ingress.yaml ``` --- ## `kong/kong` — Flexible Building Block `kong/kong` (chart v3.2.0, app v3.9) deploys a Kong Gateway pod and an optional Kong Ingress Controller sidecar deployment. Every Kong configuration option maps to `env.*` values (translated to `KONG_*` environment variables at runtime). A Bitnami PostgreSQL subchart is available for development use. Enterprise features, hybrid mode, cert-manager TLS, HPA, PDB, DaemonSet, Prometheus ServiceMonitor, and Konnect sync are all toggleable via values. ### DB-less with Ingress Controller (default) ```yaml # values-dbless-kic.yaml image: repository: kong tag: "3.9" env: database: "off" ingressController: enabled: true proxy: enabled: true type: LoadBalancer ``` ```bash helm install kong kong/kong -n kong --create-namespace -f values-dbless-kic.yaml ``` ### Standalone Kong with PostgreSQL (no KIC) ```yaml # values-standalone.yaml image: repository: kong tag: "3.9" env: database: postgres admin: enabled: true http: enabled: true servicePort: 8001 containerPort: 8001 postgresql: enabled: true auth: username: kong database: kong ingressController: enabled: false ``` ```bash helm install kong kong/kong -n kong --create-namespace -f values-standalone.yaml # Access Admin API kubectl port-forward deploy/kong-kong 8001:8001 -n kong curl http://localhost:8001/ ``` ### Kong Enterprise DB-less ```yaml # values-enterprise-dbless.yaml image: repository: kong/kong-gateway tag: "3.9" enterprise: enabled: true license_secret: kong-enterprise-license # kubectl create secret generic kong-enterprise-license --from-file=license=/path/to/license.json vitals: enabled: false portal: enabled: false rbac: enabled: false manager: enabled: false portal: enabled: false portalapi: enabled: false env: database: "off" ingressController: enabled: true proxy: enabled: true type: NodePort ``` ```bash kubectl create secret generic kong-enterprise-license \ --from-file=license=/path/to/license.json -n kong helm install kong kong/kong -n kong --create-namespace -f values-enterprise-dbless.yaml ``` ### Hybrid Mode — Control Plane ```bash # Step 1: Generate cluster mTLS certificate openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp384r1) \ -keyout /tmp/cluster.key -out /tmp/cluster.crt \ -days 1095 -subj "/CN=kong_clustering" kubectl create secret tls kong-cluster-cert \ --cert=/tmp/cluster.crt --key=/tmp/cluster.key -n kong ``` ```yaml # values-hybrid-cp.yaml image: repository: kong tag: "3.9" env: database: postgres role: control_plane cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key admin: enabled: true http: enabled: true servicePort: 8001 containerPort: 8001 cluster: enabled: true tls: enabled: true servicePort: 8005 containerPort: 8005 proxy: enabled: false secretVolumes: - kong-cluster-cert postgresql: enabled: true auth: username: kong database: kong ingressController: enabled: false ``` ```bash helm install kong-cp kong/kong -n hybrid --create-namespace -f values-hybrid-cp.yaml ``` ### Hybrid Mode — Data Plane ```yaml # values-hybrid-dp.yaml image: repository: kong tag: "3.9" env: database: "off" role: data_plane cluster_control_plane: kong-cp-kong-cluster.hybrid.svc.cluster.local:8005 cluster_telemetry_endpoint: kong-cp-kong-clustertelemetry.hybrid.svc.cluster.local:8006 lua_ssl_trusted_certificate: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key admin: enabled: false secretVolumes: - kong-cluster-cert ingressController: enabled: false ``` ```bash helm install kong-dp kong/kong -n hybrid -f values-hybrid-dp.yaml ``` ### Hybrid Mode — Control Plane with cert-manager ```yaml # values-hybrid-cp-certmanager.yaml env: role: control_plane database: postgres pg_host: postgres-postgresql.db.svc.cluster.local pg_user: kong pg_password: super_secret cluster: enabled: true tls: enabled: true certificates: enabled: true issuer: my-ca-issuer # cert-manager ClusterIssuer name cluster: enabled: true commonName: custom.example.com proxy: enabled: false ingressController: env: publish_service: kong/kong-cp-kong-proxy ``` ```bash helm install kong-cp kong/kong -n kong --create-namespace -f values-hybrid-cp-certmanager.yaml ``` ### Gateway Discovery — Separate Controller and Gateway Releases ```yaml # values-gd-gateway.yaml (gateway release, name: gw) admin: enabled: true type: ClusterIP clusterIP: None tls: client: secretName: "admin-api-ca-cert" ingressController: enabled: false replicaCount: 3 # autoscaling: # enabled: true ``` ```yaml # values-gd-controller.yaml (controller release) deployment: kong: enabled: false # only run KIC, no Kong pod proxy: nameOverride: gw-kong-proxy # must match gateway release proxy Service name ingressController: enabled: true gatewayDiscovery: enabled: true adminApiService: name: gw-kong-admin # must match gateway release admin Service name adminApi: tls: client: enabled: true caSecretName: "admin-api-ca-cert" env: kong_admin_svc_port_names: "kong-admin-tls" ``` ```bash helm install gw kong/kong -n kong --create-namespace -f values-gd-gateway.yaml helm install kic kong/kong -n kong -f values-gd-controller.yaml ``` ### DB-less Declarative Config via ConfigMap ```bash kubectl create configmap kong-config --from-file=kong.yaml=/path/to/kong.yaml -n kong ``` ```yaml # values-dbless-config.yaml env: database: "off" dblessConfig: configMap: kong-config ingressController: enabled: false ``` ```bash helm install kong kong/kong -n kong --create-namespace -f values-dbless-config.yaml ``` ### Custom Plugins via ConfigMap ```bash kubectl create configmap kong-plugin-myplugin \ --from-file=handler.lua --from-file=schema.lua -n kong ``` ```yaml # values-custom-plugin.yaml plugins: configMaps: - name: kong-plugin-myplugin pluginName: myplugin env: plugins: bundled,myplugin ``` ```bash helm install kong kong/kong -n kong --create-namespace -f values-custom-plugin.yaml ``` ### Autoscaling (HPA) ```yaml # values-hpa.yaml replicaCount: 2 autoscaling: enabled: true minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 80 ``` ### Prometheus ServiceMonitor ```yaml # values-prometheus.yaml serviceMonitor: enabled: true trustCRDsExist: true # set true if Prometheus Operator CRDs are already installed # labels: # add labels to select this ServiceMonitor from your Prometheus instance # release: prometheus ``` ### OpenShift Deployment ```yaml # values-openshift.yaml containerSecurityContext: enabled: false # OpenShift manages SCCs; disable chart-managed securityContext postgresql: primary: podSecurityContext: enabled: false containerSecurityContext: enabled: false ``` ### PodDisruptionBudget ```yaml podDisruptionBudget: enabled: true maxUnavailable: "50%" # minAvailable: 1 ``` ### DaemonSet Deployment ```yaml deployment: daemonset: true kong: enabled: true ``` ### Manual CRD Update (required before chart upgrades) ```bash # Update CRDs manually before helm upgrade — Helm 3 does not auto-update CRDs kubectl apply -f https://raw.githubusercontent.com/Kong/charts/kong-3.2.0/charts/kong/crds/custom-resource-definitions.yaml helm upgrade kong kong/kong -n kong -f values.yaml ``` --- ## `kong/kong-operator` — Kong Operator (Current) `kong/kong-operator` (chart v1.2.4, app v2.1.5) deploys the Kong Operator, a Kubernetes Operator that manages `ControlPlane`, `DataPlane`, and `GatewayConfiguration` CRDs. It bundles Kong Operator CRDs (`ko-crds`), Gateway API standard CRDs, and optional experimental Gateway API CRDs. Validating and conversion webhooks are enabled by default. The `ko-crds` subchart sets `keep: true` so CRDs survive `helm uninstall`. Cert-manager can be used to automate certificate management for webhooks and the CA. ### Basic Install ```bash helm install ko kong/kong-operator -n kong-system --create-namespace # Verify operator pod kubectl get pods -n kong-system kubectl get crds | grep konghq.com ``` ### Install via OCI Registry ```bash helm install ko oci://docker.io/kong/kong-operator-chart \ --version 1.2.4 \ -n kong-system --create-namespace ``` ### Custom Values ```yaml # values-ko.yaml replicaCount: 1 image: repository: docker.io/kong/kong-operator tag: "2.1.5" # Disable experimental Gateway API CRDs (default: off) gwapi-experimental-crds: enabled: false # Enable cert-manager for webhook certificate management global: webhooks: options: certManager: enabled: true certificateAuthority: options: certManager: enabled: true # Controller feature flags (env vars set on the operator Deployment) env: enable_controller_gateway: "true" enable_controller_controlplane: "true" enable_controller_dataplane: "true" enable_controller_dataplane_bluegreen: "true" enable_controller_aigateway: "false" # experimental resources: limits: cpu: 500m memory: 256Mi requests: cpu: 10m memory: 128Mi ``` ```bash helm install ko kong/kong-operator -n kong-system --create-namespace -f values-ko.yaml ``` ### Multi-Instance Cluster — Disable Duplicate CRDs ```bash # First install: CRDs included (default) helm install ko-primary kong/kong-operator -n kong-system --create-namespace # Additional installs: disable CRDs to avoid conflicts helm install ko-secondary kong/kong-operator -n other-namespace \ --set ko-crds.enabled=false \ --set gwapi-standard-crds.enabled=false ``` ### Update CRDs Before Operator Upgrade ```bash # Update Kong Operator CRDs to a specific version kustomize build github.com/Kong/kong-operator/config/crd/gateway-operator?ref=v2.0.1 \ | kubectl apply -f - # Update Gateway API CRDs kustomize build github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0 \ | kubectl apply -f - helm upgrade ko kong/kong-operator -n kong-system -f values-ko.yaml ``` ### Migrate from `kong/gateway-operator` to `kong/kong-operator` ```bash # Step 1: Update CRDs (required — schemas changed between KGO and KO) kustomize build github.com/kong/kong-operator/config/crd/gateway-operator \ | kubectl apply --server-side -f - # Step 2: Uninstall old chart (CRDs remain due to keep: true policy in old chart) helm uninstall kgo -n kong-system # Step 3: Install new chart helm install ko kong/kong-operator -n kong-system \ --set ko-crds.enabled=false # CRDs already applied above ``` --- ## `kong/gateway-operator` — Deprecated Kong Gateway Operator `kong/gateway-operator` (chart v0.6.1, app v1.6) is the predecessor to `kong/kong-operator`. It has been replaced and should not be used for new installations. It supports Kong Gateway Operator versions 1.2.0 through 1.6.x. The `kube-rbac-proxy` sidecar (deprecated in KGO 1.5+) was used for metrics access control and is superseded by the `--metrics-access-filter` operator flag. ```bash # Legacy install (not recommended — use kong/kong-operator instead) helm install kgo kong/gateway-operator -n kong-system --create-namespace # With explicit operator version pin helm install kgo kong/gateway-operator -n kong-system --create-namespace \ --set image.tag="1.6" ``` ```yaml # values-kgo.yaml — minimal deprecated chart values image: repository: docker.io/kong/gateway-operator tag: "1.6" kic-crds: enabled: true gwapi-standard-crds: enabled: true gwapi-experimental-crds: enabled: false env: enable_controller_gateway: "true" enable_controller_controlplane: "true" enable_controller_dataplane: "true" ``` --- ## Contributing and Local Development ```bash # Install tools (mise-based: helm, kube-linter, chartsnap, shellcheck, actionlint) make tools # Lint all charts with kube-linter + shellcheck + actionlint make lint # Run golden snapshot tests for kong, ingress, gateway-operator charts make test.golden # Update golden snapshots after intentional template changes make test.golden.update # Lint charts only make lint.charts # Update Helm dependencies for ingress chart (which depends on kong/kong) helm dependencies update charts/ingress ``` --- ## Summary The Kong Helm Charts repository covers the full lifecycle of Kong on Kubernetes: simple DB-less KIC-managed gateways, production-grade PostgreSQL-backed standalone instances, hybrid control plane / data plane topologies, Kong Enterprise deployments with RBAC and Dev Portal, and operator-managed declarative configurations via `ControlPlane` and `DataPlane` CRDs. The `kong/ingress` chart is the recommended starting point for new users, deploying a split gateway-discovery architecture in a single `helm install` command. The `kong/kong` chart is the underlying primitive for users who need precise control over routing, secrets, sidecars, DaemonSets, cert-manager integration, or multi-node hybrid layouts. For operator-based workflows where Kong resources are managed declaratively as Kubernetes CRDs, `kong/kong-operator` (v1.2.4, app v2.1.5) is the current chart. It supports conversion and validating webhooks, cert-manager CA automation, ValidatingAdmissionPolicies, and controller feature flags toggled via `env.*` values. All charts follow a manual CRD upgrade pattern (applying CRD manifests with `kubectl apply` or `kustomize build` before running `helm upgrade`) because Helm 3 does not automatically update CRDs during upgrades. The repository uses `make lint` + `make test.golden` (chartsnap) for CI validation and the chart-releaser GitHub Action for automated publishing to `https://charts.konghq.com`.