Terraform - Kong API Gateway deployment in Kubernetes

Binoy - Sep 28 - - Dev Community

This section helps to basic understand how can we install the Kong API Gateway in the Kubernetes Cluster with help of Terraform

Objective

In a microservice architecture, one of the key components is the API Gateway, which acts as a reverse proxy. Instead of clients communicating directly with multiple services, all requests are sent to a single server (the API Gateway), which routes them to the appropriate microservices based on routing policies configured in the reverse proxy server. One might wonder if a reverse proxy server like Nginx could replace an API Gateway. However, an API Gateway offers more advanced capabilities compared to a standard Nginx server. Below are some key differences:

  • Plugins for authentication (JWT, OAuth2, key authentication).
  • Rate limiting and request throttling.
  • Logging and monitoring (integration with Prometheus, Grafana).
  • Service discovery and health checks.
  • Supports running in various environments, including Kubernetes and Docker.
  • Load balancing with round-robin, least-connections, etc.
  • Integration with third-party services like Datadog, Zipkin, and Cassandra.
  • Manage the version API
  • Manage the deployment strategy like “green/blue”, “canary” deployments
  • Comes with built-in API management capabilities and is easier to set up for managing APIs. You can use its admin API to configure routes, services, and plugins dynamically.
  • Built with scaling in mind, it easily integrates with tools like PostgreSQL and Cassandra for storing API configuration and scaling horizontally across many nodes. ## Setup local environment to build DevOps resources

I use docker containers to set up work environments for multiple applications(Setup Environment). This approach ensures fully isolated and maintainable environments for application development, allowing us to easily start and terminate these environments. Below is the Docker command to create the environment.

docker run -it --name test-microservices-module-envornment-box -v ~/.kube/config:/work/.kube/config -e KUBECONFIG=/work/.kube/config -v ${HOME}:/root/ -v ${PWD}:/work -w /work --net host developerhelperhub/kub-terr-work-env-box
Enter fullscreen mode Exit fullscreen mode

The container contains Docker, Kubectl, Helm, Terraform, Kind, Git

Setup Kong on Kubernetes Cluster

I have created the terraform mdoules, which are available in the GitHub repository. You can download and set up Kong on a Kubernetes cluster, which runs locally in a Docker container.

Clone the repository onto your local Linux machine to get started.

git clone https://github.com/developerhelperhub/kuberentes-help.git
cd kuberentes-help/terraform/sections/00008/terraform
Enter fullscreen mode Exit fullscreen mode

main.tf terraform script

module "microservices" {
    source = "git::https://github.com/developerhelperhub/microservices-terraform-module.git//microservices?ref=v1.2.0"
    kind_cluster_name = var.kind_cluster_name
    kind_http_port    = 80
    kind_https_port   = 443
    kubernetes_namespace = "microservices"
    kong_enable            = true
    kong_admin_domain_name = var.kong_admin_domain_name
    kong_proxy_domain_name = var.kong_proxy_domain_name
    kong_db_user           = "mykong"
    kong_db_name           = "mykongdb"
    kong_db_password       = "MyPassword2222@"
    kong_db_admin_password = "MyPassword2222@"
    kong_persistence_size  = "5Gi"
}
Enter fullscreen mode Exit fullscreen mode

variables.tf terraform script

#This is variable arguments while running the terraform scripts
variable "kind_cluster_name" {
    type = string
    description = "Kind cluster name"
}
variable "kong_admin_domain_name" {
    type = string
    description = "Kong admin api domain name"
    default = "admin.kong.myapp.com"
}
variable "kong_proxy_domain_name" {
    type = string
    description = "Kong proxy domain name"
    default = "api.gateway.mes.app.com"
}
Enter fullscreen mode Exit fullscreen mode

These Terraform scripts install and configure resources in the cluster:

  • Create the Kubernetes cluster in docker container locally, the cluster name will be “microservices-development-cluster-control-plane”
  • Install the ingress controller and exposes ports 80 and 443 to allow access to services from outside the cluster.
  • Create a namespace called "microservices"
  • Install Kong in the "microservices" namespace using a Helm chart.
  • Kong postgres username and password default “mykong” and “MyPassword2222@”
  • Setup the Kong admin API to create the service, route etc.
  • Setup the Kong Ingress resource to connect the Ingress controller with the Kong Admin API and Kong Proxy services.
  • Disabled monitoring Keycloak, Grafana and Prometheus

Cluster create terraform script under kind folder

terraform init
terraform plan  -var="kind_cluster_name=microservices-development-cluster"
terraform apply  -var="kind_cluster_name=microservices-development-cluster"
Enter fullscreen mode Exit fullscreen mode

Following command verify the services

kubectl cluster-info #verify cluster info
kubectl get nodes -o wide #verify node

kubectl get namespace #verify the microservices namespace
kubectl get -n microservices pod #verify server is running
kubectl get -n microservices svc #verify service
Enter fullscreen mode Exit fullscreen mode

As per my experience, this Kong services take time to start and ready to use it. Make sure all services should be ready status before open the service. Eg:

kubectl -n microservices get pod --watch
NAME                              READY   STATUS      RESTARTS   AGE
kong-kong-6bdd9944d-cp79n         2/2     Running     0          9m39s
kong-kong-init-migrations-fptth   0/1     Completed   0          9m39s
kong-postgresql-0                 1/1     Running     0          9m51s
Enter fullscreen mode Exit fullscreen mode

Following command use to login into postgres, the password will be prompt executed the command.

kubectl -n microservices exec -it pod/kong-postgresql-0 -- psql -U mykong -d mykongdb
Enter fullscreen mode Exit fullscreen mode

Note: The Terraform state file should be kept secure and encrypted (using encryption at rest) because it contains sensitive information, such as usernames, passwords, and Kubernetes cluster details etc.

Add our domain to the bottom of the /etc/hosts file on your local machine. This configuration should not be inside our working Linux box “test-microservices-module-envornment-box”; it should be applied to your personal machine's /etc/hosts file. (you will need administrator access):

127.0.0.1       api.gateway.mes.app.com
127.0.0.1       admin.kong.myapp.com
Enter fullscreen mode Exit fullscreen mode

Verify the admin api service, this api response contains the kong API gateway details which is configured in the cluster.


curl --location 'http://admin.kong.myapp.com/'
Enter fullscreen mode Exit fullscreen mode

Run the microservices in Kubernetes cluster

I have created two spring boot applications which are available in the docker hub repository for testing the routing the request to multiple microservices in the cluster. The microservice services will be running 8080 port

  • “developerhelperhub/mes-item-service:1.0.0.1-SNAPSHOT”
  • “developerhelperhub/mes-order-service:1.0.0.1-SNAPSHOT”

Deploy the item service in the cluster

kubectl -n microservices -f microservices/item-service/kube-deployment.yaml apply
kubectl -n microservices -f microservices/item-service/kube-service.yaml apply
Enter fullscreen mode Exit fullscreen mode

Deploy the order service in the cluster

kubectl -n microservices -f microservices/order-service/kube-deployment.yaml apply
kubectl -n microservices -f microservices/order-service/kube-service.yaml apply
Enter fullscreen mode Exit fullscreen mode

Following command verify the pods of microservices

NAME                                 READY   STATUS      RESTARTS   AGE
mes-item-service-544f54f9fd-2jkbs    1/1     Running     0          2m46s
mes-item-service-544f54f9fd-bm85t    1/1     Running     0          2m46s
mes-item-service-544f54f9fd-cddrh    1/1     Running     0          2m46s
mes-item-service-544f54f9fd-zdnjd    1/1     Running     0          2m46s
mes-order-service-5f7cf68dd9-79z48   1/1     Running     0          2m39s
mes-order-service-5f7cf68dd9-qx2dv   1/1     Running     0          2m39s
mes-order-service-5f7cf68dd9-w28nt   1/1     Running     0          2m39s
Enter fullscreen mode Exit fullscreen mode

Following command verify the services are running in the correct port

kubectl -n microservices get svc
NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
kong-kong-admin                ClusterIP   10.96.215.110   <none>        8001/TCP                        24m
kong-kong-manager              NodePort    10.96.185.130   <none>        8002:32038/TCP,8445:31091/TCP   24m
kong-kong-proxy                ClusterIP   10.96.125.115   <none>        80/TCP,443/TCP                  24m
kong-kong-validation-webhook   ClusterIP   10.96.180.81    <none>        443/TCP                         24m
kong-postgresql                ClusterIP   10.96.129.217   <none>        5432/TCP                        24m
kong-postgresql-hl             ClusterIP   None            <none>        5432/TCP                        24m
mes-item-service               ClusterIP   10.96.241.39    <none>        8080/TCP                        3m32s
mes-order-service              ClusterIP   10.96.252.164   <none>        8080/TCP                        3m25s
Enter fullscreen mode Exit fullscreen mode

Create Service and Route path in Kong API

Kong Admin API provides endpoints to create the services and its route path of the services.

Create the service of item-service

curl --location 'http://admin.kong.myapp.com/services/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'name=mes-item-service' \
--data-urlencode 'url=http://mes-item-service.microservices.svc.cluster.local:8080'
Enter fullscreen mode Exit fullscreen mode

Create the route path of item-service. We are routing the all request into “item-service” if the path contains “/item-service”

curl --location 'http://admin.kong.myapp.com/routes/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'service.id=<service_id>' \
--data-urlencode 'paths%5B%5D=/item-service'
Enter fullscreen mode Exit fullscreen mode

Note : Replace the <service_id> with actual service id of item-service.

Create the service of order-service

curl --location 'http://admin.kong.myapp.com/services/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'name=mes-order-service' \
--data-urlencode 'url=http://mes-order-service.microservices.svc.cluster.local:8080'
Enter fullscreen mode Exit fullscreen mode

Create the route path of item-service. We are routing the all request into “order-service” if the path contains “/item-service”

curl --location 'http://admin.kong.myapp.com/routes/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'service.id=<service_id>' \
--data-urlencode 'paths%5B%5D=/order-service'
Enter fullscreen mode Exit fullscreen mode

Note : Replace the <service_id> with actual service id of item-service.

Testing the endpoints of Item service

#get the list of items
curl --location 'http://api.gateway.mes.app.com/item-service/items'
#get the service info
curl --location 'http://api.gateway.mes.app.com/item-service/actuator/info'
#get the helth info
curl --location 'http://api.gateway.mes.app.com/item-service/actuator/health'
Enter fullscreen mode Exit fullscreen mode

Testing the endpoints of Item service

#get the list of items
curl --location 'http://api.gateway.mes.app.com/order-service/items'
#get the service info
curl --location 'http://api.gateway.mes.app.com/order-service/actuator/info'
#get the helth info
curl --location 'http://api.gateway.mes.app.com/order-service/actuator/health'
Enter fullscreen mode Exit fullscreen mode

Note : Postman collections and environment files are available in the repo

Reference

. . . . . . . . . . . . . . . . .