envoy: dns: DnsResolverImpl keeps using a "broken" c-ares channel
We have a STRICT_DNS
type of a cluster defined in bootstrap config. In one of our test Pods, the membership count of this cluster became zero. This is understandable because the DNS resolution might have resulted in zero hosts. However this remained like this for quite a long time and after killing the container, Envoy is able to successfully resolve the DNS.
I have taken debug logs when Envoy is not able to resolve this. I see the following line
“source/common/network/dns_impl.cc:118] DNS request timed out 4 times
”,
And I see these lines repeatedly “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 0 milliseconds”, “source/common/network/dns_impl.cc:147] Setting DNS resolution timer for 22 milliseconds”
So at this point I am not very clear if it is Envoy issue or container DNS issue - as container restart resolved the issue. Has any one seen similar issues with DNS? and another question is it the DNS resolution timer behaviour correct in the sense it is trying to resolve 0 milliseconds?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 2
- Comments: 30 (19 by maintainers)
Did some late night digging yesterday and arrived at an explanation:
When c-ares initializes a channel (trimming irrelevant details):
ares_init_options
.init_by_resolv_conf
which has platform specific code.#elif defined(CARES_USE_LIBRESOLV)
which usesres_getservers
to get the addresses of DNS servers.res_getservers
returnsAF_UNSPEC
for the server address’ family.init_by_defaults
which usesINADDR_LOOPBACK:NAMESERVER_PORT
as the servers address. There is obviously no guarantee that a DNS server is going to be running on loopback, and on the phone it is definitely not. In addition once a channel has been initialized it never re-resolves its server set, so even when connectivity is regained, the channel still only has the one default server.Solution:
Envoy Mobile has the same issue in iOS.
Steps to repro: From an Envoy Mobile clone
bazel build --config=ios //:ios_dist
bazel run //examples/swift/hello_world:app --config=ios
Config used: This is repro’ed with clusters with both STRICT and LOGICAL DNS. As well as the dynamic forward proxy. The DNS refresh rate was configured to be 5s.
I am going to be looking at this issue as the setup above repros this issue 100% of the time.