> For the complete documentation index, see [llms.txt](https://docs.cloud.olakrutrim.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cloud.olakrutrim.com/basics/core-infrastructure/krutrim-kubernetes-system/load-balancers.md).

# Load Balancers

Load balancers let you expose applications running in Krutrim Kubernetes Service (KKS) to clients outside the cluster. This guide explains how to create and operate Kubernetes Services of type `LoadBalancer` without exposing underlying infrastructure details.

> **Layer 7 traffic:** Use a Kubernetes Ingress controller or Gateway API implementation for HTTP and HTTPS features such as host-based routing, path-based routing, TLS termination, redirects, and header manipulation. Use a `LoadBalancer` Service as the Layer 4 entry point for TCP or UDP traffic.

### What is a LoadBalancer Service?

A Kubernetes Service of type `LoadBalancer` requests a managed network endpoint for a set of application Pods. KKS provisions the endpoint asynchronously and publishes its address in the Service status.

Key benefits include:

* A stable endpoint for external clients
* Managed provisioning and cleanup
* Traffic distribution across healthy Service backends
* Support for TCP and UDP services
* Integration with standard Kubernetes networking resources

### How LoadBalancer Services work in KKS

```
flowchart TD
    A[Client] --> B[Managed load balancer]
    B --> C[Kubernetes Service]
    C --> D[Ready application Pods]
```

When you create a Service with `spec.type: LoadBalancer`:

1. Kubernetes records the Service definition.
2. KKS provisions a managed load-balancer endpoint.
3. The endpoint address appears in `.status.loadBalancer`.
4. Incoming traffic is forwarded to the Service backends.

Provisioning is asynchronous and usually takes a few minutes. The exact network resources and routing path are platform-managed and can change without requiring changes to your application manifest.

### Public and private exposure

#### Public load balancer

A public load balancer provides an endpoint that can be reached from the internet, subject to the access controls configured for the Service and cluster network.

Public exposure is appropriate for:

* Public websites and APIs
* Internet-facing ingress controllers
* TCP or UDP services that must be reached by external clients

#### Private load balancer

A private load balancer provides an endpoint reachable only from connected private networks. Use private exposure for internal APIs, databases, and service-to-service traffic that must not be internet-accessible.

Kubernetes does not define one universal field for selecting public or private exposure. Use the KKS-supported private-load-balancer option available for your cluster version. Do not add undocumented annotations or infrastructure resource identifiers to the Service manifest.

Each provisioned load balancer can consume service quota and network address capacity. Include expected public and private endpoints when planning cluster networking and quotas.

### Layer 4 and Layer 7 traffic

#### Use a LoadBalancer Service for Layer 4

A `LoadBalancer` Service is a good fit when you need:

* Direct TCP or UDP exposure
* A single externally reachable service
* Port-based forwarding
* A network entry point for an ingress controller

#### Use Ingress or Gateway API for Layer 7

Use an Ingress controller or Gateway API implementation when you need:

* Host-based or path-based routing
* Multiple HTTP services behind one endpoint
* TLS termination and certificate handling
* Redirects, rewrites, authentication, or header policies
* Centralized HTTP traffic management

An Ingress resource has no effect unless an Ingress controller is installed. Review the documentation for the controller or Gateway implementation enabled on your cluster.

### Before you begin

Confirm that:

* Your KKS cluster is running.
* `kubectl` is configured for the cluster.
* The target workload is running and has stable labels.
* Your account has sufficient load-balancer and network quota.
* Network policies and application-level access controls allow the required traffic.

### Create a LoadBalancer Service

Create a file named `web-load-balancer.yaml`:

```
apiVersion: v1
kind: Service
metadata:
  name: web-load-balancer
  namespace: default
  labels:
    app.kubernetes.io/name: web
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: web
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
```

Apply the manifest:

```
kubectl apply -f web-load-balancer.yaml
```

Watch for the assigned endpoint:

```
kubectl get service web-load-balancer --watch
```

The endpoint is ready when the `EXTERNAL-IP` column shows an IP address or hostname instead of `<pending>`.

Inspect detailed status and events:

```
kubectl describe service web-load-balancer
```

### Understand Service ports

| Field        | Purpose                                                                                                                                 |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `port`       | The port exposed to clients through the Service.                                                                                        |
| `targetPort` | The port on which the application container accepts traffic.                                                                            |
| `protocol`   | The transport protocol, normally `TCP` or `UDP`.                                                                                        |
| `selector`   | Labels used to identify the Pods that receive traffic.                                                                                  |
| `nodePort`   | A node-level port allocated automatically when the load-balancer implementation requires it. Usually, you should not set this manually. |

For the preceding example, clients connect to port `80`, and the Service forwards traffic to port `8080` on matching Pods.

### Restrict access by client IP range

Use `spec.loadBalancerSourceRanges` to allow only specified client networks:

```
apiVersion: v1
kind: Service
metadata:
  name: restricted-api
spec:
  type: LoadBalancer
  loadBalancerSourceRanges:
    - 203.0.113.0/24
    - 198.51.100.10/32
  selector:
    app.kubernetes.io/name: api
  ports:
    - name: https
      protocol: TCP
      port: 443
      targetPort: 8443
```

Support for source ranges depends on the load-balancer capability enabled for the cluster. Also apply appropriate authentication, authorization, and network policies; source ranges are not a replacement for application security.

### Control external traffic routing

The `externalTrafficPolicy` field controls how nodes route traffic received from outside the cluster.

#### Cluster policy

`Cluster` is the default. Traffic can be routed to ready endpoints anywhere in the cluster.

```
spec:
  type: LoadBalancer
  externalTrafficPolicy: Cluster
```

Use `Cluster` when even traffic distribution and broad endpoint availability are more important than retaining the original client IP at the application.

#### Local policy

`Local` routes traffic only to ready endpoints on the node that receives it and can preserve the original client source IP.

```
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
```

Use `Local` only when the application requires the client IP. Ensure that the workload has enough replicas and is distributed across eligible nodes. Traffic sent to a node with no local ready endpoint can be dropped, and distribution across Pods can become uneven.

### Configure session affinity

For client-IP-based session affinity, use the standard Service fields:

```
apiVersion: v1
kind: Service
metadata:
  name: session-api
spec:
  type: LoadBalancer
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  selector:
    app.kubernetes.io/name: session-api
  ports:
    - name: tcp
      protocol: TCP
      port: 443
      targetPort: 8443
```

Session affinity can concentrate traffic on a subset of Pods. Prefer stateless applications when possible, and store session data in a shared external store.

### Health and readiness

KKS manages infrastructure-level load-balancer checks. At the application layer, configure Kubernetes readiness probes so that Pods receive Service traffic only when they are ready.

Example Deployment fragment:

```
spec:
  template:
    spec:
      containers:
        - name: web
          image: example/web:1.0
          ports:
            - name: http
              containerPort: 8080
          readinessProbe:
            httpGet:
              path: /healthz
              port: http
            initialDelaySeconds: 5
            periodSeconds: 10
            timeoutSeconds: 2
            failureThreshold: 3
```

Choose a readiness endpoint that verifies whether the application can serve traffic. Do not make the probe depend on slow or unreliable external systems unless that dependency is essential for serving requests.

Check Service endpoints:

```
kubectl get endpointslice -l kubernetes.io/service-name=web-load-balancer
```

### Use a LoadBalancer with an Ingress controller

For HTTP and HTTPS applications, the recommended pattern is:

1. Expose the ingress controller through one `LoadBalancer` Service.
2. Expose application workloads through `ClusterIP` Services.
3. Create Ingress resources to route hosts and paths to those Services.
4. Configure TLS at the ingress layer.

This pattern lets multiple applications share one external endpoint and keeps HTTP routing separate from Layer 4 service exposure.

### Change the Service type

Changing a Service from `LoadBalancer` to `ClusterIP` or `NodePort` starts cleanup of the managed load balancer and releases its endpoint.

Edit the manifest and reapply it:

```
spec:
  type: ClusterIP
```

```
kubectl apply -f web-load-balancer.yaml
```

If you later change the Service back to `LoadBalancer`, KKS provisions a new endpoint. The address may differ from the previous one, so verify and update DNS records and client configuration.

Before reusing older manifests, remove legacy infrastructure-specific annotations. Keep only fields supported by Kubernetes and options explicitly documented for KKS.

### Delete a LoadBalancer Service

Delete the Service when it is no longer required:

```
kubectl delete service web-load-balancer
```

Kubernetes and KKS then clean up the managed load-balancer resources. Remove or update DNS records that reference the released endpoint.

### Troubleshooting

#### Endpoint remains pending

Check the Service and its events:

```
kubectl get service web-load-balancer -o wide
kubectl describe service web-load-balancer
```

Common causes include:

* Load-balancer or network quota is exhausted.
* The Service manifest contains an unsupported field or annotation.
* The requested port or protocol is not supported.
* Cluster networking is not ready.
* Platform provisioning is temporarily unavailable.

Record the Service YAML and Events section before contacting Krutrim support.

#### Endpoint exists but the application is unreachable

Verify the selected Pods and endpoints:

```
kubectl get pods -l app.kubernetes.io/name=web -o wide
kubectl get endpointslice -l kubernetes.io/service-name=web-load-balancer
```

Then check:

* The Service selector matches the workload labels.
* `targetPort` matches the application's listening port.
* Pods are Ready and the readiness probe succeeds.
* The application listens on the Pod interface, not only on `127.0.0.1`.
* `loadBalancerSourceRanges`, network policies, and application firewalls allow the client.
* With `externalTrafficPolicy: Local`, ready Pods run on eligible nodes.

Test from an allowed client network:

```
curl -v http://<LOAD_BALANCER_ADDRESS>:80/
```

#### The application does not see the original client IP

The default `externalTrafficPolicy: Cluster` can obscure the original source address. If the application requires the client IP, evaluate `externalTrafficPolicy: Local` and its availability and traffic-distribution tradeoffs.

For HTTP and HTTPS, an Ingress controller can also propagate client information through trusted forwarding headers. Configure trusted proxy ranges carefully so that clients cannot spoof those headers.

### Best practices

* Use `LoadBalancer` Services for Layer 4 entry points and Ingress or Gateway API for Layer 7 routing.
* Consolidate multiple HTTP services behind an ingress controller when practical.
* Use private exposure for internal-only applications.
* Restrict public endpoints to the smallest required source ranges.
* Configure readiness probes for every production workload.
* Use multiple replicas and distribute them across nodes or zones.
* Prefer `externalTrafficPolicy: Cluster` unless source-IP preservation is required.
* Avoid the deprecated `spec.loadBalancerIP` field.
* Do not copy undocumented annotations or infrastructure identifiers into manifests.
* Monitor Service events, endpoint readiness, latency, error rate, and connection count.
* Delete unused Services to release endpoints and quota.
* Expect a new endpoint after deleting and recreating a Service; use DNS rather than embedding an address in clients.

### Standard Service fields

| Field                           | Use                                                                    |
| ------------------------------- | ---------------------------------------------------------------------- |
| `spec.type`                     | Set to `LoadBalancer` to request a managed load balancer.              |
| `spec.ports`                    | Defines the client-facing port, target port, and protocol.             |
| `spec.selector`                 | Selects the application Pods.                                          |
| `spec.loadBalancerSourceRanges` | Restricts accepted client CIDR ranges when supported by the platform.  |
| `spec.externalTrafficPolicy`    | Selects cluster-wide or node-local routing for external traffic.       |
| `spec.sessionAffinity`          | Enables client-IP session affinity when set to `ClientIP`.             |
| `spec.sessionAffinityConfig`    | Configures the client-IP affinity timeout.                             |
| `spec.ipFamilyPolicy`           | Requests single-stack or dual-stack behavior supported by the cluster. |

Settings such as private/public scope, infrastructure health-check intervals, connection limits, listener behavior, and load-balancing algorithms are implementation-dependent. Use only options explicitly documented and supported by KKS.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.cloud.olakrutrim.com/basics/core-infrastructure/krutrim-kubernetes-system/load-balancers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
