i'm selfhosting LiveKit SFU in a e2-standard-2 (2v...
# ask-ai
a
i'm selfhosting LiveKit SFU in a e2-standard-2 (2vCPUs, 4GB) inside a GKE cluster, right now i limited that node to just one replica but im already starting to see it getting spikers around 80% CPU usage at times but only 25~30% memory usage, should i allow more replicas and it will immediately allow to handle more rooms or what's the recommendation here?
t
Thanks for reaching out, Sebastián. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — that’s helpful context. You’re asking whether adding replicas will immediately let you handle more rooms given CPU spikes on a single e2-standard-2 node. I’ll address that directly and give practical recommendations. Short answer • Yes. Scaling out (adding SFU replicas) is the normal way to handle more rooms: new rooms will be placed on other replicas and that will reduce per-node CPU load. CPU is the bottleneck in your case since memory is low, so adding replicas should help. What happens when you add replicas • Each room is served by a single SFU instance, so additional replicas let the cluster distribute new rooms across nodes rather than concentrating them on one node. • That distribution reduces CPU pressure per node and increases total concurrent-room capacity for the cluster. Practical recommendations 1. Scale horizontally first ◦ Start by increasing replicas to 2–4 and monitor CPU per pod. This will quickly show whether horizontal scaling solves the spikes. 1. Monitor key metrics ◦ Observe pod CPU usage (not just node averages), room count per pod, connection/stream counts, and P95/P99 CPU. These tell you if load is balancing as expected. 1. Check load balancing/session affinity ◦ Ensure your Service/Ingress does not enforce stickiness for new room assignments. New rooms should be able to land on the least busy replica. 1. Ensure distributed configuration ◦ When running multiple SFU instances, use the required shared message bus for server coordination (e.g., Redis) so room metadata and signaling work correctly across replicas. 1. Consider vertical scaling if needed ◦ If individual rooms are very heavy (many participants, high-resolution video, many simultaneous publishers), a larger machine (more vCPUs) per replica may be needed in addition to scaling out. 1. Use bandwidth/CPU optimizations ◦ Enable simulcast and adaptive streaming where possible to reduce per-publisher CPU and bandwidth load for heavy rooms. 1. Capacity testing ◦ Run load tests that mimic your typical room sizes and publisher counts to validate how many rooms a pod/node can handle before CPU is saturated. Next steps I can help with • If you want, tell me: ◦ How many concurrent rooms and average participants per room you see now. ◦ Whether rooms are mostly video, audio-only, or mixed. ◦ Your current SFU deployment manifest (replica count, Service type). I can suggest an initial replica count, pod resource requests/limits, and a short monitoring checklist to validate the change. Would you like help estimating an initial replica count based on your current room/participant numbers? Sources: Server lifecycle | LiveKit Documentation | How We Built a Globally Distributed WebRTC Mesh Network | Bringing Zoom's end-to-end optimizations to WebRTC
a
we have voice only, two participants (agent and client) and around 12 rooms simultaneous (and around the same 12 draining down probably)
t
Thanks — that additional detail is perfect. You’re running voice-only rooms with 2 participants each and ~12 concurrent rooms (with similar churn). That changes the guidance: voice-only, two-party rooms are much lighter than multi-video rooms, so CPU per room is low and horizontal scaling should be straightforward. Here’s a concise, practical plan you can try. Immediate action (fast, low-risk) 1. Increase replicas to 2–3 ◦ Start with 2 replicas; if CPU per pod still approaches 70–80% under typical load, move to 3. ◦ This will immediately allow new rooms to be placed on the other pods and should reduce CPU spikes. Pod sizing guidance • Keep using your current e2-standard-2 nodes for now (2 vCPU, 4 GB) because voice-only, 2‑participant rooms are lightweight. • If you later host many more concurrent rooms or heavier rooms, consider moving some pods to larger instance types (e.g., more vCPUs). Kubernetes scaling and resource settings 1. Set conservative resources on the SFU pod spec: ◦ Request CPU roughly equal to what a single replica needs under typical load, and set a CPU limit to cap runaway usage. ◦ Example approach: if your single pod currently hits 80% on a 2‑vCPU node, set requests to 0.5–1.0 CPU and limits to 1.5–2.0 CPU (adjust after monitoring). 1. Use a Horizontal Pod Autoscaler (HPA) ◦ Configure HPA on CPU usage (e.g., target 50–60% per pod) so pods autoscale when necessary. ◦ Start with minReplicas=2 and maxReplicas=5 (adjust later based on load). 1. Ensure the Service/Ingress allows even distribution ◦ Disable session affinity/stickiness for room creation so room traffic can be balanced across replicas. Operational checks and monitoring • Monitor per-pod CPU, room count per pod, and connection counts. Confirm rooms are distributed (no single pod holding most rooms). • Watch for P95/P99 CPU and pod restarts. • Track signaling/coordination errors (if any) after scaling. Required configuration for multi-node operation • Ensure your LiveKit servers share the messaging/state backend (for example, Redis) so multiple SFU instances coordinate properly across the cluster. Optimizations to consider (longer-term) • Voice-only benefits from lower bandwidth and CPU: make sure codecs/settings are appropriate for voice. • If you see sustained load growth, combine horizontal scaling with larger node types rather than only increasing replicas. Quick recommendation summary • Increase to 2 replicas now, monitor, and go to 3 if pods still hit ~70–80% CPU. • Add HPA targeting ~50–60% CPU with minReplicas=2, maxReplicas=5. • Ensure shared message bus is configured and service affinity is off. • Revisit vertical scaling only if individual rooms become heavier or total concurrency grows significantly. If you want, I can: • Suggest exact Kubernetes resource request/limit values if you share current pod CPU metrics (average and peak). • Draft an example HPA and pod resource snippet to apply to your deployment. Which would you prefer?
a
just to know, is the instance type correct or should be bigger?
t
Thanks — good question. You’re running voice-only, two-participant rooms with ~12 concurrent rooms and occasional CPU spikes to ~80% on an e2-standard-2 (2 vCPU, 4 GB). I’ll address whether the instance type is correct and give a clear recommendation. Short answer • Your current e2-standard-2 can likely handle 12 voice-only, two-party rooms, but it’s below the recommended baseline. Upgrading to a 4 vCPU / 8 GB instance is advised to provide headroom and more stable performance. Why I recommend a larger instance • The SFU’s CPU is the bottleneck in your setup (memory looks fine). The recommended configuration for LiveKit SFU deployments is 4 vCPUs and 8 GB RAM, which gives more headroom for signaling, media routing, and transient spikes. • Even voice-only rooms generate CPU work for WebRTC and media forwarding; having the recommended capacity reduces the chance of hitting 70–80% CPU regularly and avoids degraded performance during bursty load. Practical guidance • Short term: You can scale horizontally (add replicas to 2–3) to spread load immediately while staying on e2-standard-2 nodes. That will reduce per-pod CPU pressure. • Medium term: Move at least some pods to 4 vCPU / 8 GB instances (or use larger node pools) so each SFU pod has the recommended baseline. This is especially useful if you want predictable performance or expect concurrency to grow. • Use autoscaling: Combine vertical sizing with Horizontal Pod Autoscaler (target ~50–60% CPU per pod) so you get both headroom and dynamic scaling. If you want, I can: • Suggest specific Kubernetes resource requests/limits for your pods based on current CPU averages/peaks (share current pod CPU metrics if available). • Draft an example plan: start with replica=2 on current nodes, add one 4vCPU/8GB node pool and move one pod there to compare behavior. Which of those would you like help with? Sources: Self-hosted deployments | LiveKit Documentation
a
yes please
t
Great — I can help with both options. Which of these would you like me to prepare first? • I. Suggested Kubernetes resource requests/limits and an example Deployment + HPA snippet tuned to your current load (I’ll base values on typical voice-only, 2‑participant rooms). If you want more accuracy, share current pod CPU metrics (average and peak % or mCPU over a 5–15 minute window). • II. A migration plan to introduce a 4 vCPU / 8 GB node pool in GKE and a short rollout strategy (move one pod to the new node type, compare behavior, then migrate remaining pods or adjust replica count). If you pick I, tell me: • Current pod CPU usage in mCPU or % (average and peak), if available. • Current Deployment manifest (replica count, CPU requests/limits if set). If you pick II, tell me: • Whether you use node pools today and whether you’re comfortable creating a new node pool (yes/no). • Any constraints on rolling updates (times when you can or cannot disrupt pods). I can also provide both — resource snippet first, then a migration plan — if you prefer. Which would you like?
a
how to match the agent server cpu load value and k8s HPA measuring
t
Thanks — that’s a great question. You want the LiveKit agent server’s CPU load value to line up with what the Kubernetes HPA uses so autoscaling behaves predictably. I’ll explain how the two relate and give actionable steps and an example HPA approach to make them match. How the two metrics relate • LiveKit agent server load: uses overall CPU utilization (a float 0..1) over a short window (default ~5s) as its load function. This represents fraction of CPU capacity used by the process. • Kubernetes HPA (CPU): uses CPU utilization percentage, calculated as container CPU usage divided by the container CPU requests (reported by the metrics provider, e.g., Metrics Server). HPA target is expressed as a percentage of the requested CPU. Goal: make both speak the same language — CPU utilization relative to the pod’s requested CPU. Steps to match them reliably 1. Configure pod CPU requests and limits ◦ Set a realistic CPU request for your SFU container that reflects steady-state expected usage. The HPA percentage is computed against this request. ◦ Example starting values for voice-only load: Request = 500m (0.5 CPU), Limit = 1500m (1.5 CPU). Adjust after monitoring. 1. Ensure HPA uses CPU utilization (not a custom metric) ◦ Configure HPA with
metrics: type: Resource
and
name: cpu
so it targets CPU utilization %. 1. Pick complementary thresholds ◦ LiveKit agent load threshold (default 0.7) means the server considers itself "busy" at ~70% CPU. ◦ Set HPA target lower than that so HPA starts adding pods before LiveKit hits its threshold. Common choice: HPA target = 50–60%. ◦ This gives headroom for pods to come up and cold-start before existing pods exceed 70–80%. 1. Validate with per-pod metrics ◦ Monitor actual container CPU usage in mCPU and as % of requests (average and P95/P99). ◦ Also monitor the LiveKit agent reported load value (if exposed) to confirm it tracks CPU utilization. 1. Optional: expose custom load metric (advanced) ◦ If you prefer autoscaling directly on LiveKit’s internal load metric, export it to a metrics endpoint (Prometheus) and use the HPA with custom/external metrics. This requires a metrics adapter and is more complex but gives exact parity. Example HPA strategy (conceptual) 1. Pod spec ◦ resources: requests: cpu: "500m" limits: cpu: "1500m" 1. HPA (CPU-based) ◦ target CPU utilization: 50% (this means scale when average usage across pods > 50% of 500m = 250m) ◦ minReplicas: 2 ◦ maxReplicas: 5 Why this works • With requests set, HPA % maps directly to the same denominator LiveKit uses (fraction of available CPU capacity). Setting HPA target below LiveKit’s busy threshold ensures autoscaling reacts early and avoids pods reaching 70–80% CPU. What I recommend you do next • If you want, share one of: ◦ Current pod CPU requests/limits and observed pod CPU (average and peak in mCPU or %). ◦ The value LiveKit exposes for the agent load (if you’re already scraping it). I’ll convert those into concrete request/limit values and an HPA YAML snippet tuned to your actual metrics. Would you like a ready-to-apply HPA and Deployment snippet based on the example values (500m/1500m, target 50%) or should I tune it to your real metrics? Sources: Self-hosted deployments | LiveKit Documentation