Degraphql
Create a KongCustomEntity
resource that specifies the entity name in spec.type
and any required properties under spec.fields
.
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'
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.3.0/standard-install.yaml
-
Create a
Gateway
andGatewayClass
instance 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/kic-gateway-controller
---
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 -
Create a KIC Control Plane
Use the Konnect API to create a new CLUSTER_TYPE_K8S_INGRESS_CONTROLLER
Control Plane:
CONTROL_PLANE_DETAILS=$(curl -X POST "https://us.api.konghq.com/v2/control-planes" \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"name": "My KIC CP",
"cluster_type": "CLUSTER_TYPE_K8S_INGRESS_CONTROLLER"
}')
We’ll need the id
and telemetry_endpoint
for the values.yaml
file later. Save them as environment variables:
CONTROL_PLANE_ID=$(echo $CONTROL_PLANE_DETAILS | jq -r .id)
CONTROL_PLANE_TELEMETRY=$(echo $CONTROL_PLANE_DETAILS | jq -r '.config.telemetry_endpoint | sub("https://";"")')
Create mTLS certificates
Kong Ingress Controller talks to Konnect over a connected secured with TLS certificates.
Generate a new certificate using openssl
:
openssl req -new -x509 -nodes -newkey rsa:2048 -subj "/CN=kongdp/C=US" -keyout ./tls.key -out ./tls.crt
The certificate needs to be a single line string to send it to the Konnect API with curl. Use awk
to format the certificate:
export CERT=$(awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' tls.crt);
Next, upload the certificate to Konnect:
curl -X POST "https://us.api.konghq.com/v2/control-planes/$CONTROL_PLANE_ID/dp-client-certificates" \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"cert": "'$CERT'"
}'
Finally, store the certificate in a Kubernetes secret so that Kong Ingress Controller can read it:
kubectl create namespace kong -o yaml --dry-run=client | kubectl apply -f -
kubectl create secret tls konnect-client-tls -n kong --cert=./tls.crt --key=./tls.key
Kong Ingress Controller running (with an Enterprise license)
-
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 --dry-run=client -o yaml | kubectl apply -f - kubectl create secret generic kong-enterprise-license --from-file=license=./license.json -n kong
-
Create a
values.yaml
file:cat <<EOF > values.yaml gateway: image: repository: kong/kong-gateway env: LICENSE_DATA: valueFrom: secretKeyRef: name: kong-enterprise-license key: license EOF
-
Install Kong Ingress Controller using Helm:
helm install kong kong/ingress -n kong --create-namespace --values ./values.yaml
-
Set
$PROXY_IP
as an environment variable for future commands:export PROXY_IP=$(kubectl get svc --namespace kong kong-gateway-proxy -o jsonpath='{range .status.loadBalancer.ingress[0]}{@.ip}{@.hostname}{end}') echo $PROXY_IP
Create a GraphQL Service
The degraphql
plugin requires an upstream GraphQL API. For this how-to, 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: kong
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: kong
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8080
selector:
app: hasura
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hasura-ingress-console
namespace: kong
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, bootstrap 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"}}'
Create a Route
Our Hasura API will be exposed using the /contacts
path. Create an HTTPRoute
or Ingress
resource pointing to the hasura
Service that we can attach the degraphql
plugin to:
Configure the DeGraphQL plugin
The degraphql
plugin accepts a single configuration option, graphql_server_path
. Create a KongPlugin
resource and attach it to the demo-graphql
route that you just created:
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: degraphql-example
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
plugin: degraphql
config:
graphql_server_path: '/v1/graphql'
" | kubectl apply -f -
Next, apply the KongPlugin
resource by annotating the httproute
or ingress
resource:
The degraphql
entity requires you to configure a mapping between paths and GraphQL queries. In this example, we’ll map the /list
path to query{ contacts { name } }
using the KongCustomEntity
CRD. The KongCustomEntity
CRD attaches the fields
to the KongPlugin
specified in the parentRef
field.
The following resource tells Kong Ingress Controller to create a degraphql_routes
entity in Kong Gateway and attach it to the plugin created by the degraphql-example
KongPlugin
resource:
echo 'apiVersion: configuration.konghq.com/v1alpha1
kind: KongCustomEntity
metadata:
namespace: kong
name: degraphql-route-example
spec:
type: degraphql_routes
fields:
uri: "/list"
query: "query{ contacts { name } }"
controllerName: kong
parentRef:
group: "configuration.konghq.com"
kind: "KongPlugin"
name: "degraphql-example"
' | kubectl apply -f -
Test the Service with the DeGraphQL plugin
To test the degraphql
plugin, call the /contacts/list
endpoint. The /contacts
prefix comes from our Route definition, and the /list
segment comes from our degraphql_routes
definition.
curl "$PROXY_IP/contacts/list"
curl "$PROXY_IP/contacts/list"
The cURL command should return the data that we inserted at the beginning of this how-to:
{"data":{"contacts":[{"name":"Alice"}]}}
Cleanup
Uninstall KIC from your cluster
helm uninstall kong -n kong