PROGRAMMING

Kong API Gateway With Kubernetes

Install Kong to control access to our API

Lightphos
actual-tech

--

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

http://localhost:32615/

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.

--

--