Skip to main content

Deliver and secure ingress for APIs in Kubernetes

You currently have a K8s cluster with an API (micro)service and want to deliver it to production with additional features and protection, like rate limiting, authentication, and DDoS protection.

In this guide, you'll learn how to implement ngrok as an API gateway, using the ngrok Kubernetes Operator, in these steps:

  1. Apply the ngrok Kubernetes Operator to your cluster
  2. Configure your cluster to use ngrok as an API gateway
  3. Set up Traffic Policy to shape traffic into/out of your API service

What you'll need

ngrok account

Any tier will do— register now.

A reserved domain

Grab yours in the ngrok dashboard.

A Kubernetes cluster

... and optionally, a functioning API service. If you don't yet have one, you can install our demo service.

kubectl and Helm

Both installed locally on your workstation.

Why use the K8s Gateway API for your API gateway?

Kubernetes has two APIs for handling ingress from external traffic into your cluster's internal network: the original Ingress Controller or the Gateway API.

The ngrok Kubernetes Operator supports both mechanisms. While we encourage you to explore both, we recommend the Gateway API based on the following:

  • The Ingress API, which Ingress Controllers utilize, is frozen in new versions of K8s and no longer receives updates.
  • While the Ingress Controller is designed purely for ingress, the Gateway API is also designed for dynamic infrastructure provisioning and advanced traffic routing.
  • The Gateway API is role-oriented, allowing DevOps/platform/infrastructure engineering teams to control clusters, policies, and permissions centrally, while still allowing API developers to self-service endpoints to their services with route objects.
  • The Gateway API provides a common interface to K8s networking, removing reliance on vendor-specific configurations.
  • Many developers can integrate their APIs or apps onto a single GatewayClass or Gateway, using HTTPRoutes, without affecting others.

For the scope of this guide, and based on this recommendation, we'll focus on Gateway API.

Step 0. Deploy the example ngrok API service

If you're building a proof of concept with ngrok as the API gateway for your APIs in Kubernetes, you can use our example ngrok API service. This service responds to all routes with information about the connection—think of it as the pong to your curl.

note

If you already have an API service, you can skip this step—just be aware that you'll need to edit the example configurations below to properly configure the ngrok Kubernetes Operator.

To deploy the ngrok API service to your cluster, create the prod namespace and apply its deployment.yaml file.

kubectl create namespace prod
kubectl apply -f https://raw.githubusercontent.com/ngrok-samples/ngrok-api-service/refs/heads/main/kubernetes/deployment.yaml

Step 1. Apply the ngrok Kubernetes Operator

Add the ngrok Kubernetes Operator repo to Helm.

helm repo add ngrok https://charts.ngrok.com
helm repo update

Apply the latest Gateway API CRDs to your cluster.

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

Set up a few environment variables to help apply the ngrok Kubernetes Operator.

export NGROK_AUTHTOKEN={AUTHTOKEN}
export NGROK_API_KEY={API_KEY}

Install the ngrok Kubernetes Operator into the previously-created prod namespace with Gateway API functionality enabled.

helm install ngrok-ingress-controller ngrok/kubernetes-ingress-controller \
--namespace prod \
--create-namespace \
--set credentials.apiKey=$NGROK_API_KEY \
--set credentials.authtoken=$NGROK_AUTHTOKEN \
--set useExperimentalGatewayApi=true

Step 2. Configure your cluster to use ngrok as an API gateway

For ngrok to operate as your API gateway, using the native Gateway API, you need to configure the following:

  • A GatewayClass that uses the controller from the ngrok Kubernetes Operator project.
  • A Gateway with at least one listener attached to the ngrok domain you already reserved.
  • At least one HTTPRoute, with your Gateway as its parent, that matches paths to one or more existing API services (in any namespace) based on their name and port.

Create the API gateway configuration

Create a new YAML file named ngrok-api-gateway.yaml and paste in the following content.

First, replace {YOUR_NGROK_DOMAIN} with the domain you reserved.

If you're using the example API service from Step 0, substitute {YOUR_SERVICE_NAME} with ngrok-api-service and {SERVICE-PORT} with 80.

If you're deploying your own API service, change those variables accordingly, and edit the prod namespace to match the namespace where your service is already running. If you have multiple API services in different containers, you'll need to create multiple rules to match paths to services.

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: ngrok-gatewayclass
namespace: prod
spec:
controllerName: ngrok.com/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: ngrok-gateway
namespace: prod
spec:
gatewayClassName: ngrok-gatewayclass
listeners:
- name: ngrok-listener
hostname: {YOUR_NGROK_DOMAIN}
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: ngrokcert
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngrok-route
namespace: prod
spec:
parentRefs:
- kind: Gateway
name: ngrok-gateway
hostnames:
- {YOUR_NGROK_DOMAIN}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: {YOUR_SERVICE_NAME}
port: {SERVICE_PORT}
kind: Service

Write the manifest to disk and apply to your cluster.

kubectl apply -f ngrok-api-gateway.yaml

With the ngrok Kubernetes Operator deployed and configured as an API gateway, your API service is now publicly available at {YOUR_NGROK_DOMAIN}. You can now test your API gateway and service.

curl https://{YOUR_NGROK_DOMAIN}

You'll see a response like the following:

{"message":"Pong from ngrok!","host":"{YOUR_NGROK_DOMAIN}","client_ip":"{YOUR_IP_ADDRESS}","method":"GET","url":"/","time":"2024-10-16T13:51:37.836Z","status":200}

Step 3. Set up Traffic Policy to shape traffic into/out of your API service

ngrok's Traffic Policy module allows you to conditionally act upon traffic as it arrives and departs your API gateway. In a Kubernetes context, Traffic Policy builds on top of the existing YAML manifests you already use to declare your deployments and services.

When the ngrok Kubernetes Operator initiates in your cluster, and your HTTPRoute configuration contains one or more filter dictionaries that reference the NgrokTrafficPolicy CRD, the Operator pipes the raw YAML to ngrok's network to provision the action and enforce it upon incoming and outgoing traffic.

Rate limiting—one of the most in-demand API gateway features— is both quick to implement and highly flexible based on your use case.

Define a rate limiting rule

Create a new YAML file named ngrok-rate-limit.yaml with the following content:

---
kind: NgrokTrafficPolicy
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
metadata:
name: rate-limiting
namespace: prod
spec:
policy:
inbound:
- name: "Rate limit POST requests"
expressions:
- "req.method == 'POST' || req.method == 'PUT'"
actions:
- type: "rate-limit"
config:
name: "Only allow 10 requests per minute"
algorithm: "sliding_window"
capacity: 10
rate: "60s"
bucket_key:
- "conn.client_ip"

This CRD instantiates a rate limiting rule with the following properties:

  • Via the expression, it only applies to requests with the POST or PUT HTTP method—all others, like GET, are unaffected.
  • Allows for a maximum of 10 requests within the last 60s—both values are configurable to your needs.
  • Uses the client's IP address (via the conn.client_ip variable) to track usage against your capacity limit.

Check out the Traffic Policy (for HTTP tunnels) documentation for a complete view of how to combine variables, expressions, and actions to create rules that beneficially shape the traffic on your API gateway and lessen the operational burden on your API service.

Apply the Traffic Policy rule to your cluster

You must instantiate the NgrokTrafficPolicy CRD in your cluster before you can reference it in your API gateway configuration.

kubectl apply -f ngrok-rate-limit.yaml

Update your API gateway configuration to include the Traffic Policy rule

With the CRD applied, you need to update your existing configuration ngrok-api-gateway.yaml with a filter, which is a process that must be completed during the request or response lifecycle.

Edit your existing ngrok-api-gateway.yaml file—specifically the HTTPRoute section—to add a reference to the rate limiting policy.

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngrok-route
namespace: prod
spec:
parentRefs:
- kind: Gateway
name: ngrok-gateway
hostnames:
- {YOUR_NGROK_DOMAIN}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: {YOUR_SERVICE_NAME}
port: {SERVICE_PORT}
kind: Service
filters:
- type: ExtensionRef
extensionRef:
group: ngrok.k8s.ngrok.com
kind: NgrokTrafficPolicy
name: rate-limiting

Re-apply your manifest to update your API gateway with the new Traffic Policy rule.

kubectl apply -f ngrok-api-gateway.yaml

Test the rate limiting rule

Finally, you can validate that your new rate limiting rule was deployed successfully at the ngrok network by creating a large number of requests in quick succession. Run the following on your local workstation, replacing {YOUR_NGROK_DOMAIN}.

for i in `seq 1 50`; do curl -X GET -w '%{http_code}' https://{YOUR_NGROK_DOMAIN}/ ; done

Depending on the capacity value you configured in the NgrokTrafficPolicy CRD, you should start seeing 429 response codes shortly.

You can confirm your Traffic Policy rules in the Edges section of your ngrok dashboard. Click on the edge associated with this deployment, then one of the routes you attached your Traffic Policy rule to. Click Traffic Policy to view the rule as run on the ngrok network.

Viewing the ngrok dashboard to confirm deployment of a Traffic Policy
rule

What's next?

Congratulations—you've now made your API service available to the public internet, backed by the power of ngrok operating as an API gateway.

You also already have HTTP/2 enabled by default for all connections that support it. HTTP/2 gives you better performance with prioritization, multiplexing, and header compression.

Your next best step is to expand your usage of Traffic Policy actions to handle more advanced API gateway requirements:

Finally, you can extend how you use ngrok as an API gateway to better match your Git-based workflows and using version-controlled, declarative, and repeatable configurations with a continuous deployment mechanism like Argo CD.