You are browsing documentation for an older version. See the latest documentation here.
Using Plugin Resources
Learn to apply the Kong Ingress Controller
KongPlugin
and KongClusterPlugin
custom resources to other configurations. These
resources change how Kong Gateway handles proxied requests. You can
configures plugins to modify headers and enforce authentication requirements.
See the concept
documentation for more information about the purpose of the KongPlugin
resource.
Installation
Follow the deployment documentation to install the Kong Ingress Controller on the Kubernetes cluster.
Installing the Gateway APIs
If you wish to use the Gateway APIs examples, follow the supplemental Gateway APIs installation instructions.
Testing connectivity to Kong Gateway
Ensure that the PROXY_IP
environment variable is
set to contain the IP address or URL pointing to Kong Gateway.
The deployment guide that you used to install the Kong Ingress Controller on the Kubernetes cluster provides the instructions to configure this environment variable.
If everything is set correctly, a request to Kong Gateway returns
a HTTP 404 Not Found
status code:
curl -i $PROXY_IP
The results should look like this:
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 48
X-Kong-Response-Latency: 0
Server: kong/3.0.0
{"message":"no Route matched with those values"}
This is expected because Kong Gateway doesn’t know how to proxy the request yet.
Deploy an echo service
To proxy requests, you need an upstream application to send a request to. Deploying this echo server provides a simple application that returns information about the Pod it’s running in:
kubectl apply -f https://docs.konghq.com/assets/kubernetes-ingress-controller/examples/echo-service.yaml
The results should look like this:
service/echo created
deployment.apps/echo created
Create a configuration group
Ingress and Gateway APIs controllers need a configuration that indicates which set of routing configuration they should recognize. This allows multiple controllers to coexist in the same cluster. Before creating individual routes, you need to create a class configuration to associate routes with:
Kong Ingress Controller recognizes the kong
IngressClass and
konghq.com/kic-gateway-controller
GatewayClass
by default. Setting the CONTROLLER_INGRESS_CLASS
or
CONTROLLER_GATEWAY_API_CONTROLLER_NAME
environment variable to
another value overrides these defaults.
Add routing configuration
Create routing configuration to proxy /lemon
requests to the echo server:
The results should look like this:
Test the routing rule:
curl -i -H 'Host:kong.example' $PROXY_IP/lemon
The results should look like this:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 140
Connection: keep-alive
Date: Fri, 21 Apr 2023 12:24:55 GMT
X-Kong-Upstream-Latency: 0
X-Kong-Proxy-Latency: 1
Via: kong/3.2.2
Welcome, you are connected to node docker-desktop.
Running on Pod echo-7f87468b8c-tzzv6.
In namespace default.
With IP address 10.1.0.237.
...
If everything is deployed correctly, you should see the above response. This verifies that Kong Gateway can correctly route traffic to an application running inside Kubernetes.
After you test the routing configuration to proxy /lemon
, create a second routing configuration to proxy /lime
that points to the same Service:
The results should look like this:
Configuring plugins for routing configuration
Kong Gateway plugins can apply to a variety of resources. Plugins apply to different sets of requests depending on what type of resource they are applied to. Applying a plugin an Ingress or HTTPRoute modifies requests that match that resource’s routing rules.
The validating admission webhook is not installed by this guide, but is recommended for all environments. The webhook is required to validate plugin configuration. Not installing the webhook can allow invalid plugin configuration, and invalid plugin configuration will block configuration updates until fixed.
-
Create a KongPlugin resource
add-header-route
that adds a response headerx-added-route: demo
.echo ' apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: add-header-route annotations: kubernetes.io/ingress.class: kong config: add: headers: - "x-added-route: demo" plugin: response-transformer ' | kubectl apply -f -
The results should look like this:
kongplugin.configuration.konghq.com/add-header-route created
-
Associate the plugin with routing configuration by adding a
konghq.com/plugins
annotation whose value is the name of the KongPlugin.The results should look like this:
-
Test the plugin by sending requests to the routes.
-
Requests that match the
lemon
rules now includes the plugin header:curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added-route
The results should look like this:
x-added-route: demo
-
Requests to the
lime
rules does not include the plugin header:curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP | grep x-added-route | wc -l
The results should look like this:
0
-
Configuring plugins on Service resource
Associating a plugin with a Service applies it to any requests that match a routing rule that uses that Service as a backend.
-
Create a KongPlugin resource
add-header-service
that adds a response headerx-added-service: demo
.echo ' apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: add-header-service annotations: kubernetes.io/ingress.class: kong config: add: headers: - "x-added-service: demo" plugin: response-transformer ' | kubectl apply -f -
The results should look like this:
kongplugin.configuration.konghq.com/add-header-service created
-
Associate the plugin with the Service.
kubectl annotate service echo konghq.com/plugins=add-header-service
The results should look like this:
service/echo annotated
-
Test the plugin by sending requests to the routes.
-
Requests to the
lemon
route includes the header from the first plugin:curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added-
The results should look like this:
x-added-route: demo
-
Requests to the
lime
route includes the header from the second plugin:curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP | grep x-added-
The results should look like this:
x-added-service: demo
Although both routes use the
echo
Service, only thelime
route applies theecho
Service’s plugin. This is because only one instance of a particular plugin can execute on a request, determined by a precedence order. Route plugins take precedence over service plugins, so thelemon
route still uses the header from the plugin that you created first. -
-
Remove the plugin annotation to remove plugin(s) from a resource.
The results should look like this:
-
Verify that the plugin is removed by sending requests through the
lemon
route. It now use the Service’s plugin.curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added-
The results should look like this:
x-added-service: demo
Configuring global plugins
Global plugins apply to all requests, regardless of which resources they match. Because this applies across Kubernetes namespaces, global plugins require a cluster-scoped KongClusterPlugin instead of a namespaced KongPlugin.
Although not shown in this guide, you can also apply a KongClusterPlugin to resources using
konghq.com/plugins
annotations, to reuse plugin configurations across namespaces.
-
Create a cluster plugin. KongClusterPlugin configuration is largely the same as KongPlugin configuration, though this resource uses a different plugin and therefore uses different configuration inside its
config
key.echo " apiVersion: configuration.konghq.com/v1 kind: KongClusterPlugin metadata: name: auth annotations: kubernetes.io/ingress.class: kong labels: global: 'true' plugin: key-auth config: key_in_header: true key_in_body: false key_in_query: false " | kubectl apply -f -
The results should look like this:
kongclusterplugin.configuration.konghq.com/auth created
The
global='true'
label tells Kong Ingress Controller to create a global plugin. These plugins do not need annotations on other resources for them to take effect, but they do need aningress.class
annotation for the controller to recognize them. -
Send requests to any route. Kong Gateway now rejects requests, because the global plugin requires authentication for all of them.
curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP
The results should look like this:
HTTP/1.1 401 Unauthorized Date: Fri, 09 Dec 2022 20:10:11 GMT Content-Type: application/json; charset=utf-8 Connection: keep-alive WWW-Authenticate: Key realm="kong" Content-Length: 45 x-added-service: demo X-Kong-Response-Latency: 0 Server: kong/3.0.1 { "message":"No API key found in request" }
Note that the earlier header plugins are still applied. Plugins that affect responses can modify both proxied responses and responses generated by Kong Gateway.
-
Configure a credential Secret.
kubectl create secret generic consumer-1-key-auth \ --from-literal=kongCredType=key-auth \ --from-literal=key=consumer-1
The results should look like this:
secret/consumer-1-key-auth created
-
Configure a KongConsumer resource that uses the Secret.
echo "apiVersion: configuration.konghq.com/v1 kind: KongConsumer metadata: name: consumer-1 annotations: kubernetes.io/ingress.class: kong username: consumer-1 credentials: - consumer-1-key-auth " | kubectl apply -f -
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-1 created
-
Test the global plugin by including the key that now satisfies the authentication requirement enforced by the global plugin.
curl -sI http://kong.example/lemon --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-1'
The results should look like this:
HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 9593 Connection: keep-alive Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true x-added-service: demo X-Kong-Upstream-Latency: 2 X-Kong-Proxy-Latency: 1 Via: kong/3.1.1
Configure a plugins for consumers and multiple resources
Plugins can match requests made by a consumer and match requests that meet multiple criteria, such as requests made by a consumer for a specific route.
-
Create a two KongPlugin resources
add-header-consumer
andadd-header-multi
that adds a response headerx-added-consumer: demo
andx-added-multi: demo
respectively.echo ' --- apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: add-header-consumer annotations: kubernetes.io/ingress.class: kong config: add: headers: - "x-added-consumer: demo" plugin: response-transformer --- apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: add-header-multi annotations: kubernetes.io/ingress.class: kong config: add: headers: - "x-added-multi: demo" plugin: response-transformer ' | kubectl apply -f -
The results should look like this: ```text kongplugin.configuration.konghq.com/add-header-consumer created kongplugin.configuration.konghq.com/add-header-multi created
-
Associate a plugin with a consumer. Similar to the other resources, consumers can use the
konghq.com/plugins
annotation to associate a plugin.kubectl annotate kongconsumer consumer-1 konghq.com/plugins=add-header-consumer
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-1 annotated
-
Verify by sending requests as
consumer-1
. The response now includes thex-added-consumer: demo
header, because consumer plugins take precedence over both route and service plugins.curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-1' | grep x-added
The results should look like this:
x-added-consumer: demo
Associate a plugin with a consumer and route
Plugins can be associated with more than one resource. Although routing and Service configuration is implicitly linked (a routing rule cannot proxy to multiple Services), consumers are not. Assigning plugins to multiple resources allows a consumer to use different plugin configuration depending on which route they hit.
-
Add the
add-header-multi
plugin to a route.The results should look like this:
-
Update the consumer configuration to include both plugins.
kubectl annotate kongconsumer consumer-1 konghq.com/plugins=add-header-consumer,add-header-multi --overwrite
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-1 annotated
-
Send requests with the consumer credentials. The header returned now depend on which route the consumer uses.
echo "lemon\!"; curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-1' | grep x-added echo "lime\!"; curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-1' | grep x-added
The results should look like this:
lemon! x-added-multi: demo lime! x-added-consumer: demo
-
Send a request to the
lemon
route without the consumer credentials and it does not activate the multi-resource plugin, and instead falls back to the Service plugin. When plugins are associated with multiple resources, requests must match all of them.curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added
The results should look like this:
x-added-service: demo
More specific plugins (for example, a route and consumer, versus just a consumer or just a route) always take precedence over less specific plugins.
Associate a plugin with multiple consumers using a consumer group
This feature requires Kong Gateway Enterprise 3.4 or higher. It is not compatible with the older consumer groups implementation introduced in Kong Gateway Enterprise 2.7.
Consumer groups allow you to group like consumers together and apply the same plugin configuration to them without annotating the consumers individually.
-
Create an additional plugin.
echo ' --- apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: add-header-group-golden annotations: kubernetes.io/ingress.class: kong config: add: headers: - "x-added-consumer-group: demo" plugin: response-transformer-advanced ' | kubectl apply -f -
The results should look like this:
kongplugin.configuration.konghq.com/add-header-group-golden created
-
Create a KongConsumerGroup resource with that plugin applied.
echo ' --- apiVersion: configuration.konghq.com/v1beta1 kind: KongConsumerGroup metadata: name: golden annotations: kubernetes.io/ingress.class: kong konghq.com/plugins: add-header-group-golden ' | kubectl apply -f -
The results should look like this:
kongconsumergroup.configuration.konghq.com/golden created
-
Create a second credential and KongConsumer.
kubectl create secret generic consumer-2-key-auth \ --from-literal=kongCredType=key-auth \ --from-literal=key=consumer-2
The results should look like this:
secret/consumer-2-key-auth created
echo "apiVersion: configuration.konghq.com/v1 kind: KongConsumer metadata: name: consumer-2 annotations: kubernetes.io/ingress.class: kong username: consumer-2 credentials: - consumer-2-key-auth " | kubectl apply -f -
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-2 created
-
Add both consumers to this group by adding a
consumerGroups
array to their KongConsumers.kubectl patch --type json kongconsumer consumer-1 -p='[{ "op":"add", "path":"/consumerGroups", "value":["golden"], }]' kubectl patch --type json kongconsumer consumer-2 -p='[{ "op":"add", "path":"/consumerGroups", "value":["golden"], }]'
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-1 patched kongconsumer.configuration.konghq.com/consumer-2 patched
-
Send requests as the
consumer-1
consumer to thelime
route.curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-1' | grep x-added
The results should look like this:
x-added-consumer-group: demo x-added-consumer: demo
- Send requests from
consumer-2
consumer to thelime
route.curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-2' | grep x-added
The results should look like this:
x-added-consumer-group: demo x-added-service: demo
-
Delete the consumer-level annotation to let the group-level configuration take effect.
kubectl annotate kongconsumer consumer-1 konghq.com/plugins- curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP -H 'apikey: consumer-1' | grep x-added
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-1 annotated x-added-consumer-group: demo x-added-service: demo
Next steps
There’s a lot more you can do with Kong plugins. Check the Plugin Hub to see all of the available plugins and how to use them.
Next, you might want to learn more about Ingress with the KongIngress resource guide.