Feb 19, 2025

Kong API Gateway + Kubernetes: Ingress, Auth & Rate Limiting


Video Summary

In this tutorial, we will deploy the Kong API Gateway on a Kubernetes cluster using Helm, configure a Kong Ingress Controller for external routing to a sample "Grade Submission API," implement key-based authentication for securing the API, and finally set up rate-limiting to control incoming requests.

The end goal is to ensure that:

  1. The Grade Submission API is exposed externally via Kong.

  2. Only valid API key holders can access the API (Key-Auth plugin).

  3. We limit how many requests each consumer can make within a fixed time window (Rate-Limiting plugin).

Prerequisites

  • A functioning Kubernetes cluster.

  • The kubectl CLI installed and configured to talk to your cluster.

  • Helm installed on your local machine.

  • Basic knowledge of Kubernetes objects (Deployment, Service, Ingress, etc.).

What We’ll Build

We have a stateless Grade Submission API running in our cluster. We want to expose it to external clients, secure it with API key authentication, and limit how many requests each consumer can make in one minute.

Specifically, Kong will serve as:

  1. Ingress Controller / API Gateway – forwards external traffic to the correct internal service.

  2. Security Layer – only authorized calls (with valid API key) can pass.

  3. Traffic Control – limit request volume from each consumer to prevent abuse or DDoS.

Video Chapters Overview

Below are the key time-stamped sections from the video:

  • 00:00:00 – 00:01:06: What to Expect: Kong API Gateway on Kubernetes

  • 00:01:06 – 00:02:14: Download and Test Starter Code

  • 00:02:14 – 00:04:07: Test Base Application Before Kong

  • 00:04:07 – 00:13:34: Installing Kong Gateway Using Helm on Kubernetes Cluster

  • 00:13:34 – 00:21:23: Kong Ingress Controller: Configuring API Routes

  • 00:21:23 – 00:30:30: Securing APIs: Kong Key Authentication Plugin Setup

  • 00:30:30 – end: Kong Rate Limiting Plugin: Traffic Control Implementation

Starter Code and Basic Setup

All starter YAML manifests for the Grade Submission API are available in the GitHub repository. Here is the key portion that deploys our simple API:

apiVersion: v1
kind: Namespace
metadata:
  name: grade-demo

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grade-submission-api
  namespace: grade-demo
  labels:
    app: grade-submission
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grade-submission
  template:
    metadata:
      labels:
        app: grade-submission
    spec:
      containers:
      - name: grade-submission-api
        image: rslim087/kubernetes-course-grade-submission-api:stateless
        ports:
          - containerPort: 3000

---
apiVersion: v1
kind: Service
metadata:
  name: grade-submission-api
  namespace: grade-demo
spec:
  selector:
    app: grade-submission
  ports:
    - port: 3000
      targetPort: 3000

Applying the Starter Manifests

Save the file as starter-manifests.yaml (or use the provided one in the repository) and run:

kubectl apply -f

Check that everything is up and running:

kubectl get pods -n grade-demo
kubectl get svc -n

Testing the Base Application

If you want to test the Grade Submission API before integrating Kong, do a port-forward:

kubectl port-forward svc/grade-submission-api 3000:3000 -n

Open a new terminal and test:

# Add grades
curl -X POST <http://localhost:3000/grades> \\
  -H "Content-Type: application/json" \\
  -d '{"name": "Harry", "subject": "Defense Against Dark Arts", "score": 95}'

curl -X POST <http://localhost:3000/grades> \\
  -H "Content-Type: application/json" \\
  -d '{"name": "Ron", "subject": "Charms", "score": 82}'

curl -X POST <http://localhost:3000/grades> \\
  -H "Content-Type: application/json" \\
  -d '{"name": "Hermione", "subject": "Potions", "score": 98}'

# Get all grades
curl

This confirms our API is working. Next, we’ll install Kong and expose this service to external traffic without manual port-forwarding.

Installing Kong Gateway Using Helm

Kong provides an official Helm chart that bundles all configurations for Kong Gateway (including the Ingress Controller).

Adding the Kong Helm Repository


Search to confirm you see the Kong chart:

Deploying Kong with helm install

Install the chart into a new namespace called kong:

helm install kong kong/kong \\
  --create-namespace \\
  --namespace kong \\
  --version 2.47.0 \\
  --set ingressController.installCRDs=false

Note: Check the Kong Helm Repository for the latest chart version or maintain the version in the tutorial (2.47.0) for consistency.

Run:

kubectl get pods -n kong
kubectl get svc -n

You should see pods for both the proxy and ingress-controller.

Configuring NodePort vs. LoadBalancer

If you run Kubernetes on a local environment (Docker Desktop or minikube), the default Service type might be set to LoadBalancer. On most local setups, you need a NodePort instead because you don’t have a cloud load balancer available.

If necessary, modify values.yaml with:

proxy:
  type

This ensures Kong’s proxy service is exposed on a NodePort (e.g., 30000+).

If you’re on a cloud provider (AWS, GCP, Azure), you can leave it as LoadBalancer so that a standard cloud load balancer is automatically provisioned.

Configuring the Kong Ingress Controller

Ingress Resource for Routing

Now, let’s define an Ingress resource to route traffic from Kong to our grade-submission-api Service. Below is an example YAML (call it kong-ingress.yaml):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: grade-submission
  namespace: grade-demo
  annotations:
    kubernetes.io/ingress.class: kong
    konghq.com/strip-path: "false"
    # We'll add plugin references here shortly
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /grades
        pathType: Prefix
        backend:
          service:
            name: grade-submission-api
            port:
              number: 3000

Apply it:

kubectl apply -f

Check the route:

# For NodePort, find the port Kong is using:
kubectl get svc -n

Look for kong-proxy or similar. If it shows type NodePort, note the assigned node port (e.g., 30664). Now test:

# GET request via Kong
curl

You should see either an empty array or “cannot GET” (depending on your app logic). If the logs show requests are hitting your service, you have successfully routed traffic through Kong.

Strip Path Explanation

  • konghq.com/strip-path: "false" preserves the exact path (/grades) when forwarding requests to the backend service.

  • If set to "true", it would strip /grades and send requests to the backend as /.

Securing the API with Key-Auth Plugin

We don’t want our API open to the world. Let’s enforce an API key requirement.

Creating the Kong Plugin Resource

Define a custom resource of kind KongPlugin. Create a file (e.g., kong-auth-plugin.yaml):

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: grade-auth
  namespace: grade-demo
  annotations:
    kubernetes.io/ingress.class: kong
plugin: key-auth
config:
  key_names:
    - apikey   # The header clients must provide
  hide_credentials: true

This plugin says: “Any request must have a header apikey: <VALID_KEY> to be allowed through.”

Defining a Kong Consumer

We create a Consumer that will represent a client/application allowed to make requests. It references credentials (stored in a Secret). For example (kong-consumer.yaml):

apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
  name: grade-submission-consumer
  namespace: grade-demo
  annotations:
    kubernetes.io/ingress.class: kong
username: grade-submission
custom_id: 12345
credentials

Here, we reference a secret named user1-api-key.

Storing the API Key in a Secret

Finally, define the Secret which stores the actual key (kong-secret.yaml):

apiVersion: v1
kind: Secret
metadata:
  name: user1-api-key
  namespace: grade-demo
  labels:
    konghq.com/credential: key-auth
type: Opaque
stringData:
  kongCredType: key-auth
  key

  1. key: your-secret-key is the actual token the consumer must include as a header.

  2. kongCredType must be set to key-auth to match the plugin type.

Linking the Plugin with the Ingress

In the Ingress definition (from kong-ingress.yaml), add a reference to this plugin:

metadata:
  ...
  annotations:
    konghq.com/plugins: "grade-auth"

Re-apply all resources:

kubectl apply -f kong-ingress.yaml
kubectl apply -f kong-auth-plugin.yaml
kubectl apply -f kong-consumer.yaml
kubectl apply -f

Now, if you attempt to call GET /grades without the correct header, you should see:


When including the correct key:

curl <http://localhost>:<node-port>/grades \\
  -H "apikey: your-secret-key"

You should succeed!

Applying Rate Limiting

Next, let’s prevent any single consumer from overwhelming our API by limiting requests per minute.

Configuring the Rate-Limiting Plugin

Create another KongPlugin resource (e.g., kong-rate-limit.yaml):

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: grade-rate-limit
  namespace: grade-demo
  annotations:
    kubernetes.io/ingress.class: kong
plugin: rate-limiting
config:
  minute: 5     # Only 5 requests per minute
  limit_by: consumer
  policy

Add that plugin to your Ingress annotations:

metadata:
  ...
  annotations:
    konghq.com/plugins: "grade-auth, grade-rate-limit"

Re-apply:

kubectl apply -f kong-rate-limit.yaml
kubectl apply -f

Testing Rate Limit Enforcement

Make repeated calls:

# Attempt more than 5 requests in a row (within a single minute)
for i in {1..6}; do
  curl <http://localhost>:<node-port>/grades -H "apikey: your-secret-key"
  echo
done

You should see HTTP 429 “API rate limit exceeded” on the 6th attempt. The plugin effectively throttles traffic from that specific consumer.

Final Testing

Once everything is in place, you can:

  1. Verify the pod and service are all running:

    kubectl get pods,svc -n grade-demo
    kubectl get pods,svc -n
    
    
  2. Confirm you cannot call the API without an API key or if you exceed the rate limit.

  3. Successfully call the API with a valid key and under the allowed threshold.

Useful Resources

Conclusion

By following these steps, you have:

  1. Deployed a simple microservice (Grade Submission API) on Kubernetes.

  2. Installed Kong via Helm, which acts as both an Ingress Controller and an API Gateway.

  3. Configured routing rules to expose your internal service through Kong.

  4. Implemented the Key Authentication plugin to restrict access to valid API key holders.

  5. Added rate limiting to throttle traffic and prevent potential DDoS or abuse.

This setup demonstrates how Kong can serve as a robust API management platform—handling ingress traffic, authentication, and traffic policies all within your Kubernetes cluster.

Kubernetes Training

If you find these guides helpful, check out our Kubernetes Training course

Let’s keep in touch

Subscribe to the mailing list and receive the latest updates

Let’s keep in touch

Subscribe to the mailing list and receive the latest updates

Let’s keep in touch

Subscribe to the mailing list and receive the latest updates

Let’s keep in touch

Subscribe to the mailing list and receive the latest updates