Behavior: DNS resolver search list and options handling in k6 without --dns
0 reputation · 31 Jul 2022, 19:47 UTC
0 reputation · 31 Jul 2022, 19:47 UTC
The goal is to determine whether k6, when the `--dns` flag is omitted, applies the search list and resolver options (such as `rotate` and `timeout`) defined in the system’s `/etc/resolv.conf` during hostname lookups initiated by virtual users.
DNS results are cached per VU for the test duration and are not refreshed if the underlying record changes, and the caching mechanism is independent of the system resolver. Observations indicate that the handling of `/etc/resolv.conf` varies across Linux distributions and may have changed in k6 v0.44 when the DNS resolver implementation was updated, leaving the exact behavior unclear.
Does k6 honor the search list from `/etc/resolv.conf` when `--dns` is not set? Does it respect the `rotate` and `timeout` options in that file? How does this behavior differ between k6 versions (e.g., v0.44 and later) and various Linux distributions?
When --dns is omitted, k6 performs hostname lookups through Go's resolver, which on Linux reads /etc/resolv.conf — including the search list and options like rotate and timeout. So in the common case, yes: short hostnames that rely on a search suffix will resolve, and resolver options are read. The important caveats are (1) k6's per-VU DNS cache can mask rotation and mid-test changes, and (2) the exact resolution path depends on whether Go uses its pure-Go resolver or cgo, which varies with build and environment.
Confirmed, well-established behavior:
net package on Linux parses /etc/resolv.conf itself when using the built-in (pure Go) resolver, honoring nameserver, search/domain, and options such as timeout, attempts, and rotate.rotate round-robin effects are largely invisible within a single VU's iterations.--dns (or the older per-run DNS config) overrides this path entirely with k6's own resolver configuration.Likely, but not fully verified:
Distributions manage /etc/resolv.conf differently: NetworkManager or systemd-resolved may point it at a local stub (127.0.0.53), containers often get a synthesized file, and Alpine (musl) has its own resolver semantics — notably, musl historically ignores some options and queries nameservers in parallel rather than honoring rotate. If k6 runs with cgo on musl, option handling follows musl, not glibc. Inside Docker, the file is bind-mounted from the daemon's config, so the host's search list may not appear at all.
Because caching hides per-lookup behavior, observe the wire rather than the script output:
# Watch which nameserver is queried and with what name
sudo tcpdump -i any -n port 53 &
k6 run script.js # no --dns flag
Useful checks:
http.get("http://myservice/")) and confirm in the capture that queries for myservice.<suffix> are attempted in search-list order.nameserver at a non-responsive address and measure time-to-failure with and without options timeout:1.GODEBUG=netdns=2 k6 run script.js makes Go log which resolver it selected and what it parsed from resolv.conf — the most direct way to settle the question for your binary.If your test depends on a specific search suffix or deterministic nameserver behavior, don't rely on ambient resolv.conf state — use fully qualified names in the script, or pin resolution explicitly with --dns. If you need DNS changes picked up mid-test, be aware the per-VU cache prevents that regardless of resolver options.
One missing detail that would change this answer: whether you're running an official k6 release binary or a custom/xk6 build, since that determines the Go-vs-cgo resolver path. Version-specific differences around v0.44 should be treated as unverified until tested with the GODEBUG method above.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.