Using Custom Entities
This feature is released as a tech preview (alpha-quality) and should not be depended upon in a production environment.
Kong Ingress Controller provides an interface to configure Kong Gateway entities using CRDs.
Some Kong plugins define custom entities that require configuration. These entities can be configured using the KongCustomEntity
resource.
Note: The KongCustomEntity controller is an opt-in feature. You must enable it by setting feature gate
KongCustomEntity
totrue
to enable the controller.
The KongCustomEntity
resource contains a type
field which indicates the type of Kong entity to create, and a fields
property which can contain any values that need to be set on an entity.
In the following example, a degraphql_routes
entity is created with two properties, uri
and query
.
spec:
type: degraphql_routes
fields:
uri: "/contacts"
query: "query{ contacts { name } }"
This corresponds to the uri
and query
parameters documented in the plugin documentation
Tutorial: DeGraphQL custom entities
Before you begin ensure that you have Installed Kong Ingress Controller with Gateway API support in your Kubernetes cluster and are able to connect to Kong. This guide requires Kong Gateway Enterprise.
Before you begin ensure that you have Installed Kong Ingress Controller with Gateway API support in your Kubernetes cluster and are able to connect to Kong. This guide requires Kong Gateway Enterprise.
Prerequisites
Install the Gateway APIs
-
Install the Gateway API CRDs before installing Kong Ingress Controller.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
-
Create a
Gateway
andGatewayClass
instance to use.echo " --- apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: kong annotations: konghq.com/gatewayclass-unmanaged: 'true' spec: controllerName: konghq.com/kic-gateway-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: kong spec: gatewayClassName: kong listeners: - name: proxy port: 80 protocol: HTTP " | kubectl apply -f -
The results should look like this:
gatewayclass.gateway.networking.k8s.io/kong created gateway.gateway.networking.k8s.io/kong created
Install Kong
You can install Kong in your Kubernetes cluster using Helm.
-
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com helm repo update
-
Create a file named
license.json
containing your Kong Gateway Enterprise license and store it in a Kubernetes secret:kubectl create namespace kong kubectl create secret generic kong-enterprise-license --from-file=license=./license.json -n kong
-
Create a
values.yaml
file:gateway: image: repository: kong/kong-gateway env: LICENSE_DATA: valueFrom: secretKeyRef: name: kong-enterprise-license key: license
-
Install Kong Ingress Controller and Kong Gateway with Helm:
helm install kong kong/ingress -n kong --create-namespace --values ./values.yaml
Test connectivity to Kong
Kubernetes exposes the proxy through a Kubernetes service. Run the following commands to store the load balancer IP address in a variable named PROXY_IP
:
-
Populate
$PROXY_IP
for future commands:export PROXY_IP=$(kubectl get svc --namespace kong kong-gateway-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $PROXY_IP
-
Ensure that you can call the proxy IP:
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 example configures custom entities for the degraphql
plugin, which allows you to access a GraphQL endpoint as a REST API.
Create a GraphQL Service
The degraphql
plugin requires an upstream GraphQL API. For this tutorial, we’ll use Hasura to create an example GraphQL service:
echo 'apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: hasura
hasuraService: custom
name: hasura
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: hasura
template:
metadata:
labels:
app: hasura
spec:
containers:
- image: hasura/graphql-engine:v2.38.0
imagePullPolicy: IfNotPresent
name: hasura
env:
- name: HASURA_GRAPHQL_DATABASE_URL
value: postgres://user:password@localhost:5432/hasura_data
- name: HASURA_GRAPHQL_ENABLE_CONSOLE
value: "true"
- name: HASURA_GRAPHQL_DEV_MODE
value: "true"
ports:
- name: http
containerPort: 8080
protocol: TCP
resources: {}
- image: postgres:15
name: postgres
env:
- name: POSTGRES_USER
value: "user"
- name: POSTGRES_PASSWORD
value: "password"
- name: POSTGRES_DB
value: "hasura_data"
---
apiVersion: v1
kind: Service
metadata:
labels:
app: hasura
name: hasura
namespace: default
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8080
selector:
app: hasura
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hasura-ingress-console
annotations:
konghq.com/strip-path: "true"
spec:
ingressClassName: kong
rules:
- http:
paths:
- path: /hasura
pathType: Prefix
backend:
service:
name: hasura
port:
number: 80' | kubectl apply -f -
Once the Hasura Pod is running, create an API to return contact details using the Hasura API:
curl -X POST -H "Content-Type:application/json" -H "X-Hasura-Role:admin" http://${PROXY_IP}/hasura/v2/query -d '{"type": "run_sql","args": {"sql": "CREATE TABLE contacts(id serial NOT NULL, name text NOT NULL, phone text NOT NULL, PRIMARY KEY(id));"}}'
curl -X POST -H "Content-Type:application/json" -H "X-Hasura-Role:admin" http://${PROXY_IP}/hasura/v2/query -d $'{"type": "run_sql","args": {"sql": "INSERT INTO contacts (name, phone) VALUES (\'Alice\',\'0123456789\');"}}'
curl -X POST -H "Content-Type:application/json" -H "X-Hasura-Role:admin" http://${PROXY_IP}/hasura/v1/metadata -d '{"type": "pg_track_table","args": {"schema": "public","name": "contacts"}}'
Configure the degraphql plugin
The degraphql entity requires you to configure a mapping between paths and GraphQL queries. In this example, we’ll map the /contact
path to query{ contacts { name } }
.
The KongPlugin
CRD creates a new degraphql
plugin, and the KongCustomEntity
CRD attaches the fields
to the KongPlugin
in parentRef
.
echo '---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
namespace: default
name: degraphql-example
plugin: degraphql
config:
graphql_server_path: /v1/graphql
---
apiVersion: configuration.konghq.com/v1alpha1
kind: KongCustomEntity
metadata:
namespace: default
name: degraphql-route-example
spec:
type: degraphql_routes
fields:
uri: "/contacts"
query: "query{ contacts { name } }"
controllerName: kong
parentRef:
group: "configuration.konghq.com"
kind: "KongPlugin"
name: "degraphql-example"
' | kubectl apply -f -
Once the KongPlugin
is configured, you can attach it to an Ingress
:
echo '
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-graphql
annotations:
konghq.com/plugins: "degraphql-example"
spec:
ingressClassName: kong
rules:
- http:
paths:
- path: /contacts
pathType: Prefix
backend:
service:
name: hasura
port:
number: 80' | kubectl apply -f -
Test the Service with the degraphql Plugin
You can access the demo-graphql
ingress with the degraphql
plugin attached to verify the degraphql
plugin and degraphql_routes
entity works:
curl http://${PROXY_IP}/contacts
The curl
command should return
{"data":{"contacts":[{"name":"Alice"}]}}
which matches the data inserted in the previous steps.