helm upgrade --install kong-operator kong/kong-operator -n kong-system \
--create-namespace \
--set image.tag=2.1 \
--set env.ENABLE_CONTROLLER_KONNECT=true \
--set env.ENABLE_CONTROLLER_KONGPLUGININSTALLATION=true
Deploy custom plugins with Kong Operator
Build and push a plugin as a container image, then use a KongPluginInstallation
to register it with the operator. Reference it in your GatewayConfiguration to
make it available in Data Planes and configure its behavior using a KongPlugin resource.
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'Copied!
Enable the Gateway API
-
Install the Gateway API CRDs before installing Kong Ingress Controller.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yamlCopied! -
Create a
GatewayandGatewayClassinstance to use.echo " apiVersion: v1 kind: Namespace metadata: name: kong --- apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: kong annotations: konghq.com/gatewayclass-unmanaged: 'true' spec: controllerName: konghq.com/gateway-operator --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: kong spec: gatewayClassName: kong listeners: - name: proxy port: 80 protocol: HTTP allowedRoutes: namespaces: from: All " | kubectl apply -n kong -f -Copied!
Kong Operator running
-
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com helm repo updateCopied! -
Install Kong Operator using Helm:
Copied!helm upgrade --install kong-operator kong/kong-operator -n kong-system \ --create-namespace \ --set image.tag=2.1 \ --set env.ENABLE_CONTROLLER_KONGPLUGININSTALLATION=trueCopied!If 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=trueCopied!If 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 -
Required Kubernetes resources
This how-to requires some Kubernetes services to be available in your cluster. These services will be used by the resources created in this how-to.
kubectl apply -f https://developer.konghq.com/manifests/kic/echo-service.yaml -n kong
This how-to also requires 1 pre-configured route:
Wait until the pods for the services are ready:
kubectl wait --for=condition=Ready pod --all -n kong --timeout=300s
Plugin distribution using an OCI registry
Kong Operator can install Kong custom plugins packaged as container images. This guide shows how to package, install, and use a custom plugin in Kong Gateway instances managed by the Kong Operator.
Create a custom plugin (Optional)
If you already have a real plugin, you can skip this step.
mkdir myheader
echo 'local MyHeader = {}
MyHeader.PRIORITY = 1000
MyHeader.VERSION = "1.0.0"
function MyHeader:header_filter(conf)
-- do custom logic here
kong.response.set_header("myheader", conf.header_value)
end
return MyHeader
' > myheader/handler.lua
echo 'return {
name = "myheader",
fields = {
{ config = {
type = "record",
fields = {
{ header_value = { type = "string", default = "roar", }, },
},
}, },
}
}
' > myheader/schema.lua
The directory should now look like this:
myheader
├── handler.lua
└── schema.lua
1 directory, 2 files
Build a container image (Optional)
This section is optional. The rest of this guide uses a pre-published image, and the following information is provided if you want to package your own custom plugin.
Plugin-related files should be at the root of the image, so the Dockerfile for the plugin would look like this:
echo 'FROM scratch
COPY myheader /
' > Dockerfile
In this example, myheader is a directory that contains handler.lua and schema.lua.
Build the image:
docker build -t myheader:1.0.0 .
Next, push the image to a public or private registry available to the Kubernetes cluster where Kong Operator is running.
docker tag myheader:1.0.0 $YOUR_REGISTRY_ADDRESS/myheader:1.0.0
docker push $YOUR_REGISTRY_ADDRESS/myheader:1.0.0
In this example, the plugin is available in the public registry (Docker Hub) as kong/plugin-example:1.0.0. The following steps use the same source.
Register the plugin schema in Konnect
To see your custom plugin in Kong Konnect, you need to register the schema with your control plane.
First, get your control plane ID:
CONTROL_PLANE_ID=$(curl -X GET "https://us.api.konghq.com/v2/control-planes?filter%5Bname%5D%5Beq%5D=gateway-control-plane" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" | jq -r ".data[0].id"
)
Run the following command to upload your schema file to your Konnect control plane:
curl -X POST \
https://us.api.konghq.com/v2/control-planes/$CONTROL_PLANE_ID/core-entities/plugin-schemas \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data "{\"lua_schema\": $(jq -Rs . './myheader/schema.lua')}"
Install the plugin
-
Install the plugin using the
KongPluginInstallationresource. This resource makes the plugin available for instances of Kong Gateway resources:echo ' kind: KongPluginInstallation apiVersion: gateway-operator.konghq.com/v1alpha1 metadata: name: custom-plugin-myheader spec: image: kong/plugin-example:1.0.0 ' | kubectl apply -f -Copied!Verify that the plugin is fetched and available by examining the status of the
KongPluginInstallationresource:kubectl get kongplugininstallations.gateway-operator.konghq.com -o jsonpath-as-json='{.items[*].status}'Copied!The output should look like this:
[ { "conditions": [ { "lastTransitionTime": "2024-10-09T19:39:39Z", "message": "plugin successfully saved in cluster as ConfigMap", "observedGeneration": 1, "reason": "Ready", "status": "True", "type": "Accepted" } ], "underlyingConfigMapName": "custom-plugin-myheader-hnzf9" } ]Copied!In case of problems, the respective
conditionsor respective resources will provide more information.The
KongPluginInstallationresource creates aConfigMapwith the plugin content. AdditionalConfigMaps are created when a plugin is referenced by other resources. The operator automatically manages the lifecycle of all theseConfigMaps. -
Make the plugin available in a
Gatewayresource by referencing it in thespec.dataPlaneOptions.spec.pluginsToInstallfield of theGatewayConfigurationresource. Plugins can be referenced across namespaces without any additional configuration.echo ' kind: GatewayConfiguration apiVersion: gateway-operator.konghq.com/v2beta1 metadata: name: kong namespace: default spec: dataPlaneOptions: deployment: replicas: 2 podTemplateSpec: spec: containers: - name: proxy image: kong/kong-gateway:3.13 pluginsToInstall: - name: custom-plugin-myheader --- apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: kong spec: controllerName: konghq.com/gateway-operator parametersRef: group: gateway-operator.konghq.com kind: GatewayConfiguration name: kong namespace: default ' | kubectl apply -f -Copied! -
Deploy an example service and expose it by configuring
HTTPRoutewith the custom plugin:kubectl apply -f https://developer.konghq.com/assets/kubernetes-ingress-controller/examples/echo-service.yamlCopied!Next, add the
HTTPRoutewith the custom plugin. The configuration of the plugin is provided with theKongPluginCRD, where the fieldpluginis set to the name of theKongPluginInstallationresource.echo " apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: myheader namespace: kong annotations: kubernetes.io/ingress.class: kong plugin: custom-plugin-myheader config: header_value: my-first-plugin " | kubectl apply -f -Copied!Next, apply the
KongPluginresource by annotating theserviceresource:kubectl annotate -n kong service echo konghq.com/plugins=myheaderCopied!
Validate your configuration
Ensure that everything is up and running and make a request to the service.
curl "$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
You should see the following header:
myheader: my-first-plugin
curl "$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
You should see the following header:
myheader: my-first-plugin