9 July 2026 · 9 min read · recloud engineering

Running FreeRADIUS on Kubernetes: subscriber AAA at scale

RADIUS is the quiet dependency of every ISP: if it stops answering, your BNG stops bringing subscribers online. Moving it onto Kubernetes gives you rollbacks, canaries and real monitoring — but RADIUS predates the cloud-native world by two decades, and it shows. Here is what actually matters when you containerise subscriber AAA.

The UDP problem

RADIUS runs over UDP, and NAS devices identify clients by source IP and shared secret. Two consequences:

  • The NAS must see a stable server address. Expose FreeRADIUS through a LoadBalancer service with a pinned address (MetalLB pool or equivalent) rather than a NodePort that moves.
  • Replies must leave from the address the request arrived on. Set externalTrafficPolicy: Local so kube-proxy doesn't SNAT the request and break the return path — it also preserves the NAS source address for your clients.conf matching.
apiVersion: v1
kind: Service
metadata:
  name: radius
  annotations:
    metallb.universe.tf/address-pool: radius-vips
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - { name: auth, port: 1812, protocol: UDP }
    - { name: acct, port: 1813, protocol: UDP }
  selector: { app: freeradius }

Where the BNG lives on a directly attached VLAN, a Multus secondary interface (covered in the bare-metal article) is simpler still: the pod owns a real address on the AAA VLAN and Kubernetes handles everything else.

Authentication is stateless. Accounting is not.

Access-Request handling scales horizontally without drama: three replicas behind the same VIP, each hitting the same subscriber database, is a fine design. Accounting is the part that punishes casual scaling — Interim-Updates arrive continuously for every online session, and you must not lose Stop records if you bill on usage.

The pattern we deploy: FreeRADIUS writes accounting to a queue instead of straight into SQL.

# sites-enabled/default (accounting section)
accounting {
    # fire-and-forget into a local buffer, workers drain to Kafka/SQL
    detail
    sql_kafka
}

A consumer service then owns the database write, dedupes on Acct-Unique-Session-Id, and can be redeployed freely without dropping packets — the queue absorbs the gap. It also gives your monitoring a beautiful signal: consumer lag tells you instantly when accounting is falling behind.

Health checks that mean something

A TCP connect check tells you nothing about a UDP daemon. Probe RADIUS with RADIUS — radclient sending a Status-Server request:

livenessProbe:
  exec:
    command: ["/usr/bin/radclient-probe.sh"]  # Status-Server to 127.0.0.1:18121
  periodSeconds: 10
  failureThreshold: 3

Pair it with a readiness probe that also checks the subscriber database connection: a FreeRADIUS pod that can't reach its datastore should stop receiving traffic before it starts rejecting subscribers.

Monitoring the thing that matters

Export per-pod counters (accepts, rejects, latency histograms) via the FreeRADIUS status server into Prometheus, then alert on the ratios, not the absolutes: a spike in Access-Reject with steady Access-Request volume is a config or datastore problem; both dropping together means the network in front of you is the problem. Graph online session count from your accounting pipeline next to BNG session counts from SNMP — when those diverge, you have silent accounting loss.

Rollouts without dropped subscribers

With externalTrafficPolicy: Local, a terminating pod means its node stops being a valid backend — so use maxUnavailable: 0, maxSurge: 1 rolling updates and a preStop sleep long enough for the LB withdrawal to propagate. NAS retransmission covers the last in-flight packets. Subscribers already online are untouched throughout: sessions live on the BNG, not in RADIUS.

Need a hand with this in production?

recloud is a group of software and network engineers specialising in Cisco Systems and Juniper, working with Australian ISPs, network operators and enterprises. See BNG and subscriber access services, Kubernetes services. Or contact us.