In this post I want to describe how to setup a local Minikube environment with an API Gateway solution called KrakenD. An API Gateway acts as a reverse proxy and ingress for your cluster containing all further backend services. It can handle rate limiting, authentication, data aggregation and/or manipulation and many more. KrakenD is a fast solution to create such a gateway by using simple JSON configuration.
A Kubernetes LoadBalancer is a special type of Kubernetes service which directs traffic from external sources to the internal backend pods. So that is the kind of thing we want to combine with the krakenD API Gateway.
The prerequisites for this adventure are
docker
installedkubectl
installedminikube
installed
Let’s begin by starting the Minikube cluster
minikube start
This command creates the cluster and should end with
🏄 Done!
To get the LoadBalancer
up and running we need a KrakenD image first. This is really simple, because all KrakenD needs is a simple configuration file. By taking the provided base image it is nothing else than
# Dockerfile
FROM devopsfaith/krakend
ADD ./krakend.json /etc/krakend/krakend.json
EXPOSE 8080
To improve this a next step could be to put this configuration into a Kubernetes ConfigMap
but let us start here.
Create the most basic krakend.json with the content
{
"version": 2
}
in the same directory like the Dockerfile. To push the image into the local directory used by the Minikube cluster execute
eval $(minikube docker-env)
And continue building the image within the same terminal session with
docker build . -t krakend-api-gateway
To deploy this into the Kubernetes cluster I use the following definition.
# k8s.yml
apiVersion: v1
kind: Service
metadata:
name: api-gateway
spec:
type: LoadBalancer
selector:
app: krakenD
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: krakend-deployment
labels:
app: krakend-api-gateway
spec:
replicas: 1
selector:
matchLabels:
app: krakenD
template:
metadata:
labels:
app: krakenD
spec:
containers:
- name: api-gateway
image: krakend-api-gateway
ports:
- containerPort: 8080
imagePullPolicy: Never
command: ["/usr/bin/krakend"]
args: ["run", "-d", "-c", "/etc/krakend/krakend.json", "-p", "8080"]
Here the service definition includes the type: LoadBalancer
. This makes the service a LoadBalancer
one which should handle external traffic.
To get this into the Minikube cluster it takes nothing more than
kubectl apply -f k8s.yml
This creates the LoadBalancer
Kubernetes service and deploys one replica of the KrakenD image containing our configuration.
Let’s assume there is a second service running in the cluster which contains a web service with a /hello-world
route. And let’s assume the service is called hello-world-service
. We now want to connect our api-gateway to direct incoming traffic to that route via the external /hello-gateway
route.
This is now done in the krakend.json configuration file and is basically as simple as
{
"version": 2,
"timeout": "3000ms",
"cache_ttl": "300s",
"name": "API - Gateway",
"endpoints": [
{
"endpoint": "/hello-gateway",
"output_encoding": "string",
"method": "GET",
"backend": [
{
"url_pattern": "/hello-world",
"encoding": "string",
"sd": "dns",
"method": "GET",
"host": ["hello-world-service"],
"disable_host_sanitize": true
}
]
}
]
}
By setting “sd“: „dns“
we tell KrakenD, that it should resolve the “host“:“hello-world-service“
by the given DNS. It’s also crucial to use "disable_host_sanitize": true
while working with a service discovery in KrakenD. Nevertheless this makes the configuration rather convenient.
If kubectl get svc
gives you the following
➜ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api-gateway LoadBalancer 10.110.59.77 <pending> 80:31299/TCP 18m
hello-world-service ClusterIP 10.107.30.157 <none> 8080/TCP 4s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 34m
there is only one last step missing. The last step transform the EXTERNAL-IP: <pending>
into our localhost ip. It is
minikube tunnel
When you execute kubectl get svc
, you should see EXTERNAL-IP: 127.0.0.1
for the api-gateway
🎉 By open http://localhost/hello-gateway
you should get something like
Quick Note
It’s also rather easy adding e.g. authentication via Auth0 by following the given provided description.