#14993·kong

Kong DNS resolver silently drops all options when /etc/resolv.conf has multiple options on a single "options" line (breaks Kubernetes dnsConfig)

Author: tcxdgitCreated Sep 10, 2026Updated Sep 10, 2026

Is there an existing issue for this?

  • I have searched the existing issues

Kong version ($ kong version)

Kong 3.9.3

Current Behavior

Kong's resolv.conf parser only works when each options line contains a single option. The standard resolv.conf format (man 5 resolv.conf) allows multiple space-separated options on one line:

options ndots:2 timeout:2 attempts:3

Kubernetes generates exactly this format when dnsConfig.options is set on a Pod. With such a line, Kong's parser fails to match it and drops every option on the line — including the first one. All values then silently fall back to Kong's built-in defaults, most notably ndots, which controls search-domain expansion and can significantly change query behavior for short hostnames (e.g. excessive search-domain queries before hitting the actual name).

There is no workaround through configuration: kong.conf exposes dns_order, dns_not_found_ttl, etc., but nothing that overrides the values parsed from resolv.conf, and Kubernetes dnsConfig cannot produce one-option-per-line output.

Root cause in parseResolvConf: the entire remainder of the options line is passed to parseOption as one string:

lua
elseif option == "options" then
  result.options = result.options or {}
  parseOption(result.options, details)   -- details = "ndots:2 timeout:2 attempts:3"
end

and parseOption matches it against a pattern anchored at both ends:

lua
local option, n = details:match("^([^:]+)%:*(%d*)$")

For "ndots:2 timeout:2 attempts:3", ([^:]+) captures ndots, but (%d*)$ cannot match the remaining 2 timeout:2 attempts:3 (it is not all digits up to end-of-line), so the whole match returns nil and no option is recorded at all.

Expected Behavior

Kong should iterate over all whitespace-separated name[:value] tokens on an options line — e.g. for token in details:gmatch("%S+") do parseOption(...) end — matching the documented resolv.conf format, so settings like ndots, timeout, and attempts configured via Kubernetes dnsConfig actually take effect.

Steps To Reproduce

  1. Deploy Kong with a dnsConfig:
yaml
spec:
  dnsConfig:
    options:
      - name: ndots
        value: "2"
      - name: timeout
        value: "2"
      - name: attempts
        value: "3"
  1. Kubernetes writes /etc/resolv.conf in the container as:
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:2 timeout:2 attempts:3
  1. Observe the effective resolver behavior (e.g. query a short hostname and count search-domain expansions, or inspect the parsed options with KONG_LOG_LEVEL=debug): ndots:2 is not honored — Kong uses its default ndots, and timeout/attempts fall back to defaults as well.

    Cross-check: mounting a custom resolv.conf with one option per line

options ndots:2
options timeout:2
options attempts:3

makes all values take effect, confirming the parser handles multi-line options correctly and only the single-line multi-option case (the one Kubernetes produces) is broken.

Anything else?

No response