Skip to content

Commit 2e6357f

Browse files
authored
Allow specifying the number of available cores via the env (#733)
Kubernetes does not necessarily configure `cgroups` to limit the number of CPUs visible to a process when a cpu limit is set. In order to allow the proxy injector to control this setting independently of `cgroups`, this change introduces a `LINKERD2_PROXY_CORES` environment variable that augments the `num_cpus`-based detection. If the configured value is larger than the number of available CPUs, it is ignored.
1 parent 82579be commit 2e6357f

File tree

1 file changed

+51
-18
lines changed

1 file changed

+51
-18
lines changed

linkerd2-proxy/src/rt.rs

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,59 @@
11
use tokio::runtime::{Builder, Runtime};
2+
use tracing::{info, warn};
23

34
#[cfg(feature = "multicore")]
45
pub(crate) fn build() -> Runtime {
5-
// The proxy creates an additional admin thread, but it would be wasteful to allocate a whole
6-
// core to it; so we let the main runtime consume all cores the process has. The basic scheduler
7-
// is used when the threaded scheduler would provide no benefit.
8-
match num_cpus::get() {
6+
// The proxy creates an additional admin thread, but it would be wasteful to
7+
// allocate a whole core to it; so we let the main runtime consume all
8+
// available cores. The number of available cores is determined by checking
9+
// the environment or by inspecting the host or cgroups.
10+
//
11+
// The basic scheduler is used when the threaded scheduler would provide no
12+
// benefit.
13+
let mut cores = std::env::var("LINKERD2_PROXY_CORES")
14+
.ok()
15+
.and_then(|v| {
16+
let opt = v.parse::<usize>().ok().filter(|n| *n > 0);
17+
if opt.is_none() {
18+
warn!(LINKERD2_PROXY_CORES = %v, "Ignoring invalid configuration");
19+
}
20+
opt
21+
})
22+
.unwrap_or(0);
23+
24+
let cpus = num_cpus::get();
25+
debug_assert!(cpus > 0, "At least one CPU must be available");
26+
if cores > cpus {
27+
warn!(
28+
cpus,
29+
LINKERD2_PROXY_CORES = cores,
30+
"Ignoring configuration due to insufficient resources"
31+
);
32+
cores = cpus;
33+
}
34+
35+
match cores {
936
// `0` is unexpected, but it's a wild world out there.
10-
0 | 1 => Builder::new()
11-
.enable_all()
12-
.thread_name("proxy")
13-
.basic_scheduler()
14-
.build()
15-
.expect("failed to build basic runtime!"),
16-
num_cpus => Builder::new()
17-
.enable_all()
18-
.thread_name("proxy")
19-
.threaded_scheduler()
20-
.core_threads(num_cpus)
21-
.max_threads(num_cpus)
22-
.build()
23-
.expect("failed to build threaded runtime!"),
37+
0 | 1 => {
38+
info!("Using single-threaded proxy runtime");
39+
Builder::new()
40+
.enable_all()
41+
.thread_name("proxy")
42+
.basic_scheduler()
43+
.build()
44+
.expect("failed to build basic runtime!")
45+
}
46+
num_cpus => {
47+
info!(%cores, "Using multi-threaded proxy runtime");
48+
Builder::new()
49+
.enable_all()
50+
.thread_name("proxy")
51+
.threaded_scheduler()
52+
.core_threads(num_cpus)
53+
.max_threads(num_cpus)
54+
.build()
55+
.expect("failed to build threaded runtime!")
56+
}
2457
}
2558
}
2659

0 commit comments

Comments
 (0)