feat(#2754): hive-wide CPUWeight= / IOWeight= for agent containers
`CPUQuota=`/`MemoryMax=` are hard caps: they throttle an agent even when
the host is idle, so they are the wrong tool for "be polite under
contention". The cgroup v2 relative shares are, and neither was wired.
Adds `services.hyperhive.{agentCpuWeight,agentIoWeight}` (1..=10000,
default 80) threaded through the existing drop-in path: HiveEnv ->
write_dropins -> WriteResourceLimits -> hyperhive-limits.conf, next to
the caps already there. Hive-wide only, as the operator scoped it on the
issue: no per-agent override, no resource-limits.json field, no
dashboard form.
The default of 80 is below the kernel's 100, so agent containers yield
to everything *not* on this drop-in path -- host services and the infra
containers (hive-ci, hive-forge, hive-gateway, hive-matrix). It does not
rank agents against each other; they all carry the same weight.
`WriteResourceLimits` gains two `#[serde(default)]` fields, and the
writer treats weight 0 as "not configured" and omits the line, so an
older hive-c0re talking to a newer hive-priv still produces the exact
pre-weights drop-in. The body is extracted into `limits_dropin_body` so
that is covered by a test rather than asserted by eye.
This commit is contained in:
parent
80650041d9
commit
e407fa93df
8 changed files with 221 additions and 16 deletions
|
|
@ -81,6 +81,8 @@ let
|
|||
context_window_tokens = cfg.contextWindowTokens;
|
||||
agent_cpu_quota = cfg.agentCpuQuota;
|
||||
agent_memory_max = cfg.agentMemoryMax;
|
||||
agent_cpu_weight = cfg.agentCpuWeight;
|
||||
agent_io_weight = cfg.agentIoWeight;
|
||||
model_prices = cfg.modelPrices;
|
||||
build_slots = cfg.buildSlots;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -301,6 +301,49 @@
|
|||
'';
|
||||
};
|
||||
|
||||
agentCpuWeight = lib.mkOption {
|
||||
type = lib.types.ints.between 1 10000;
|
||||
default = 80;
|
||||
example = 50;
|
||||
description = ''
|
||||
systemd `CPUWeight=` applied to every agent container via the
|
||||
same drop-in as `agentCpuQuota`. This is the cgroup v2
|
||||
`cpu.weight` relative share, **not** a cap: a low-weight
|
||||
container still gets the whole machine when nothing else wants
|
||||
it, and the weight only decides who yields under contention.
|
||||
That makes it the complement of `agentCpuQuota`, which throttles
|
||||
even on an idle host.
|
||||
|
||||
The kernel default is `100`. The hyperhive default of `80` means
|
||||
agent containers yield slightly to everything that is *not* on
|
||||
this drop-in path — host services and the infrastructure
|
||||
containers (`hive-ci`, `hive-forge`, `hive-gateway`,
|
||||
`hive-matrix`), which stay at `100`. Note this is a hive-wide
|
||||
value, so it does not rank agents against *each other*: they all
|
||||
share one weight.
|
||||
'';
|
||||
};
|
||||
|
||||
agentIoWeight = lib.mkOption {
|
||||
type = lib.types.ints.between 1 10000;
|
||||
default = 80;
|
||||
example = 50;
|
||||
description = ''
|
||||
systemd `IOWeight=` applied to every agent container via the
|
||||
same drop-in as `agentCpuQuota` — the block-IO counterpart of
|
||||
`agentCpuWeight`, with the same relative-share, contention-only
|
||||
semantics.
|
||||
|
||||
Caveat: `IOWeight=` maps to the cgroup v2 `io.weight` knob, which
|
||||
is only honoured when the `io.cost` (blk-iocost) controller is
|
||||
enabled for the backing device, or when the device uses the BFQ
|
||||
scheduler. On a host running `none`/`mq-deadline`/`kyber` without
|
||||
iocost QoS configured, systemd writes the value and the kernel
|
||||
ignores it — harmless, but it will measure as a no-op. Check with
|
||||
`cat /sys/fs/cgroup/io.cost.qos` on the host.
|
||||
'';
|
||||
};
|
||||
|
||||
buildSlots = lib.mkOption {
|
||||
type = lib.types.ints.positive;
|
||||
default = 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue