BKE Bahriya Kubernetes Engine Start a 14-day trial

Ingress with Kong

Kong is the cluster’s ingress: the component that receives HTTP and HTTPS from outside and routes each request to the right application. BKE installs it ready to use — this page shows how to put an application behind it, give it a certificate, and switch on the traffic controls most clusters want first.

Kong is configured through Kubernetes resources, applied with kubectl like anything else. There is no separate Kong console or admin API to operate: create an Ingress, and the routing exists; delete it, and it is gone.

BKE’s part of Kong is installing and upgrading it at tested versions. What you route, limit and cache — the resources and examples on this page — is your application configuration: the examples are starting points offered to help you, not part of BKE, and what you build from them is yours to operate.

Reference architecture covers how outside traffic reaches Kong in the first place — the load balancer, ports 32080/32443, and the firewall rules. This page assumes that path exists.

Exposing an application

Suppose a Deployment called shop runs in namespace retail, listening on port 8080. Two resources put it on the internet.

A Service, giving the pods one stable address inside the cluster:

apiVersion: v1
kind: Service
metadata:
  name: shop
  namespace: retail
spec:
  selector:
    app: shop
  ports:
    - port: 80
      targetPort: 8080

And an Ingress, telling Kong which hostname routes to it:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
  namespace: retail
spec:
  ingressClassName: kong
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: shop
                port:
                  number: 80

Resources like these are applied from any machine with a kubeconfig — the first control-plane node works. Save each as a file and apply it:

kubectl apply -f shop-service.yaml -f shop-ingress.yaml

Changing a resource is the same motion — edit the file, kubectl apply -f it again — and kubectl delete -f <file> removes what it created. These files are yours, not BKE’s: BKE neither creates nor reconciles them, so keep them in your own source control the way you keep anything that decides what runs.

ingressClassName: kong is what hands the route to Kong; without it, the Ingress belongs to nothing and does nothing. With DNS for shop.example.com pointing at your ingress load balancer:

curl http://shop.example.com/

A 404 from Kong rather than your application means the request arrived but no route matched — almost always a hostname that does not match the host: rule. kubectl -n retail describe ingress shop shows what Kong made of it.

TLS certificates

cert-manager obtains and renews certificates; Kong serves them. BKE installs cert-manager but deliberately ships no certificate issuer, because an issuer names things that are yours — your registration email, your DNS provider, your domains. You create one, once, and every application after that is two lines on its Ingress.

An issuer for Let’s Encrypt, proving domain ownership over HTTP through Kong:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: platform@example.com
    privateKeySecretRef:
      name: letsencrypt-account
    solvers:
      - http01:
          ingress:
            ingressClassName: kong

Two things must be true for this http01 proof to work: the hostname’s DNS already points at your ingress load balancer, and port 80 is reachable from the internet — the certificate authority makes a plain-HTTP request to the hostname and must get through. If port 80 cannot be open in your environment, use a dns01 solver instead: the proof is a DNS record rather than an HTTP request, cert-manager’s documentation lists the supported DNS providers, and the rest of this page is unchanged.

While testing, point server: at https://acme-staging-v02.api.letsencrypt.org/directory — the staging environment issues certificates browsers do not trust, but it does not apply the rate limits that can lock a domain out of the production environment for days after repeated failed attempts.

Then ask for a certificate on the Ingress:

metadata:
  name: shop
  namespace: retail
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  ingressClassName: kong
  tls:
    - hosts:
        - shop.example.com
      secretName: shop-tls
  ...

cert-manager sees the annotation, performs the proof, and writes the certificate into the shop-tls Secret; Kong serves it and https:// works. Renewal is automatic. Progress, when you want to watch it:

kubectl -n retail get certificate
kubectl -n retail describe certificate shop-tls

Plugins

Kong’s traffic behaviour beyond routing — limits, caching, restrictions — comes from plugins. A plugin is declared once as a KongPlugin resource and attached by name to whatever it should govern, through an annotation:

  • on an Ingress — governs those routes;
  • on a Service — governs everything reaching that Service;
  • as a KongClusterPlugin with the label global: "true" — governs all traffic through Kong.

The plugins below are part of Kong’s open-source plugin set, which is what BKE installs.

Rate limiting

Sixty requests per minute, per client address:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: shop-rate-limit
  namespace: retail
plugin: rate-limiting
config:
  minute: 60
  policy: local

Attached to the application’s Ingress:

metadata:
  name: shop
  namespace: retail
  annotations:
    konghq.com/plugins: shop-rate-limit

A client over the limit receives 429, and every response carries RateLimit-Remaining so well-behaved clients can pace themselves.

policy: local counts on each Kong instance separately. Kong runs at least two instances for availability, so a client spreading requests across them can reach roughly the limit multiplied by the instance count. For most uses — protecting an application from a runaway caller — that is accurate enough. If you need one exact shared count, policy: redis keeps the counters in a Redis you provide; the plugin’s redis settings name the host.

Note that the address the limit counts is the address Kong sees. Behind a load balancer that is the balancer’s own address — one counter for everyone — unless the client address is being passed through. Reference architecture covers that under The client address, stated honestly.

Response caching

Caching responses in Kong takes repeated identical requests off your application:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: shop-cache
  namespace: retail
plugin: proxy-cache
config:
  response_code: [200, 301]
  request_method: [GET, HEAD]
  content_type:
    - text/html
    - application/json
  cache_ttl: 300
  strategy: memory

Attach it through the same annotation — several plugins are a comma-separated list:

    konghq.com/plugins: shop-rate-limit,shop-cache

Every response then carries X-Cache-Status: Miss, Hit, or Bypass for requests the configuration excludes. Two properties to know before relying on it: the cache lives in each Kong instance’s memory, so it is emptied whenever Kong restarts and warmed separately per instance; and only responses matching the codes, methods and content types listed are stored. It is a load-shedding cache, not a store — an application that must not serve stale data for longer than cache_ttl seconds should set it accordingly.

Others worth knowing

Plugin What it does
ip-restriction allow or deny listed client networks
cors sets cross-origin headers for browser-facing APIs
request-size-limiting rejects request bodies over a stated size
request-termination answers with a fixed status — a maintenance switch for one route
bot-detection rejects known crawler and script user-agents

Each follows the same pattern: a KongPlugin naming the plugin and its config, attached with the konghq.com/plugins annotation.

Seeing what Kong is doing

Kong writes one JSON line per request to its own log, including the route, the status, the caller as Kong saw it, latency figures, and — when caching is on — upstream_cache_status:

kubectl -n kong logs -l app.kubernetes.io/name=kong --tail=50

Substitute the namespace your config.yaml installs Kong into. For a request that behaves unexpectedly, this log answers the first question — did it reach Kong, what did Kong decide, and how long did the application take.