otel: agents reach their hive's collector by a swarm-wide name
Agents are handed `http://hive-collector.<swarm domain>:<port>` as their otel endpoint instead of `http://<bridge IP>:<port>`. Every hive running its collector contributes the name to `gateway.localNames`, so its own dnsmasq answers it with its bridge IP, the way the queue's name already works. The rendered meta flake then carries no hive-specific address, which a swarm-level render needs (#4857, operator ruling 100744: "b"). hive-c0re's own exporter keeps the bridge address: on the host the name may resolve to loopback through `gateway.localHostsEntry`, where the receiver does not listen. The name sits under the swarm domain and starts with `hive`, a fragment no hive name may contain, so no hive's default domain can take it.
This commit is contained in:
parent
db4bfd4007
commit
d4e20803ec
6 changed files with 58 additions and 13 deletions
|
|
@ -83,11 +83,13 @@ in
|
|||
# don't render no-op env lines.
|
||||
let
|
||||
otel = config.services.hyperhive.otel;
|
||||
# The first hop, bound once and consumed twice below: what agents are
|
||||
# handed, and where hive-c0re's own exporter sends. One binding so the
|
||||
# address a hive tells its agents about and the one it uses itself
|
||||
# cannot drift apart.
|
||||
firstHop = "http://${config.services.hyperhive.network.bridgeIp}:${toString otel.collector.port}";
|
||||
# The first hop, this hive's own collector, under the two spellings its
|
||||
# two kinds of caller need. Agents get the swarm-wide name, so their
|
||||
# builds carry nothing hive-specific; this daemon gets the bridge
|
||||
# address, because on the host the name may resolve to loopback
|
||||
# (`gateway.localHostsEntry`), where the receiver does not listen.
|
||||
agentFirstHop = "http://${otel.collector.host}:${toString otel.collector.port}";
|
||||
hostFirstHop = "http://${config.services.hyperhive.network.bridgeIp}:${toString otel.collector.port}";
|
||||
in
|
||||
{
|
||||
# `otel.endpoint` means "where telemetry ultimately goes" and keeps
|
||||
|
|
@ -95,7 +97,7 @@ in
|
|||
# always this hive's own collector. Deriving it rather than
|
||||
# redefining `endpoint` is what lets every existing deployment keep
|
||||
# its configured value untouched.
|
||||
HYPERHIVE_OTEL_ENDPOINT = firstHop;
|
||||
HYPERHIVE_OTEL_ENDPOINT = agentFirstHop;
|
||||
# hive-c0re's OWN container-resource exporter (stats/otel_metrics.rs)
|
||||
# reads the STANDARD OTLP variable — the same one hive-metric and every
|
||||
# agent read — and lets the SDK resolve the URL, which appends the
|
||||
|
|
@ -108,7 +110,7 @@ in
|
|||
# replace this one:
|
||||
# it is the agent-config transport meta.rs reads, and the SDK does not
|
||||
# know that name.
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT = firstHop;
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT = hostFirstHop;
|
||||
# The first hop is the collector's OTLP/HTTP receiver, which speaks
|
||||
# protobuf regardless of what the upstream wants — `otel.protocol`
|
||||
# describes the *upstream* link, and the collector's own exporter is
|
||||
|
|
|
|||
|
|
@ -203,6 +203,28 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
collector.host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
readOnly = true;
|
||||
# Total on a null swarm domain, as in ./swarm-otel-service.nix: the
|
||||
# required-domain assertion should be what an operator sees.
|
||||
default = "hive-collector.${
|
||||
if config.services.hyperhive.swarm.domain == null then
|
||||
"invalid"
|
||||
else
|
||||
config.services.hyperhive.swarm.domain
|
||||
}";
|
||||
defaultText = lib.literalExpression ''"hive-collector.''${services.hyperhive.swarm.domain}"'';
|
||||
description = ''
|
||||
The name agents reach this hive's collector on. The same string on
|
||||
every hive: each hive's own resolver answers it with its own bridge
|
||||
IP, so an agent's build carries no hive-specific address.
|
||||
|
||||
No hive can claim this name as its domain:
|
||||
`nix/reserved-hive-fragments.nix` forbids `hive` in any hive name.
|
||||
'';
|
||||
};
|
||||
|
||||
telemetryPort = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8888;
|
||||
|
|
@ -357,6 +379,9 @@ in
|
|||
# the port on the bridge interface only.
|
||||
services.hyperhive.network.exposeHostPorts = [ otel.collector.port ];
|
||||
|
||||
# The name agents dial, answered with the bridge IP the receiver binds.
|
||||
services.hyperhive.gateway.localNames = [ otel.collector.host ];
|
||||
|
||||
# …and the receiver binds that bridge address, so the interface has
|
||||
# to exist. `exposeHostPorts` is a firewall hole, not a demand.
|
||||
services.hyperhive.network.enable = lib.mkDefault true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue