Commit 9bb9723
authored
fix(e2e): make instance metadata endpoint unreachable on kind nodes (#1352)
Since 2026-08-29 the e2e tests fail on CI regardless of the branch under
test: the collector container of the daemonset collector does not become
ready in time, the BeforeAll node fails and every remaining spec is
skipped. c94a444 bought time by raising the startup probe to 120s and
the test timeout to 150s. This commit adds a workaround at the network
level.
This commit also reverts the workarounds from an earlier commit:
waitForCollectorToStart waits 60s again (instead of 150) and the
daemonset collector is back to the default startup probe timeouts.
A probe that ran the eight resource detectors of the daemonset
collector, one at a time (run
[33278618771](https://github.com/dash0hq/dash0-operator/actions/runs/33278618771)),
singled out gcp:
```
eks 0.003s ecs 0.000s ec2 2.000s gcp 27.947s azure 2.000s
aks 2.000s k8snode 0.004s system 0.000s all 27.972s
```
ec2, azure and aks stop at the configured timeout of 2s, the rest finish
in milliseconds, and all eight together take no longer than gcp alone. A
second probe replayed the steps of the gcp detector inside a pod (run
33307695809):
```
onGKE/metadata 12.824s dial tcp 169.254.169.254:80: i/o timeout
onGCE/metadata 13.928s dial tcp 169.254.169.254:80: i/o timeout
metadata.OnGCE 0.003s false
tcp-dial 10.001s i/o timeout (reference)
dns-lookup 0.003s no such host (reference)
CloudPlatform() 26.519s UnknownPlatform
```
DNS is healthy and answers in 3ms, so name resolution was never
involved. The IP 169.254.169.254 is blackholed on the runner: the dials
end in "i/o timeout", not "connection refused", so the packets are
dropped rather than rejected.
The delay comes from CloudPlatform() of
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp.
Two of the platform checks query the metadata server, and both pass
context.TODO(), which carries no deadline, so the timeout of the
resourcedetection processor cannot stop them:
onGKE() reads KUBERNETES_SERVICE_HOST, which is always set inside a pod,
and
then calls InstanceAttributeValueWithContext(context.TODO(),
"cluster-location")
onGCE() calls GetWithContext(context.TODO(), "instance/machine-type")
metadata.NewClient(nil) returns the package default client, which dials
with a timeout of 2s and retries up to five times, hence about 13s per
call. The daemonset collector runs the detectors once per pipeline and
has three, which is about 80s against a startup probe that grants 90s.
This is a known upstream defect, tracked in
GoogleCloudPlatform/opentelemetry-operations-go#1026,
and not fixed yet.
The workaround, on every kind node:
* Add an unreachable route for the endpoint that makes connect() fail
immediately with EHOSTUNREACH, which the metadata client neither retries
nor treats as temporary, so the detector gives up immediately.
* Write a sysctl `net.ipv4.icmp_ratelimit=0`; without it, only the first
connections fail fast, then Linux throttles the generation of ICMP
errors per destination via net.ipv4.icmp_ratelimit, one message per
second by default, so every connection after the first gets no ICMP at
all and waits for the retransmission of its SYN instead. The retry burst
of the detector is exactly the pattern that runs into this, which is why
isolated calls end at 0s while the detector as a whole would still >
18s.
An iptables REJECT rule would have been the worse choice: both
--reject-with tcp-reset and the default icmp-port-unreachable produce
ECONNREFUSED, and syscallRetryable in retry_linux.go of
cloud.google.com/go/compute/metadata retries exactly ECONNRESET and
ECONNREFUSED, so the five retries would still run and only the dial
timeouts would be saved.
Disabling the rate limit on every node should make all of the calls fail
immediately rather than only the first few. There is still an
unexplained 1s delay for every consecutive call after the first call,
e.g. a total lag of ~2 seconds. But since that is coincidentally roughly
the same as the 2 second timeout that is configured for the
resourcedetection processor, it is acceptable.
Nothing in the kind cluster needs the instance metadata endpoint, so
making it unreachable costs nothing. Note that this only repairs CI. Any
cluster that blackholes the link-local range still pays about 80s of
collector startup, and the e2e suite no longer covers that case.1 parent 02177de commit 9bb9723
4 files changed
Lines changed: 101 additions & 10 deletions
File tree
- .github/workflows
- e2e
- test/e2e
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
131 | 137 | | |
132 | 138 | | |
133 | 139 | | |
| |||
Lines changed: 94 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
| 128 | + | |
133 | 129 | | |
134 | 130 | | |
135 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
254 | 254 | | |
255 | 255 | | |
256 | 256 | | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | 257 | | |
263 | 258 | | |
264 | 259 | | |
| |||
0 commit comments