Kubernetes
AWS
Internal Load Balancers
Cloud Infrastructure
DevOps

Kubernetes support for Internal Load Balancers in AWS

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Yes, Kubernetes on AWS supports internal load balancers. The usual way is to create a Service of type LoadBalancer and add AWS-specific annotations so the controller provisions a private load balancer instead of an internet-facing one. The exact annotation depends on which AWS integration you use, but the idea is the same: keep the service reachable only inside your VPC or connected private networks.

How internal load balancers fit into Kubernetes

In Kubernetes, a LoadBalancer service asks the cloud provider integration to provision an external load balancer and connect it to your service endpoints. On AWS, that target might be an NLB or another supported load balancer type depending on your cluster setup and controller.

An internal load balancer is still a real AWS load balancer. The difference is that it gets private reachability rather than public internet exposure.

That makes it useful for:

  • internal APIs
  • private dashboards
  • east-west traffic between VPC-connected systems
  • services fronted by a separate public gateway

The service manifest

On modern AWS setups, a common annotation is aws-load-balancer-scheme: internal:

yaml
1apiVersion: v1
2kind: Service
3metadata:
4  name: internal-api
5  annotations:
6    service.beta.kubernetes.io/aws-load-balancer-scheme: internal
7spec:
8  type: LoadBalancer
9  selector:
10    app: internal-api
11  ports:
12    - port: 80
13      targetPort: 8080

Historically, some environments used service.beta.kubernetes.io/aws-load-balancer-internal: "true" instead. Which one you should use depends on the controller version and provisioning path in your cluster, so check the documentation for the AWS cloud provider or AWS Load Balancer Controller that actually manages your services.

AWS networking still decides whether it works

The service annotation is only part of the setup. AWS also needs the right subnets and routing model.

The usual requirements are:

  • private subnets available in the target Availability Zones
  • subnet tags that let the controller discover internal subnets
  • security groups that allow traffic from the intended clients
  • route tables that let those clients reach the subnets

If the load balancer keeps coming up as internet-facing, subnet tagging is a common culprit. If it provisions correctly but is unreachable, security groups or routing are more likely.

Internal does not mean "reachable from nowhere"

An internal load balancer is private, not isolated. It can still be reachable from:

  • instances inside the same VPC
  • peered VPCs
  • Transit Gateway attachments
  • on-premises networks connected through Direct Connect or VPN

That is useful, but it also means you still need to think about network boundaries and security group policy. Private exposure is not the same thing as access control.

When to use an ingress controller instead

If you need host-based or path-based HTTP routing across many services, an ingress controller inside the cluster can sit behind an internal AWS load balancer. That gives you one private entry point with richer application-layer routing.

A common pattern is:

  1. deploy an ingress controller
  2. expose the controller service as an internal LoadBalancer
  3. route internal application traffic through that controller

This is often easier to operate than creating many separate internal load balancers for many HTTP services.

Common Pitfalls

The most common mistake is using the right annotation with the wrong controller version. AWS integration details changed over time, so confirm whether your cluster expects the older internal: "true" form or the newer scheme: internal form.

Another common issue is subnet tagging. The Kubernetes manifest can be perfect and AWS still will not place the load balancer into the intended private subnets.

Teams also forget that security groups still apply. An internal NLB or ELB is private, but it will not magically accept traffic from every private source.

Finally, do not confuse an internal load balancer with a private Kubernetes service. ClusterIP is only inside the cluster. An internal AWS load balancer extends reachability to the VPC and connected networks.

Summary

  • Kubernetes on AWS supports internal load balancers through LoadBalancer services plus AWS annotations.
  • A common modern annotation is service.beta.kubernetes.io/aws-load-balancer-scheme: internal.
  • Correct subnet tagging, routing, and security groups are required for the service to work.
  • Internal means private to your AWS network boundary, not inaccessible.
  • For richer HTTP routing, place an ingress controller behind an internal load balancer.

Course illustration
Course illustration

All Rights Reserved.