Understanding Kubernetes: Ingress, Gateway API & External Traffic

Understanding Kubernetes: Ingress, Gateway API & External Traffic

In the last article we looked at Services, DNS, and Service Discovery. Services give applications stable identities and make it possible to communicate reliably inside the cluster. But there is one important limitation: A ClusterIP Service is only reachable from inside the cluster.

So how does traffic get in from the outside? This is where NodePorts, LoadBalancers, Ingress, and Gateway API enter the picture.

East-West vs North-South traffic

When discussing Kubernetes networking, you’ll often encounter two terms:

East-West traffic

Traffic flowing between workloads inside the cluster.

Pod A  →  Service  →  Pod B

North-South traffic

Traffic entering or leaving the cluster.

User
  ↓
Internet
  ↓
Kubernetes Cluster

In the previous articles we focused entirely on East-West traffic. Today we’ll focus on North-South traffic.

Services are still the foundation

Before looking at Ingress or Gateway API, it is important to understand that external traffic does not bypass Services. The flow typically looks like this:

User
  ↓
Ingress / Gateway
  ↓
Service
  ↓
Pods

Services remain the stable entry point for workloads. Ingress and Gateway API simply add another layer in front of them.

NodePort: exposing a Service on a node

The simplest way to expose a Service externally is a NodePort. Instead of only receiving a ClusterIP, Kubernetes makes the Service reachable via the same port on every node:

apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  type: NodePort
  selector:
    app: backend
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080

This means the application becomes reachable via <Node-IP>:30080.

NodePorts are simple and useful for testing, but they rarely represent the final production setup. Some drawbacks include:

  • high port numbers
  • no hostname-based routing
  • no TLS termination
  • poor user experience

LoadBalancer Services

Most cloud providers integrate Kubernetes directly with external load balancers. Changing the Service type is enough:

spec:
  type: LoadBalancer

Kubernetes then asks the cloud platform to provision an external load balancer and connect it to the Service. The resulting architecture looks like:

Internet
    ↓
Cloud Load Balancer
    ↓
Service
    ↓
Pods

This is much easier to consume than a NodePort. However, creating one LoadBalancer per application can become expensive and difficult to manage at scale. This is where Ingress comes into play.

Ingress: one entry point, many applications

Imagine three applications:

  • shop.example.com
  • api.example.com
  • grafana.example.com

Creating a dedicated load balancer for each application may be unnecessary. Instead, we can use Ingress, allowing multiple applications to share a single external entry point while routing requests based on rules.

Example:

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

This tells Kubernetes: Requests for api.example.com should be forwarded to the backend Service. The resulting flow becomes:

User
  ↓
api.example.com
  ↓
Ingress Controller
  ↓
Service
  ↓
Pods

Wait - what is an Ingress Controller?

A common misconception is that an Ingress resource itself handles traffic. It doesn’t. Just like Deployments need controllers, Ingress resources need an Ingress Controller. This controller watches Ingress resources and configures reverse proxies accordingly. Examples include Traefik, HAProxy Ingress, or Kong, and other ingress controller implementations.

Why Gateway API exists

Ingress has been incredibly successful, but it also has limitations. Over time, controller vendors added custom annotations and controller-specific features. As a result, advanced configurations often became difficult to standardize.

Gateway API is widely considered the future direction of Kubernetes traffic management. It aims to provide richer routing capabilities, a better separation of responsibilities, improved portability across implementations, and support for more protocols.

Instead of a single resource, Gateway API introduces multiple resources that work together. The most important ones are:

  • Gateway
  • GatewayClass
  • HTTPRoute

A simplified model looks like:

Gateway
   ↓
HTTPRoute
   ↓
Service
   ↓
Pods

The mental model that matters

If you strip everything down, North-South traffic is really just layering again:

User
  ↓
Load Balancer
  ↓
Ingress / Gateway
  ↓
Service
  ↓
Pods

Each layer solves a specific problem:

  • LoadBalancers provide external reachability
  • Ingress and Gateway API provide routing
  • Services provide stable identities
  • Pods run the application

Once you understand these responsibilities, Kubernetes networking becomes much easier to reason about.

Summing up

In this article we learned about different layers Kubernetes offers to expose applications, but all of them have one thing in common: they rely on the Service to be the stable bridge between incoming traffic and application Pods.

While Ingress remains widely used and supported, Gateway API is increasingly becoming the preferred choice for new platform designs thanks to its more flexible and extensible architecture.

In the next article we’ll look at Network Policies and answer another important question: Just because workloads can communicate, should they?

header image created by buddy ChatGPT