How does the Consul DNS interface work and how do you configure DNS forwarding?
Quick Answer
Consul runs a built-in DNS server on port 8600 that resolves service names in the format <service>.service.consul to IP addresses of healthy instances. DNS forwarding is configured by setting up the system DNS resolver (using dnsmasq, systemd-resolved, or iptables) to forward queries for the .consul domain to Consul's DNS server while all other queries go to the normal DNS resolver.
Detailed Answer
The Consul DNS interface provides the simplest path to service discovery because it leverages the universal DNS protocol that every application and programming language already supports. Consul includes a built-in DNS server that listens on port 8600 by default and responds to queries for the .consul top-level domain. This means any application that can resolve hostnames can discover Consul services without any code changes, special client libraries, or HTTP API calls. The DNS interface translates the service catalog into standard DNS records that work with existing tools and infrastructure.
Consul's DNS server responds to queries following a structured naming convention. The most common query format is <service-name>.service.consul, which returns A records containing the IP addresses of all healthy instances of that service. For example, querying payments-api.service.consul might return three IP addresses corresponding to three healthy instances of the payments-api service. SRV records are also supported and return both the IP address and port number for each instance, which is essential when services run on dynamic ports. For multi-datacenter deployments, the format <service-name>.service.<datacenter>.consul allows querying services in a specific datacenter, such as payments-api.service.us-west-2.consul. Node lookups use the format <node-name>.node.consul.
By default, Consul's DNS server listens on port 8600 rather than the standard DNS port 53. This means applications cannot use it directly without additional configuration because most DNS clients send queries to port 53. DNS forwarding bridges this gap by configuring the system's DNS resolver to route queries for the .consul domain to Consul on port 8600 while forwarding all other queries to the regular upstream DNS servers. There are several approaches to configure this forwarding. Using dnsmasq, you add a line like server=/consul/127.0.0.1#8600 to forward .consul queries. Using systemd-resolved on modern Linux systems, you create a configuration that specifies the Consul DNS server for the .consul domain. Using iptables, you can redirect all DNS traffic on port 53 destined for the .consul domain to Consul's port 8600.
The DNS interface supports several configuration options that control its behavior. The dns_config.allow_stale parameter allows DNS queries to be served by follower servers rather than only the leader, improving query throughput at the cost of potentially returning slightly stale data. The dns_config.node_ttl and dns_config.service_ttl parameters control how long DNS clients cache responses. Short TTLs (e.g., 10 seconds) ensure clients quickly detect changes in service availability, while longer TTLs reduce the load on the Consul DNS server. The dns_config.enable_truncate parameter enables TCP fallback for DNS responses that exceed the UDP packet size limit of 512 bytes, which occurs when a service has many healthy instances.
In production, DNS-based service discovery works well for services that do not require advanced routing features like load balancing algorithms or circuit breaking. Its main advantage is universality: any application that can resolve a hostname can use it, regardless of language or framework. However, DNS-based discovery has limitations. DNS caching at various layers (application, OS, resolver) can cause stale results even when Consul's catalog has been updated. DNS does not natively support health-aware load balancing beyond round-robin across returned addresses. And DNS responses do not include service metadata or tags, limiting the ability to make routing decisions based on service attributes. For these reasons, many production deployments use DNS for simple service discovery and the HTTP API or service mesh for more sophisticated routing requirements.