Back to blog

Exposing Internal and External URLs in GKE Without Mixing Responsibilities

Exposing Internal and External URLs in GKE Without Mixing Responsibilities

When designing an architecture in GCP with Kubernetes, one of the most important decisions is how to expose internal and external URLs without mixing responsibilities or compromising security.

This is not about “what works”, but about what mental model you want to enforce in your platform.

Internal URLs: accessible only from your network

For internal services (backoffice, operations, private APIs), the cleanest pattern is to use an Internal Load Balancer.

In this model:

  • The service has only a private IP
  • Access is limited to:
    • VPN
    • corporate network
    • internal workloads within the VPC
  • There is no public endpoint reachable from the Internet

In GKE, this is usually implemented as:

  • An internal Service or Ingress
  • Traefik (or another ingress controller) exposed only through an Internal Load Balancer
  • Firewall rules and network routing providing real isolation

The key advantage is clear:

Internal services do not exist for the Internet, not even due to application misconfiguration.

Here, isolation does not rely on headers, paths, or middlewares, but on network boundaries.

External URLs: exposed in a controlled way

For public services (websites, public APIs), the standard pattern is an External HTTP(S) Load Balancer.

A very common and effective design in GKE is:

  • External Load Balancer (with Cloud Armor, if applicable)
  • The load balancer routes traffic to GKE NEGs
  • NEGs point directly to Traefik pods
  • Traefik handles routing to services inside the cluster

Important characteristics of this approach:

  • Traefik does not need its own public IP
  • The only Internet-facing component is the Load Balancer
  • Pod access is restricted to Google infrastructure (health checks / proxies)
  • No NodePorts or additional Load Balancers are exposed

This pattern reduces complexity and works very well as a public edge, keeping control at the perimeter.

One gateway, two entry paths

Although both patterns use Traefik and Kubernetes, their goals are different:

  • Internal: isolation through networking
  • External: controlled exposure at the perimeter (LB + WAF)

Both traffic flows converge at the same logical point inside the cluster:

  • Internal traffic reaches Traefik through an Internal Load Balancer
  • External traffic reaches Traefik through NEGs from an External Load Balancer

The final backend is the same: the cluster’s microservices.
What changes is how traffic reaches them.

The real decision

You can:

  • Use Traefik for private URLs
  • Use Traefik for public URLs
  • Share backend services when it makes sense

But you should never mix entry points.

The decision is not “what works”, but:

what level of isolation you want and where you place your real perimeter.

Designing this separation correctly from the beginning reduces complexity, lowers operational risk, and makes the architecture much easier to reason about over time.

If you are designing or evolving a GKE platform and want to discuss these patterns, you can contact me.