OpenShift Load Balancers Explained
In OpenShift, “load balancer” can refer to several different layers:
External client traffic │ ▼External Load Balancer │ ▼OpenShift Ingress Router │ ▼Service │ ▼Application Pods
There are also dedicated load balancers for the OpenShift API and machine configuration endpoints.
Main Load Balancers in OpenShift
A standard OpenShift cluster normally needs these external endpoints:
| Endpoint | Port | Purpose |
|---|---|---|
api.<cluster>.<domain> | 6443 | Kubernetes and OpenShift API |
api-int.<cluster>.<domain> | 6443 | Internal API communication |
*.apps.<cluster>.<domain> | 80/443 | Application routes |
| Machine Config Server | 22623 | Node ignition and machine configuration |
The most important distinction is:
API load balancer ≠Application ingress load balancer
They serve different traffic and normally use different backend pools.
High-Level Architecture
Administrators
│
▼
api.cluster.example.com
│
API Load Balancer
│
┌─────────────┼─────────────┐
▼ ▼ ▼
master-0 master-1 master-2
:6443 :6443 :6443
Application Users
│
▼
app1.apps.cluster.example.com
│
Ingress Load Balancer
│
┌─────────────┼─────────────┐
▼ ▼ ▼
router pod router pod router pod
│ │ │
└─────────────┼─────────────┘
▼
OpenShift Service
│
Application Pods
1. API Load Balancer
The API load balancer provides highly available access to the OpenShift control plane.
Clients include:
oc- OpenShift web console
- kubelets
- Operators
- Controllers
- Automation pipelines
- Monitoring systems
Traffic path:
oc command │ ▼api.cluster.example.com:6443 │ ▼External load balancer │ ├── master-0:6443 ├── master-1:6443 └── master-2:6443
The load balancer distributes requests across all healthy API servers.
Recommended behavior
Use:
- Layer 4 TCP load balancing
- TCP health checks or HTTPS health checks
- No application-level rewriting
- Source connection stability where required
- All control-plane nodes as backends
Example HAProxy configuration:
frontend api-server bind *:6443 mode tcp default_backend api-server-backendbackend api-server-backend mode tcp balance roundrobin option tcp-check server master0 10.10.10.10:6443 check server master1 10.10.10.11:6443 check server master2 10.10.10.12:6443 check
2. Internal API Load Balancer
The internal API name is commonly:
api-int.<cluster>.<domain>
It is used by nodes and internal cluster components.
Worker kubelet │ ▼api-int.cluster.example.com:6443 │ ▼Internal load balancer │ ▼Control-plane nodes
In some designs, the same load balancer serves both public and internal API names. In more restricted environments, separate internal and external virtual IPs are used.
3. Machine Config Server Load Balancer
The Machine Config Server listens on port 22623.
It provides Ignition and machine configuration during installation and node provisioning.
New OpenShift node │ ▼api-int.cluster.example.com:22623 │ ▼Load balancer │ ▼Machine Config Server
Typical backend targets:
master-0:22623master-1:22623master-2:22623
Example HAProxy configuration:
frontend machine-config-server bind *:22623 mode tcp default_backend machine-config-backendbackend machine-config-backend mode tcp balance roundrobin server master0 10.10.10.10:22623 check server master1 10.10.10.11:22623 check server master2 10.10.10.12:22623 check
4. Application Ingress Load Balancer
The application load balancer handles traffic for OpenShift Routes.
Example DNS:
payments.apps.cluster.example.commobile.apps.cluster.example.combanking.apps.cluster.example.com
These normally resolve to the ingress load balancer.
Client │ ▼payments.apps.cluster.example.com │ ▼External load balancer │ ▼OpenShift router pods │ ▼Service │ ▼Application pods
The router pods are usually HAProxy-based and managed by the Ingress Operator.
OpenShift Router
The OpenShift router is not the same as the external load balancer.
External Load Balancer │ ▼Ingress Router Pods │ ▼OpenShift Services │ ▼Application Pods
The external load balancer only forwards traffic to the router nodes or router pods.
The router then:
- Matches the hostname
- Matches the route
- Handles TLS
- Selects the backend service
- Load-balances traffic to pods
Route Traffic Flow
Suppose the application route is:
https://payments.apps.cluster.example.com
The request path is:
Browser │ ▼DNS │ ▼Ingress load balancer │ ▼Router pod │ ▼Route object │ ▼Service │ ▼Pod endpoint
OpenShift Route Example
apiVersion: route.openshift.io/v1kind: Routemetadata: name: payments namespace: bankingspec: host: payments.apps.cluster.example.com to: kind: Service name: payments-service port: targetPort: https tls: termination: edge
The router watches Route objects and dynamically updates its routing configuration.
Load Balancing Inside the Cluster
OpenShift Services provide internal load balancing.
Example:
apiVersion: v1kind: Servicemetadata: name: payments-servicespec: selector: app: payments ports: - port: 443 targetPort: 8443
Traffic flow:
payments-service │ ├── payments-pod-1 ├── payments-pod-2 └── payments-pod-3
The service exposes a stable virtual IP and distributes traffic to healthy pod endpoints.
Service Types
ClusterIP
Default service type.
Available only inside the cluster
spec: type: ClusterIP
Use it for internal service-to-service communication.
NodePort
Exposes a port on every node.
Client │ ▼NodeIP:NodePort │ ▼Service │ ▼Pods
spec: type: NodePort
NodePort is usually not preferred as the primary application exposure method in enterprise OpenShift. Routes are more common.
LoadBalancer
Requests an external load balancer from the cloud provider or supported infrastructure integration.
spec: type: LoadBalancer
Example flow in AWS:
Service type LoadBalancer │ ▼Cloud Controller Manager │ ▼AWS NLB or ELB created │ ▼OpenShift nodes or pods
This is frequently used for non-HTTP protocols or applications that need their own external load balancer.
ExternalName
Maps a service to an external DNS name.
spec: type: ExternalName externalName: database.example.com
It does not create a real load balancer.
Ingress Controller Placement
By default, ingress router pods are scheduled according to the Ingress Controller configuration.
For enterprise environments, dedicated infrastructure nodes are recommended:
Worker nodes ├── Application workloads └── Batch workloadsInfrastructure nodes ├── Ingress routers ├── Registry ├── Monitoring └── Logging
Example node labels:
oc label node infra-0 node-role.kubernetes.io/infra=""oc label node infra-1 node-role.kubernetes.io/infra=""oc label node infra-2 node-role.kubernetes.io/infra=""
The Ingress Controller can then use a node placement policy.
Typical Bare-Metal Architecture
Corporate Network
│
F5 / HAProxy / NetScaler
┌─────────┴──────────┐
│ │
API VIP Apps VIP
│ │
┌──────────┼──────────┐ ┌────┼────┐
▼ ▼ ▼ ▼ ▼ ▼
master-0 master-1 master-2 infra nodes
:6443 :6443 :6443 :80/:443
Example VIPs:
API VIP: 10.10.20.10Apps VIP: 10.10.20.20
DNS:
api.ocp.example.com → 10.10.20.10api-int.ocp.example.com → 10.10.20.10*.apps.ocp.example.com → 10.10.20.20
Typical Cloud Architecture
In AWS, Azure, or GCP, OpenShift can create and manage cloud load balancers.
Internet │ ▼Cloud Load Balancer │ ▼Ingress Router Service │ ▼Router Pods │ ▼Application Services
Possible cloud load balancers include:
- AWS Network Load Balancer
- Azure Load Balancer
- Google Cloud Load Balancer
The exact implementation depends on:
- Installation method
- Platform integration
- Ingress Controller configuration
- Service annotations
- Internal or external exposure
Internal vs External Ingress
A cluster can have multiple Ingress Controllers.
Example:
Public Ingress Controller └── *.apps.ocp.example.comInternal Ingress Controller └── *.internal.apps.ocp.example.com
This is useful for banking environments:
Internet-facing applications │ ▼WAF → Public LB → Public RouterInternal banking applications │ ▼Internal LB → Private Router
You can separate them by:
- DNS domain
- Node placement
- Route labels
- Namespace selectors
- Network zones
- Load balancer scope
TLS Termination
OpenShift Routes support several TLS models.
Edge termination
Client ──HTTPS──> Router ──HTTP──> Pod
The router terminates TLS.
Re-encrypt termination
Client ──HTTPS──> Router ──HTTPS──> Pod
The router decrypts and creates a new TLS connection to the backend.
This is commonly preferred for sensitive applications.
Passthrough termination
Client ──HTTPS──> Router ──HTTPS──> Pod
The router does not decrypt the traffic. TLS terminates in the application pod.
Load Balancer Health Checks
API health check
A common check is:
TCP 6443
or an HTTPS readiness endpoint:
https://<master>:6443/readyz
Ingress health check
Common checks include:
TCP 80TCP 443
or the router health endpoint, depending on platform configuration.
The load balancer should remove unhealthy endpoints automatically.
Session Persistence
Most OpenShift applications should be stateless.
However, if an application requires sticky sessions, Routes support session affinity through cookies.
Example annotation:
metadata: annotations: haproxy.router.openshift.io/balance: source
Other algorithms include:
roundrobinleastconnsource
Avoid depending heavily on session persistence when applications can instead store session state externally.
Load Balancing Algorithms
External load balancer
Typical algorithms:
- Round robin
- Least connections
- Source IP
- Weighted round robin
OpenShift router
Common options:
- Round robin
- Least connections
- Source-based persistence
Service load balancing
Kubernetes and OVN-Kubernetes distribute service traffic across available endpoints.
Failure Scenarios
One API server fails
master-1 fails │ ▼LB health check fails │ ▼master-1 removed from pool │ ▼Traffic continues to master-0 and master-2
One router pod fails
router pod fails │ ▼Load balancer or Service removes endpoint │ ▼Traffic continues through remaining router pods
One application pod fails
Application pod fails │ ▼Readiness probe fails │ ▼Endpoint removed from Service │ ▼Traffic goes to healthy pods
This shows the three load-balancing layers:
External LB health │Router readiness │Application pod readiness
Troubleshooting API Load Balancer
Test DNS:
dig api.cluster.example.com
Test the API:
curl -k https://api.cluster.example.com:6443/readyz
Test individual control-plane nodes:
curl -k https://master-0.example.com:6443/readyzcurl -k https://master-1.example.com:6443/readyzcurl -k https://master-2.example.com:6443/readyz
Check API pods:
oc get pods -n openshift-kube-apiserver -o wide
Look for:
- Incorrect backend ports
- Failed health checks
- Missing master node
- TLS inspection
- Idle timeout too low
- Load balancer SNAT exhaustion
- DNS pointing to the wrong VIP
- Firewall blocking port 6443
Troubleshooting Application Load Balancer
Check DNS:
dig payments.apps.cluster.example.com
Test the route:
curl -vk https://payments.apps.cluster.example.com
Check route:
oc get route -n bankingoc describe route payments -n banking
Check router pods:
oc get pods -n openshift-ingress -o wide
Check Ingress Controller:
oc get ingresscontroller -n openshift-ingress-operatoroc describe ingresscontroller default \ -n openshift-ingress-operator
Check the application service and endpoints:
oc get svc -n bankingoc get endpoints -n bankingoc get endpointslices -n banking
Check pod readiness:
oc get pods -n bankingoc describe pod <pod-name> -n banking
The full troubleshooting path is:
DNS ↓External load balancer ↓Router ↓Route ↓Service ↓EndpointSlice ↓Pod readiness ↓Application
Common Problems
Route returns 503
Usually means the router cannot find a healthy backend.
Check:
oc get endpointslices -n <namespace>oc get pods -n <namespace>oc describe route <route> -n <namespace>
Common causes:
- No ready pods
- Wrong Service selector
- Wrong target port
- Failed readiness probe
- Application not listening
API intermittently unavailable
Possible causes:
- Load balancer sending traffic to unhealthy master
- Incorrect health check
- Too-short timeout
- Control-plane API latency
- Network packet loss
- etcd latency
- TLS inspection device interference
Route works internally but not externally
Check:
- Wildcard DNS
- Firewall
- External VIP
- Load balancer pool
- Router node placement
- Port 80/443
- Public versus private ingress configuration
Banking Best Practices
For a regulated banking environment, I would use:
API traffic:Admin network → Private API LB → Control-plane nodesPublic traffic:Internet → DDoS protection → WAF → Public LB → Public routersInternal traffic:Corporate network → Internal LB → Internal routers
Additional controls:
- Separate API and application VIPs
- Private API endpoint
- Dedicated infra nodes for routers
- Multiple router replicas across failure domains
- Re-encrypt or passthrough TLS for sensitive applications
- WAF in front of public ingress
- Mutual TLS for partner applications
- Centralized load balancer and router access logs
- NetworkPolicies behind the router
- Health checks based on readiness
- Avoid TLS interception on OpenShift API traffic
- Monitor connection count, latency and backend health
Important Interview Distinction
An OpenShift architect should distinguish these three layers:
| Layer | Component | Purpose |
|---|---|---|
| External | F5, HAProxy, cloud LB | Sends traffic into the cluster |
| Ingress | OpenShift router | Matches Routes and sends traffic to Services |
| Internal | Kubernetes Service | Distributes traffic to application pods |
External Load Balancer │ ▼OpenShift Router │ ▼Kubernetes Service │ ▼Pods
Interview Answer
OpenShift uses load balancing at multiple layers. The API load balancer exposes port 6443 and distributes administrative and internal Kubernetes API traffic across the control-plane nodes. Port 22623 is used for the Machine Config Server during node provisioning. Application traffic is normally sent through a separate ingress load balancer on ports 80 and 443 to OpenShift router pods. The routers evaluate Route objects, terminate or pass through TLS, and forward requests to Kubernetes Services, which then distribute traffic to healthy pod endpoints.
On bare metal, the external load balancer might be F5, HAProxy or NetScaler. In cloud environments, OpenShift integrates with the cloud provider’s load-balancing services. For production, I would use separate API and application VIPs, redundant router replicas across failure domains, proper health checks, dedicated infrastructure nodes and separate public and internal Ingress Controllers. When troubleshooting, I follow the traffic path from DNS to the external load balancer, router, Route, Service, EndpointSlice, pod readiness and finally the application.