Monday, October 19, 2026
HomeArtificial IntelligenceScaling Kubernetes to 7,500 Nodes

Scaling Kubernetes to 7,500 Nodes

[ad_1]

We have scaled Kubernetes clusters to 7,500 nodes, producing a scalable infrastructure for giant fashions like GPT-3, CLIP, and DALLĀ·E, but additionally for fast small-scale iterative analysis resembling Scaling Legal guidelines for Neural Language Fashions. Scaling a single Kubernetes cluster to this measurement is never achieved and requires some particular care, however the upside is an easy infrastructure that permits our machine studying analysis groups to maneuver sooner and scale up with out altering their code.

Since our final submit on Scaling to 2,500 Nodes we have continued to develop our infrastructure to satisfy researcher wants, within the course of studying many extra classes. This submit summarizes these classes in order that others within the Kubernetes group can profit from them, and ends with issues we nonetheless face that we’ll be tackling subsequent.

Our Workload

Earlier than we get too far, it’s vital to explain our workload. The purposes and {hardware} we run with Kubernetes are fairly completely different from what chances are you’ll encounter at a typical firm. Our issues and corresponding options could, or could not, be a very good match to your individual setup!

A big machine studying job spans many nodes and runs most effectively when it has entry to all the {hardware} sources on every node. This enables GPUs to cross-communicate straight utilizing NVLink, or GPUs to straight talk with the NIC utilizing GPUDirect. So for a lot of of our workloads, a single pod occupies your complete node. Any NUMA, CPU, or PCIE useful resource rivalry aren’t components for scheduling. Bin-packing or fragmentation shouldn’t be a standard downside. Our present clusters have full bisection bandwidth, so we additionally don’t make any rack or community topology concerns. All of which means that, whereas we have now many nodes, there’s comparatively low pressure on the scheduler.

That stated, pressure on the kube-scheduler is spiky. A brand new job could encompass many a whole lot of pods all being created without delay, then return to a comparatively low price of churn.

Our largest jobs run MPI, and all pods inside the job are collaborating in a single MPI communicator. If any of the collaborating pods die, your complete job halts and must be restarted. The job checkpoints usually, and when restarted it resumes from the final checkpoint. Thus we think about the pods to be semi-stateful—killed pods may be changed and work can proceed, however doing so is disruptive and ought to be saved to a minimal.

We don’t depend on Kubernetes load balancing all that a lot. We have now little or no HTTPS site visitors, without having for A/B testing, blue/inexperienced, or canaries. Pods talk straight with each other on their pod IP addresses with MPI by way of SSH, not service endpoints. Service ā€œdiscoveryā€ is restricted; we simply do a one-time lookup for which pods are collaborating in MPI at job startup time.

Most jobs work together with some type of blob storage. They often both stream some shards of a dataset or checkpoint straight from blob storage, or cache it to a quick native ephemeral disk. We have now a couple of PersistentVolumes for instances the place POSIX semantics are helpful, however blob storage is way extra scalable and doesn’t require gradual detach/connect operations.

Lastly, the character of our work is essentially analysis, which suggests the workloads themselves are ever-changing. Whereas the Supercomputing workforce strives to supply what we’d think about a ā€œmanufacturingā€ high quality stage of compute infrastructure, the purposes that run on that cluster are short-lived and their builders iterate shortly. New utilization patterns could emerge at any time that problem our assumptions about traits and acceptable tradeoffs. We want a sustainable system that additionally permits us to reply shortly when issues change.

Networking

Because the variety of nodes and pods inside our clusters elevated, we discovered that Flannel had difficulties scaling up the throughput required. We switched to utilizing the native pod networking applied sciences for our IP Configurations for Azure VMSSes and the related CNI plugins. This allowed us to get host stage community throughput on our pods.

One more reason we have switched to utilizing alias-based IP addressing is that on our largest clusters, we may probably have roughly 200,000 IP addresses in use at anybody time. Once we examined route-based pod networking, we discovered there have been important limitations within the variety of routes we may successfully use.

Avoiding encapsulation will increase the calls for on the underlying SDN or routing engine, nevertheless it retains our networking setup easy. Including VPN or tunneling may be achieved with none extra adapters. We need not fear about packet fragmentation resulting from some portion of the community having a decrease MTU. Community insurance policies and site visitors monitoring is simple; there is not any ambiguity in regards to the supply and vacation spot of packets.

We use iptables tagging on the host to trace community useful resource utilization per Namespace and pod. This lets researchers visualize their community utilization patterns. Specifically, since loads of our experiments have distinct Web and intra-pod communication patterns, it is typically helpful to have the ability to examine the place any bottlenecks may be occurring.

iptables mangle guidelines can be utilized to arbitrarily mark packets that match explicit standards. Listed below are our guidelines to detect whether or not site visitors is inner or internet-bound. The FORWARD guidelines cowl site visitors from pods, vs INPUT and OUTPUT site visitors from the host:

iptables -t mangle -A INPUT ! -s 10.0.0.0/8 -m remark --comment "iptables-exporter openai site visitors=internet-in"
iptables -t mangle -A FORWARD ! -s 10.0.0.0/8 -m remark --comment "iptables-exporter openai site visitors=internet-in"
iptables -t mangle -A OUTPUT ! -d 10.0.0.0/8 -m remark --comment "iptables-exporter openai site visitors=internet-out"
iptables -t mangle -A FORWARD ! -d 10.0.0.0/8 -m remark --comment "iptables-exporter openai site visitors=internet-out"

As soon as marked, iptables will begin counters to trace the variety of bytes and packets that match this rule. You possibly can eyeball these counters by utilizing iptables itself:

% iptables -t mangle -L -v
Chain FORWARD (coverage ACCEPT 50M packets, 334G bytes)
 pkts bytes goal     prot choose in     out     supply               vacation spot
....
1253K  555M            all  --  any    any     wherever            !10.0.0.0/8           /* iptables-exporter openai site visitors=internet-out */
1161K 7937M            all  --  any    any    !10.0.0.0/8           wherever             /* iptables-exporter openai site visitors=internet-in */

We use an open-source Prometheus exporter referred to as iptables-exporter to then get these tracked into our monitoring system. This a easy method to monitor packets matching quite a lot of various kinds of situations.

One considerably distinctive facet of our community mannequin is that we absolutely expose the node, pod, and repair community CIDR ranges to our researchers. We have now a hub and spoke community mannequin, and use the native node and pod CIDR ranges to route that site visitors. Researchers hook up with the hub, and from there have entry to any of the person clusters (the spokes). However the clusters themselves can’t speak to at least one one other. This ensures that clusters stay remoted with no cross-cluster dependencies that may break failure isolation.

We use a “NAT” host to translate the service community CIDR vary for site visitors coming from exterior of the cluster. This setup permits our researchers important flexibility in selecting how and what sorts of community configurations they can select from for his or her experiments.

API Servers

Kubernetes API Servers and etcd are crucial elements to a wholesome working cluster, so we pay particular consideration to the stress on these methods. We use the Grafana dashboards supplied by kube-prometheus, in addition to extra in-house dashboards. We’ve discovered it helpful to alert on the speed of HTTP standing 429 (Too Many Requests) and 5xx (Server Error) on the API Servers as a high-level sign of issues.

Whereas some of us run API Servers inside kube, we’ve all the time run them exterior the cluster itself. Each etcd and API servers run on their very own devoted nodes. Our largest clusters run 5 API servers and 5 etcd nodes to unfold the load and reduce impression if one have been to ever go down. We’ve had no notable hassle with etcd since splitting out Kubernetes Occasions into their very own etcd cluster again in our final weblog submit. API Servers are stateless and usually straightforward to run in a self-healing occasion group or scaleset. We haven’t but tried to construct any self-healing automation of etcd clusters as a result of incidents have been extraordinarily uncommon.

API Servers can take up a good bit of reminiscence, and that tends to scale linearly with the variety of nodes within the cluster. For our cluster with 7,500 nodes we observe as much as 70GB of heap getting used per API Server, so fortuitously this could proceed to be well-within {hardware} capabilities into the longer term.

One massive pressure on API Servers was WATCHes on Endpoints. There are a couple of companies, resembling ā€˜kubelet’ and ā€˜node-exporter’ of which each node within the cluster is a member. When a node can be added or faraway from the cluster, this WATCH would hearth. And since usually every node itself was watching the kubelet service by way of kube-proxy, the # and bandwidth required in these responses can be $N^2$ and massive, often 1GB/s or extra. EndpointSlices, launched in Kubernetes 1.17, have been an enormous profit that introduced this load down 1000x.

Usually we’re very conscious of any API Server requests that scale with the dimensions of the cluster. We attempt to keep away from having any DaemonSets work together with the API Server. In instances the place you do want every node to observe for modifications, introducing an middleman caching service, such because the Datadog Cluster Agent, appears to be a very good sample to keep away from cluster-wide bottlenecks.

As our clusters have grown, we do much less precise autoscaling of our clusters. However we have now run into hassle often when autoscaling an excessive amount of without delay. There are lots of requests generated when a brand new node joins a cluster, and including a whole lot of nodes without delay can overload API server capability. Smoothing this out, even simply by a couple of seconds, has helped keep away from outages.

Time-Sequence Metrics with Prometheus and Grafana

We use Prometheus to gather time-series metrics and Grafana for graphs, dashboards, and alerts. We began with a deployment of kube-prometheus that collects all kinds of metrics and good dashboards for visualization. Over time we’ve added a lot of our personal dashboards, metrics, and alerts.

As we added increasingly more nodes, we struggled with the sheer quantity of metrics being collected by Prometheus. Whereas kube-prometheus exposes loads of helpful knowledge, a few of it we weren’t really ever , and a few was simply too granular to gather, retailer, and question successfully. We use Prometheus guidelines to ā€œdropā€ a few of these metrics from being ingested.

For some time we struggled with an issue the place Prometheus would eat increasingly more reminiscence till ultimately crashing the container in an Out-Of-Reminiscence error (OOM). This appeared to happen even after throwing monumental quantities of reminiscence capability on the utility. What’s worse was, when it did crash, it could take many hours on startup replaying write-ahead-log information earlier than it was usable once more.

Finally we tracked down the supply of those OOMs to be an interplay between Grafana and Prometheus, the place Grafana would use the /api/v1/collection API on Prometheus with a question of {le!=""} (Principally, ā€œgive me all of the histogram metricsā€). The implementation of /api/v1/collection was unbounded in each time and area—for a question with loads of outcomes, this is able to proceed to eat ever-more reminiscence and time. It additionally continues to develop even after the requester has given up and closed the connection. For us, there was by no means sufficient reminiscence, and Prometheus would ultimately crash. We patched Prometheus to comprise this API inside a Context to implement a timeout, which fastened it completely.

Whereas Prometheus crashed far much less typically, in instances once we did must restart it, WAL replay remained a problem. It will typically take many hours to replay by means of all WAL logs earlier than Prometheus was up gathering new metrics and servicing queries. With assist from Sturdy Notion, we discovered that making use of a GOMAXPROCS=24 had an enormous enchancment. Prometheus tries to make use of all cores when throughout WAL replay, and for servers with a lot of cores, the rivalry kills all efficiency.

We’re exploring new choices to extend our monitoring capability, described within the ā€œUnsolved issuesā€ part beneath.

Healthchecks

With a cluster this huge, we after all depend on automation to detect and take away misbehaving nodes from the cluster. Over time we have now constructed up a variety of healthcheck methods.

Passive Healthchecks

Some healthchecks are passive, all the time operating on all nodes. These monitor fundamental system sources resembling community reachability, unhealthy or full disks, or GPU errors. GPUs exhibit issues a variety of alternative ways, however a straightforward widespread one is an ā€œUncorrectable ECC error.ā€ Nvidia’s Information Heart GPU Supervisor (DCGM) instruments make it straightforward to question for this and a variety of different ā€œXidā€ errors. A method we monitor these errors is by way of dcgm-exporter to ingest the metrics into Prometheus, our monitoring system. It will seem because the DCGM_FI_DEV_XID_ERRORS metric and be set to the error code that has most just lately occurred. Moreover, the NVML Machine Question API exposes extra detailed details about the well being and operation of a GPU.

As soon as we detect an error, they’ll typically be fastened by resetting the GPU or system, although in some instances it does result in the underlying GPU needing to be bodily changed.

One other type of healthcheck tracks upkeep occasions from the upstream cloud supplier. Every of the foremost cloud suppliers expose a method to know if the present VM is due for an upcoming upkeep occasion that may ultimately trigger a disruption. The VM could have to be rebooted so an underlying hypervisor patch may be utilized or the bodily node swapped out for different {hardware}.

These passive healthchecks run continually within the background on all nodes. If a healthcheck begins failing, the node is robotically cordoned so no new pods are to be scheduled on the node. For extra critical healthcheck failures, we can even try a pod eviction to request all currently-running pods to exit instantly. It’s nonetheless as much as the pod itself, configurable by way of a Pod Disruption Finances, to determine if it needs to permit this eviction to happen. Finally, both in any case pods have terminated, or 7 days has elapsed (a part of our SLA), we are going to forcibly terminate the VM.

Energetic GPU checks

Sadly not all GPU issues manifest as error codes seen by means of DCGM. We’ve constructed up our personal library of checks that train GPUs to catch extra issues and be sure that the {hardware} and driver is behaving as anticipated. These checks can’t be run within the background—they require unique use of a GPU for a number of seconds or minutes to run.

We first run these checks on nodes upon boot, in a system we name ā€œpreflight.ā€ All nodes be a part of the cluster with a ā€œpreflightā€ taint and label utilized. This taint prevents regular pods from being scheduled on the node. A DaemonSet is configured to run preflight take a look at pods on all nodes with this label. Upon profitable completion of the take a look at, the take a look at itself removes the taint and label and the node is then accessible for common use.

We additionally then run these checks periodically through the lifetime of a node. We run this as a CronJob, permitting it to land on any accessible node within the cluster. That is admittedly a bit random and uncontrolled about which nodes get examined, however we’ve discovered that over time it gives adequate protection with minimal coordination or disruption.

Quotas & Useful resource Utilization

As we scaled up our clusters, researchers began to seek out themselves having issue getting all the capability that they have been allotted. Conventional job scheduling methods have loads of completely different options accessible to pretty run work between competing groups, which Kubernetes doesn’t have. Over time, we took inspiration from these job scheduling methods and construct a number of capabilities in a Kubernetes-native approach.

Staff taints

We have now a service in every cluster, “team-resource-manager” that has a number of capabilities. Its knowledge supply is a ConfigMap that specifies tuples of (node selector, workforce label to use, allocation quantity) for all the analysis groups which have capability in a given cluster. It reconciles this with the present nodes within the cluster, tainting the suitable variety of nodes with openai.com/workforce=teamname:NoSchedule.

ā€œteam-resource-managerā€ additionally has an admission webhook service, such that as every job is submitted, a corresponding toleration is utilized based mostly on the submitter’s workforce membership. Utilizing taints permits us to constrain the Kubernetes pod scheduler flexibly, resembling permitting a “any” toleration for decrease precedence pods, which permits groups to borrow one another’s capability with out requiring heavyweight coordination.

CPU & GPU Balloons

Along with utilizing cluster-autoscaler to dynamically scale our VM-backed clusters, we use it to remediate (take away & re-add) unhealthy members inside the cluster. We do that by setting the “min measurement” of the cluster to zero, and the “max measurement” of the cluster to the capability accessible. Nonetheless, cluster-autoscaler, if it sees idle nodes, will try and scale all the way down to solely wanted capability. For a number of causes (VM spin up latency, pre-allocated prices, the API server impacts talked about above) this idle-scaling is not perfect.

So, we launched a balloon Deployment for each our CPU-only and GPU hosts. This Deployment comprises a ReplicaSet with “max measurement” variety of low-priority pods. These pods occupy sources inside a node, so the autoscaler would not think about them as idle. Nonetheless since they’re low precedence, the scheduler can evict them instantly to make room for precise work. (We selected to make use of a Deployment as a substitute of a DaemonSet, to keep away from the DaemonSet being thought-about idle workload on a node.)

One factor of be aware, we use pod anti-affinity to make sure the pods would evenly distribute throughout the nodes. Earlier variations of the Kubernetes scheduler had an $O(N^2)$ efficiency difficulty with pod anti-affinity. This has been corrected since Kubernetes 1.18.

Gang Scheduling

Our experiments typically contain a number of StatefulSets, every working a special portion of the coaching effort. For Optimizers, researchers want all members of the StatefulSet to be scheduled, earlier than any coaching may be achieved (as we regularly use MPI to coordinate between optimizer members, and MPI is delicate to group membership modifications).

Nonetheless, Kubernetes by default will not essentially prioritize fulfilling all requests from one StatefulSet over one other. For instance if two experiments every requested 100% of the cluster’s capability, as a substitute of scheduling all of 1 experiment or the opposite, Kubernetes would possibly schedule solely half of every experiment’s pods, resulting in a impasse the place neither experiment could make progress.

We tried a couple of issues needing a customized scheduler, however bumped into edge instances that brought on conflicts with how regular pods have been scheduled. Kubernetes 1.18 launched a plugin structure for the core Kubernetes scheduler, making it a lot simpler so as to add options like this natively. We just lately landed on the Coscheduling plugin as a great way to unravel this downside.

Unsolved Issues

There are lots of issues nonetheless to handle as we scale up our Kubernetes clusters. A number of of them embrace:

Metrics

At our scale we’ve had many difficulties with Prometheus’s built-in TSDB storage engine being gradual to compact, and needing lengthy instances wanted to replay the WAL (Write-Forward-Log) any time it restarts. Queries additionally are inclined to lead to ā€œquestion processing would load too many samplesā€ errors. We’re within the means of migrating to a special Prometheus-compatible storage and question engine. Stay up for a future weblog submit about the way it goes!

Pod Community Visitors Shaping

As we scale up our clusters, every pod is calculated to have a certain quantity of Web bandwidth accessible. The mixture Web bandwidth necessities per particular person have grow to be substantial, and our researchers now have the power to unintentionally put a big useful resource pressure on different places on the Web, resembling datasets for obtain and software program packages to put in.

Conclusions

We’ve discovered Kubernetes to be an exceptionally versatile platform for our analysis wants. It has the power to scale as much as meet essentially the most demanding workloads we’ve placed on it. There are lots of areas but although the place it wants enchancment, and the Supercomputing workforce at OpenAI will proceed to discover how Kubernetes can scale. If this sort of work appears attention-grabbing, you need to think about making use of at OpenAI!

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments