Using Plugin Resources
This guide walks you through applying the Kong Ingress Controller KongPlugin and KongClusterPlugin custom resources other configuration. These resources change how Kong Gateway handles proxied requests. This guide configures plugins that modify headers and enforce authentication requirements.
See the concept
documentation for more information about the purpose of the KongPlugin
resource.
Installation
Please follow the deployment documentation to install the Kong Ingress Controller onto your 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
This guide assumes that PROXY_IP
environment variable is
set to contain the IP address or URL pointing to Kong Gateway.
If you’ve not done so, follow one of the
deployment guides to configure this environment variable.
If everything is setup correctly, making a request to Kong Gateway should return back
a HTTP 404 Not Found
status code:
curl -i $PROXY_IP
Response:
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 since Kong Gateway doesn’t know how to proxy the request yet.
Deploy an upstream HTTP application
To proxy requests, you need an upstream application to proxy to. Deploying this echo server provides a simple application that returns information about the Pod it’s running in:
echo "
apiVersion: v1
kind: Service
metadata:
labels:
app: echo
name: echo
spec:
ports:
- port: 1025
name: tcp
protocol: TCP
targetPort: 1025
- port: 1026
name: udp
protocol: TCP
targetPort: 1026
- port: 1027
name: http
protocol: TCP
targetPort: 1027
selector:
app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: echo
name: echo
spec:
replicas: 1
selector:
matchLabels:
app: echo
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: echo
spec:
containers:
- image: kong/go-echo:latest
name: echo
ports:
- containerPort: 1027
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
resources: {}
" | kubectl apply -f -
Response:
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:
Test the routing rule:
curl -i http://kong.example/lemon --resolve kong.example:80:$PROXY_IP
Response:
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.
Once the first route is working, create a second pointing to the same Service:
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 will modify 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 plugin
To try this out, first create a KongPlugin resource that adds a response header:
echo '
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: add-header-route
config:
add:
headers:
- "x-added-route: demo"
plugin: response-transformer
' | kubectl apply -f -
Response:
kongplugin.configuration.konghq.com/add-header-route created
Associate the plugin with routing configuration
After creating the plugin, associate it with other resources by adding a
konghq.com/plugins
annotation whose value is the KongPlugin’s name:
Test the plugin
Requests that match the lemon
rules will now include the plugin header:
curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added-route
Response:
x-added-route: demo
Requests to the lime
rules will not:
curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP | grep x-added-route | wc -l
Response:
0
Configuring plugins on Service resource
Associating a plugin with a Service will apply it to any requests that match a routing rule that uses that Service as a backend.
Create a plugin
To try this out, first create a KongPlugin resource that adds a response header:
echo '
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: add-header-service
config:
add:
headers:
- "x-added-service: demo"
plugin: response-transformer
' | kubectl apply -f -
Response:
kongplugin.configuration.konghq.com/add-header-service created
Associate the plugin with the Service
After creating the second plugin, annotate the Service to apply it:
kubectl annotate service echo konghq.com/plugins=add-header-service
Response:
service/echo annotated
Test the plugin
With the Service plugin in place, send requests through the lemon
and lime
routes:
curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added-
Response:
x-added-route: demo
curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP | grep x-added-
Response:
x-added-service: demo
Although both routes use the echo
Service, only the lime
route applies the
echo
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 the lemon
route still
uses the header from the first plugin you created.
Remove a plugin
Removing the plugin annotation will remove plugin(s) from a resource:
Requests through the lemon
route now use the Service’s plugin:
curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP | grep x-added-
Response:
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 -
Response:
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 an ingress.class
annotation
for the controller to recognize them.
Kong Gateway will now reject requests to any route, because the global plugin requires authentication for all of them:
curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP
Response:
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 consumer and credential
First, create a credential Secret:
kubectl create secret generic kotenok-key-auth \
--from-literal=kongCredType=key-auth \
--from-literal=key=gav
Response:
secret/kotenok-key-auth created
Second, create a KongConsumer resource that uses the Secret:
echo "apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
name: kotenok
annotations:
kubernetes.io/ingress.class: kong
username: kotenok
credentials:
- kotenok-key-auth
" | kubectl apply -f -
Response:
kongconsumer.configuration.konghq.com/kotenok created
Including this key will now satisfy the authentication requirement enforced by the global plugin:
curl -sI http://kong.example/lemon --resolve kong.example:80:$PROXY_IP -H "apikey: gav"
Response:
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 plugins
First, create two additional header KongPlugins:
echo '
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: add-header-consumer
config:
add:
headers:
- "x-added-consumer: demo"
plugin: response-transformer
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: add-header-multi
config:
add:
headers:
- "x-added-multi: demo"
plugin: response-transformer
' | kubectl apply -f -
Response:
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 kotenok konghq.com/plugins=add-header-consumer
Response:
kongconsumer.configuration.konghq.com/kotenok annotated
Requests made by the kotenok
consumer will now include this header, since
consumer plugins take precedence over both route and service plugins:
curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP -H "apikey: gav" | grep x-added
Response:
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.
First, add the add-header-multi
plugin to a route:
Then, update the consumer configuration to include both plugins:
kubectl annotate kongconsumer kotenok konghq.com/plugins=add-header-consumer,add-header-multi --overwrite
Response:
kongconsumer.configuration.konghq.com/kotenok annotated
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: gav" | grep x-added
echo "lime\!"; curl -si http://kong.example/lime --resolve kong.example:80:$PROXY_IP -H "apikey: gav" | grep x-added
Response:
lemon!
x-added-multi: demo
lime!
x-added-consumer: demo
Sending a request to the lemon
route without the consumer credentials will
not activate the multi-resource plugin, and will instead fall 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
Response:
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.
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.