---
title: "Load balancers"
description: "Gateways and load balancers on your own servers, with an IPv4 and IPv6 address pair, a wildcard certificate and DNS records in one plan, routes from your Git, and Frazer Shield at the edge."
url: https://frazer.ai/docs/load-balancers
index: https://frazer.ai/docs/llms.txt
tokens: 4194
---

> For agents: this page is indexed at https://frazer.ai/docs/llms.txt, and every page at https://frazer.ai/llms.txt. Copy commands from this file exactly.

# Load balancers

Load balancers put your services on addresses at your own sites. A cluster’s gateway is one plan: an IPv4 and an IPv6 address from your site, a wildcard certificate and the DNS records come with it, and every `LoadBalancer` Service in a project cluster gets its address the same way. Routes stay a few lines in your Git, your services see the client’s real IP address, and Frazer Shield guards every gateway.

Product overview: [Load balancers](https://frazer.ai/network/gateways).

## How it works

Creating a gateway reserves an address pair, binds it to the gateway’s Service, renders its listeners with a certificate and writes the DNS records. A request then takes a short path: to the address on your server, through an L4 load balancer that keeps the client’s IP, into the cluster’s gateway, where TLS ends and your route picks the service.

Frazer runs a cloud controller manager in every project cluster. It talks to the Frazer API with the cluster’s own identity, turns every `LoadBalancer` Service into a Frazer load balancer, and is the only component that may write address pools in the cluster, so every address has one owner and a reason.

| Kind | Frontend | How it is served |
| --- | --- | --- |
| Gateway | An external address pair from the site’s pool | The cluster’s gateway (Gateway API), rendered from the gateway resource |
| `Service type=LoadBalancer` | An address from the site’s pool or a subnet | An L4 load balancer from the cloud controller manager; backends are node ports or pod IPs |
| External L4 passthrough | An external address | Health-checked, on the network’s gateway router; the client IP is kept |
| Internal L4 (TCP, UDP) for VMs | An internal address in a subnet | Distributed across the hosts, with no proxy hop |
| External L7 (HTTP/S, gRPC, WebSocket) for VMs | An external address and a certificate | A Frazer-run L7 gateway at each site, with a security policy |
| gRPC between services | None: the client balances | `frazer-xds` hands proxyless gRPC clients the ready pods of each Service: no sidecar, no extra hop |

-   **Gateway**: a Frazer resource for a cluster, because it uses things outside the cluster: an address, a certificate and DNS records. Every cluster has two: `public`, and `ops`, which serves tools such as Frazer GitOps behind Frazer sign-in.
-   **Listener**: a hostname on a gateway, its certificate, and the environments that may attach routes to it.
-   **Route**: an `HTTPRoute` rendered from a few lines in a service’s values in Git and applied by the cluster’s Frazer GitOps.
-   **Address pair**: one IPv4 and one IPv6 address. `ip_families` is `[IPV4, IPV6]` by default; `[IPV4]` or `[IPV6]` on request.
-   **Security policy**: Frazer Shield rules attached to a gateway, a load balancer, a serverless service or an address.

Every gateway also answers on a default hostname under `frazer.run`, a domain kept apart from `frazer.ai`, so your content never shares cookies with the console. Every hostname works direct; your own Cloudflare in front is an option per gateway.

## Add a gateway

### CLI

1.  Create the gateway for the cluster:
    
    ```sh
    frazer kubernetes gateways create public --cluster acme-staging-1
    ```
    
2.  Read the plan. The CLI asks before it applies:
    
    ```text title="Output"
    Address   + 203.0.113.18 · 2001:db8:8d10::18 · ovh-vint-hill
    Bind      /32 and /128 pools for the gateway's Service
    Listener  https *.staging.acme.example · http → https
    Cert      wildcard-staging · public ACME CA · DNS-01
    DNS       A + AAAA to the pair · *.staging CNAME
    ? Apply? yes   ✓ Accepted · Programmed
    ```
    
3.  Check the hostname. The gateway’s page in the console shows each hostname with its DNS and TLS checks:
    
    ```text title="Console"
    Hostname  *.staging.acme.example · DNS check ✓ · TLS check ✓
    ```
    

### Console

1.  Open the project, then **Network › Gateways and routes**, and add a gateway to the cluster.
    
2.  Read the plan beside the form, with the same gateway as YAML:
    
    ```yaml title="gateway.yaml"
    name: public
    exposure: direct # direct | cloudflare (optional edge)
    addresses: ["203.0.113.18", "2001:db8:8d10::18"]
    listeners:
      - name: https
        hostname: "*.staging.acme.example"
        certificate: wildcard-staging
        environments: [staging] # who may attach routes
    certificates:
      - name: wildcard-staging
        dnsNames: ["*.staging.acme.example"]
        issuer: acme-dns
    ```
    
3.  Apply it. The gateway’s page shows each hostname with its DNS and TLS checks.
    

### Add a route

Routes live in your environment repository, next to the service.

1.  List the hostnames in the service’s values:
    
    ```yaml title="envs/staging/apps/gateway-rest/api/values.yaml"
    gateway:
      enabled: true
      hostnames: [api.staging.acme.example]
    paths:
      base: /
    ```
    
2.  Merge the change. The chart renders an `HTTPRoute`, and the cluster’s Frazer GitOps applies it:
    
    ```yaml title="Rendered by the chart"
    kind: HTTPRoute
    metadata: { name: api-gw-rest, namespace: acme }
    spec:
      parentRefs:
        - { name: public, namespace: gateway-system, sectionName: https }
      hostnames: [api.staging.acme.example]
      rules:
        - backendRefs: [{ name: api-gw-rest, port: 8443 }]
    ```
    
3.  Check the route in **Network › Gateways and routes**. A policy in the cluster admits only hostnames the environment may claim, and the console shows every route with its status, and with the reason when it is refused, its certificate is pending or its DNS record is missing.
    

## Expose a Service with a load balancer

Any `Service` of type `LoadBalancer` in a project cluster gets an address and an L4 load balancer:

```yaml title="service.yaml"
apiVersion: v1
kind: Service
metadata:
  name: etl-ingest
  namespace: acme
spec:
  type: LoadBalancer
  selector:
    app: etl-ingest
  ports:
    - port: 443
      targetPort: 8443
```

The cloud controller manager creates the load balancer through the Frazer API and reports its address back to the Service’s status. **Network › Load balancers** shows every load balancer with its owner, its frontends in both families, the L4 hop with its health check, the backends that serve and, for a gateway, the certificate with its expiry.

Setting an address in a Service yourself does nothing: only addresses bound through Frazer are served. To keep a static address, reserve it and use **Attach to…** in **Network › IP addresses**, which lists gateways, `LoadBalancer` Services and VMs and shows the plan.

## Choose addresses

A gateway reserves its address pair when you create it. To give it an address you already hold, attach the address; the plan shows the change:

```sh
frazer network addresses attach web --gateway acme-staging-1/gateway-system/public
```

Or bind it from Git with the annotation `frazer.ai/address: web` on the gateway; the console then shows the address as managed by Git, read-only.

-   **Address families.** With `ip_families` set to `[IPV4, IPV6]`, the default, a load balancer has one frontend per family; an internal load balancer gets an IPv6 ULA frontend next to its IPv4 one. A gateway with `[IPV4]` answers A records only, and the console says why.
-   **Ephemeral addresses.** A gateway with no bound address gets an ephemeral one if the project allows it. **Promote** makes it static in place.
-   **Deleting.** An address that is still attached cannot be deleted, and the error names what uses it. A released address is quarantined for 24 hours before it returns to your site’s pool.

Reserving, moving and pricing addresses: [VPC and firewall](https://frazer.ai/docs/network#reserve-and-attach-addresses).

## Use your own domain

For your own domain, pick how its records are kept. Every way includes a certificate.

| Way | How | Certificates |
| --- | --- | --- |
| Delegate a subdomain to Frazer DNS | Point `apps.acme.example` at Frazer’s name servers. Frazer writes the records from your gateways and routes. | DNS-01 inside the zone, through a solver that may only answer challenges |
| Keep your DNS provider | The cluster’s DNS controller and certificate manager run with your provider’s token, kept in your project’s secrets and limited to one zone. | DNS-01 at your provider |
| Manage records yourself | The console shows the exact A, AAAA and CNAME records to add. | One `_acme-challenge` CNAME into Frazer’s challenge zone, so no provider token is needed |

The cluster’s certificate manager issues a wildcard certificate for each listener over DNS-01. A public ACME certificate authority is the default issuer, and issuance falls back to a second ACME authority when the first one is down. A failed renewal or a certificate close to expiry emails the project’s admins, and **Network › Certificates** lists every certificate with its expiry.

Zones, records and DNSSEC: [DNS and certificates](https://frazer.ai/docs/dns).

## Protect a gateway with Frazer Shield

Frazer Shield is edge security built into Frazer; a third-party proxy is never required. Every gateway gets baseline protection: a managed OWASP Core Rule Set preset, network edge filtering, default rate limits and threat lists. Write a security policy for anything more.

A security policy belongs to a project. Organization policies are evaluated first, and `goto_next` hands a decision down, as in the [firewall](https://frazer.ai/docs/network#write-firewall-rules). A policy has a type:

-   `BACKEND`: enforced by the gateway or load balancer.
-   `NETWORK_EDGE`: enforced at the network edge for an address: by OVH’s edge firewall for IPv4 at OVH sites, and by the hosts’ own packet filters for both families. For IPv6, the hosts’ filters are the whole edge.
-   `EDGE`: pushed to your own Cloudflare account.

Each rule has a priority, a match, an action and a **preview** switch.

-   **Match**: source IP ranges, address groups, or an expression over `origin.ip`, `origin.region_code`, `origin.asn`, `request.method`, `request.path`, `request.headers`, `request.query`, `tls.ja4`, `tls.ja3`, `token.org` and `token.principal_type`.
-   **Actions**: `allow`, `deny` (with 403, 404, 429 or 502), `throttle`, `rate_based_ban`, `challenge`, `redirect` and `log`.
-   **Rate limits**: a window from 10 to 3,600 seconds, up to three keys (IP, `ALL`, `HEADER`, `COOKIE`, `PATH`, `SNI`, `REGION_CODE`, `ASN`, `JA4`, `USER_IP`, `ORG_CLAIM`), a threshold and a ban duration. An IP key counts IPv4 by `/32` and IPv6 by `/64`, never by single IPv6 address.
-   **WAF**: the OWASP Core Rule Set through a function, with a sensitivity that matches the rule set’s paranoia level. `-stable` rule sets follow the long-term-support release, `-canary` the latest.

```text title="Match expressions"
origin.asn == 64500
evaluatePreconfiguredWaf('sqli-v4252-stable', {'sensitivity': 2})
evaluateThreatIntelligence('iplist-tor-exit-nodes')
```

> **Tip:** Start a new rule in preview. It logs what it would have done (`preview_outcome`) and lets the request through, so you see false positives before the rule enforces.

Every decision is a record in your project’s logs: every deny and every preview match, with allows sampled at 1 %. The metric `frazer_shield_requests_total` counts requests by policy, rule, outcome and preview. Adaptive protection, opt-in per policy, proposes rules from traffic baselines and can deploy them through preview with a time limit. **Attack mode** is one audited switch per gateway or organization: it enforces adaptive rules, challenges unauthenticated HTML routes and tightens limits.

## Access and audit

| Who | What they can do |
| --- | --- |
| Project admins | Create, change and delete gateways and addresses, each as a plan. Attaching an address needs `addresses.use`. |
| Developers | Add routes in their service’s values through a pull request. A policy refuses hostnames their environment may not claim. |
| The cloud controller manager | The only writer of address pools in a cluster. Frazer Policy refuses anyone else. |
| The certificate solver | May write only `_acme-challenge` records (`roles/dns.acmeSolver`), so a leaked token can only answer challenges. |

What is recorded:

-   Every gateway change: a plan, then a numbered revision. Every security policy change is a plan too.
-   Every route with its status, and the reason when it is refused, its certificate is pending or its DNS is missing.
-   Failed renewals and expiring certificates, emailed to project admins.
-   Shield decisions in your project’s logs, and every switch of attack mode.

## Limits and quotas

| Limit | Default |
| --- | --- |
| Gateways per cluster, created with it | 2: `public` and `ops` |
| Public IPv4 addresses per project and region | 2 |
| Public IPv6 addresses per project and region | 64 |
| Quarantine of a released address | 24 hours |
| Security policies per project | 10 |
| Rules per security policy | 200 |
| Rate-limit rules | 50 |
| Address-group entries | 1,000 |
| Rules deployed by adaptive protection | 20 |
| Rate-limit window | 10 to 3,600 seconds |
| Keys per rate-limit rule | 3 |

## Pricing

Gateways, load balancers and certificates have no fee of their own, and there are no per-GB fees within fair use. Baseline Shield protection is included on every gateway; custom security policies are billed per policy and per rule, with no fee per request. Public IPv4 addresses are billed per address each month, and IPv6 addresses are free.

| Load balancers | On your servers | On the Frazer fleet |
| --- | --- | --- |
| Price | **Included**, any number · Shield baseline on every gateway | **Included** · no LCU or per-GB fee |
| Shield custom rules | $3 per policy / month + $0.50 per rule / month · first 5 rules per organization free · no request fee | Same · no request fee |

Every line, with the estimator: [pricing](https://frazer.ai/pricing#lines).

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| A route shows as refused | Its hostname is not one the environment may claim on that listener | Use a hostname under the listener’s name, or add the environment to the listener’s `environments`. |
| A hostname’s certificate stays pending | The DNS-01 challenge cannot be answered | Check the way your domain is kept: the zone’s delegation, your provider token’s zone, or the `_acme-challenge` CNAME. |
| A hostname’s DNS check fails | The A and AAAA records are missing or point elsewhere | Add the records the console shows, or let Frazer DNS or the cluster’s DNS controller write them. |
| A `LoadBalancer` Service gets no address | The address it asks for is not bound to it, or the project is at its address quota | Reserve an address and attach it to the Service, or release one you no longer use. |
| An address cannot be deleted | It is still attached | Detach it from the gateway, Service or VM that the error names. |
| A Shield rule blocks legitimate requests | The match is too wide | Put the rule in preview, read the `preview_outcome` records in your logs, and narrow the match. |
| A hostname answers only over IPv4 | The gateway’s `ip_families` is `[IPV4]` | Set `ip_families` to `[IPV4, IPV6]`; IPv6 addresses are free. |

## Reference

### CLI

| Command | What it does |
| --- | --- |
| `frazer kubernetes gateways create` | Create a gateway for a cluster, with an address pair, a certificate and DNS records in one plan. |

All of them: [CLI reference](https://frazer.ai/docs/cli).

### Terraform and OpenTofu

| Resource | What it manages |
| --- | --- |
| `frazer_network_load_balancer` | A load balancer with its frontends, address families, backends, health check and security policy. |
| `frazer_network_security_policy` | A Frazer Shield security policy and its rules. |

All of them: [Terraform and OpenTofu reference](https://frazer.ai/docs/terraform).

## Related

-   [VPC and firewall](https://frazer.ai/docs/network): addresses, IP pools, NAT and the firewall.
-   [DNS and certificates](https://frazer.ai/docs/dns): zones, records and DNSSEC for your domains.
-   [Kubernetes](https://frazer.ai/docs/kubernetes): the clusters that gateways belong to.
-   [Environments and GitOps](https://frazer.ai/docs/gitops): where your routes live.
-   [Create a Kubernetes cluster](https://frazer.ai/docs/quickstarts/kubernetes-cluster): a cluster with its two gateways.
-   [Load balancers](https://frazer.ai/network/gateways): the product page.

## Pages in Network

- [VPC and firewall](https://frazer.ai/docs/network.md)
- [Load balancers](https://frazer.ai/docs/load-balancers.md) (this page)
- [DNS and certificates](https://frazer.ai/docs/dns.md)
- [Frazer Access and VPN](https://frazer.ai/docs/access.md)
