PROGRAMMING
Kong API Gateway With Kubernetes
Install Kong to control access to our API
Previously, we created a basic spring-boot service on Kubernetes. The service did not have any logic to control access, limit the requests, perform load balancing or any such concerns. To manage these concerns we will use Kong API Gateway. We will create a similar echo service with no discovery annotation, circuit breaker or security added. With this architectural pattern, your services remain focused on the business capability, while the non-functional concerns above are handled by the API gateway.
In this article, we install Kong, use it to access our echo service, introduce Kong’s correlation id plugin and a GUI dashboard.
Note: We can use Lens to view and manage the K8s cluster
https://k8slens.dev
Vadal Echo Example Service
We are going to use this VadalEcho service.
Set the resources in application.yml as follows:
spring:
application:
name: vadalecho
server.port: 8080
Build and deploy to K8s as per previous blogs.
mvn spring-boot:build-image
kubectl create deployment vadal-echo --image=vadal-echo:0.0.1-SNAPSHOT
Add as a service, but no need to expose the NodePort, we will access this from Kong as a K8s ingress path.
echo “
apiVersion: v1
kind: Service
metadata:
labels:
app: vadal-echo
name: vadal-echo
spec:
ports:
port: 80
protocol: TCP
targetPort: 8080
selector:
app: vadal-echo
“ | kubectl apply -f -
Install Kong
In installing Kong we will also add the database (not enabled by default) and expose the admin port on 8001.
helm repo add kong https://charts.konghq.com
helm repo update# Helm 2
helm install kong/kong --name kong --set admin.enabled=true --set admin.http.enabled=true --set postgresql.enabled=true --set postgresql.postgresqlUsername=kong --set postgresql.postgresqlDatabase=kong --set env.database=postgres
Note: if you delete the chart and re-install also delete the PVC holding the db in storage.
Check our kong services.
kubectl get svc | grep kong
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kong-kong-admin NodePort 10.110.21.157 8001:31846/TCP,8444:31320/TCP 1s
kong-kong-proxy LoadBalancer 10.97.155.4 localhost 80:32109/TCP,443:32390/TCP 1s
kong-postgresql ClusterIP 10.96.43.206 5432/TCP 1s
kong-postgresql-headless ClusterIP None 5432/TCP 1s
The password for postgresql will be in secrets but we will not be needing it (we added postgres in order for the Konga dashboard to update plugin details).
We will use the admin port 31846 to connect the Konga dashboard to Konga.
If you are using Lens (highly recommended), we can see the services in Lens -> Network -> Services.
Kong Gateway
curl localhost
{“message”:”no Route matched with those values”}
We need to add a route to our echo service above.
Load balance our service with the following:
echo “
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: vadal
annotations:
konghq.com/strip-path: “true”
spec:
rules:
--host: localhost
http:
paths:
--path: /echo
backend:
serviceName: vadal-echo
servicePort: 80" | kubectl apply -f -
Kong is now serving our service.
Now we can call our service with the path defined.
curl localhost/echo
{
timestamp: "2020-07-06T18:56:26.169",
headers: {
host: "localhost",
connection: "keep-alive",
x-forwarded-proto: "http",
x-forwarded-host: "localhost",
x-forwarded-port: "8000",
x-real-ip: "192.168.65.3",
upgrade-insecure-requests: "1",
user-agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
sec-fetch-site: "none",
sec-fetch-mode: "navigate",
sec-fetch-user: "?1",
sec-fetch-dest: "document",
accept-encoding: "gzip, deflate, br",
accept-language: "en-GB,en-US;q=0.9,en;q=0.8",
cookie: "io=27Pjzcnt6E6AEnt1AAAA"
}
}
It should return a json payload like the above.
Note the setting of this annotation:
konghq.com/strip-path: “true”
This is needed if you want to access subpaths
eg:
localhost:31638/echo/actuator/health
Correlation Plugin
Kong provides us with the option of adding a custom correlation id (vadal-request-id) via it’s plugin mechanism. We can do this as follows:
echo “
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-id
config:
header_name: vadal-request-id
plugin: correlation-id
“ | kubectl apply -f -
Add it to the ingress file above
echo “
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: vadal
annotations:
konghq.com/strip-path: “true”
konghq.com/plugins: request-id
spec:
rules:
--host: localhost
http:
paths:
--path: /echo
backend:
serviceName: vadal-echo
servicePort: 80" | kubectl apply -f -
Call the echo service and notice the vadal-request-id, added by Kong.
curl localhost/echo
{
timestamp: "2020-07-04T22:03:01.78",
headers: {
host: "localhost",
connection: "keep-alive",
vadal-request-id: "51835d40-967d-448c-9055-57df9f347a6d#2",
x-forwarded-proto: "http",
x-forwarded-host: "localhost",
x-forwarded-port: "8000",
x-real-ip: "192.168.65.3",
upgrade-insecure-requests: "1",
user-agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
sec-fetch-site: "none",
sec-fetch-mode: "navigate",
sec-fetch-user: "?1",
sec-fetch-dest: "document",
accept-encoding: "gzip, deflate, br",
accept-language: "en-GB,en-US;q=0.9,en;q=0.8"
}
}
Konga Dashboard
Konga provides use with a UI dashboard over Kong. To implement it, create a file konga.yml with following content:
apiVersion: v1
kind: Service
metadata:
name: konga-svc
spec:
type: NodePort
ports:
- name: kong-proxy
port: 1337
targetPort: 1337
protocol: TCP
selector:
app: konga
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: konga
spec:
replicas: 1
selector:
matchLabels:
app: konga
template:
metadata:
labels:
name: konga
app: konga
spec:
containers:
- name: konga
image: pantsel/konga
ports:
- containerPort: 1337
env:
- name: NO_AUTH
value: "true"
Apply the file above
kubectl apply -f konga.yml
Check it is up and running:
kubectl get svc | grep svc
konga-svc NodePort 10.98.39.197 1337:32615/TCP 33m
Navigate to the dashboard
Connect to Kong with host ip (not localhost) and admin port (8001: -> 31846 in this blog). Eg http://192.168.0.111:31846 (ip of your machine and the port from the helm installation). Note: the connection to kong can be a bit flaky. If it doesn’t connect delete the connection, try again and check the pod logs.
Conclusion
We installed Kong in Kubernetes, deployed a service vadal-echo, managed by Kong, added a custom correlation id and added Konga, an open source GUI dashboard for Kong.
Next time we will add security features such as API Keys and JWTs to secure access to the service.
Resources
The source code can be found here, under directory vadal-echo and under infra/kong:
https://gitlab.com/lightphos/spring/vadal
Further Details
For more details on the chart values see: https://github.com/Kong/charts/blob/master/charts/kong/values.yaml
Kong Ingress:
https://github.com/Kong/kubernetes-ingress-controller/blob/master/docs/guides/getting-started.md
For more details on the postgres chart see: https://github.com/helm/charts/tree/master/stable/postgresql
Originally published at https://blog.ramjee.uk on July 7, 2020.