Deploy custom plugins with Kong Gateway 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 to clipboard!
Plugin distribution using an OCI registry
Kong Gateway 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 Gateway 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
0 directories, 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 Gateway 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.
Install the plugin
-
Install the plugin using the
KongPluginInstallation
resource. 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 to clipboard!Verify that the plugin is fetched and available by examining the status of the
KongPluginInstallation
resource:kubectl get kongplugininstallations.gateway-operator.konghq.com -o jsonpath-as-json='{.items[*].status}'
Copied to clipboard!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 to clipboard!In case of problems, the respective
conditions
or respective resources will provide more information.The
KongPluginInstallation
resource creates aConfigMap
with the plugin content. AdditionalConfigMap
s are created when a plugin is referenced by other resources. The operator automatically manages the lifecycle of all theseConfigMap
s. -
Make the plugin available in a
Gateway
resource by referencing it in thespec.dataPlaneOptions.spec.pluginsToInstall
field of theGatewayConfiguration
resource. Plugins can be referenced across namespaces without any additional configuration.echo ' kind: GatewayConfiguration apiVersion: gateway-operator.konghq.com/v1beta1 metadata: name: kong namespace: default spec: dataPlaneOptions: deployment: replicas: 2 podTemplateSpec: spec: containers: - name: proxy image: kong/kong-gateway:3.11 pluginsToInstall: - name: custom-plugin-myheader controlPlaneOptions: deployment: podTemplateSpec: spec: containers: - name: controller image: kong/kubernetes-ingress-controller:3.4 --- 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 to clipboard! -
Deploy an example service and expose it by configuring
HTTPRoute
with the custom plugin:kubectl apply -f https://developer.konghq.com/assets/kubernetes-ingress-controller/examples/echo-service.yaml
Copied to clipboard!Next, add the
HTTPRoute
with the custom plugin. The configuration of the plugin is provided with theKongPlugin
CRD, where the fieldplugin
is set to the name of theKongPluginInstallation
resource.echo " apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: myheader namespace: kong annotations: kubernetes.io/ingress.class: kong plugin: custom-plugin-myeader config: header_value: my-first-plugin " | kubectl apply -f -
Copied to clipboard!Next, apply the
KongPlugin
resource by annotating theservice
resource:kubectl annotate -n kong service echo konghq.com/plugins=myheader
Copied to clipboard!
Validate your configuration
Ensure that everything is up and running and make a request to the service.
curl "$PROXY_IP/echo"
You should see the following header:
myheader: my-first-plugin
curl "$PROXY_IP/echo"
You should see the following header:
myheader: my-first-plugin