Built-in DNS Service Discovery
Nacos 3.3 includes a DNS server that returns registered service instance addresses as DNS records, allowing applications to discover services through name resolution. The stable 3.3.0 release supports A records for IPv4, AAAA records for IPv6, and SRV records with service ports. DNS is disabled by default.
Built-in DNS starts with Nacos Server and requires no additional Nacos DNS plugin. For an existing deployment of the separate CoreDNS plugin, see Nacos with CoreDNS. Follow the corresponding guide for each integration’s configuration and domain naming rules.
1. Enable built-in DNS
Add the following to conf/application.properties on a Nacos Server that provides service discovery, then restart it:
nacos.naming.dns.enabled=truenacos.naming.dns.bind-address=127.0.0.1nacos.naming.dns.port=5353nacos.naming.dns.domain-suffix=nacosnacos.naming.dns.default-group=DEFAULT_GROUPnacos.naming.dns.namespace=publicnacos.naming.dns.ttl=60This configuration exposes services from the public namespace under .nacos, with DEFAULT_GROUP as the default group and a record TTL of 60 seconds. Set namespace to the namespace ID. Its configuration default is empty; explicitly set it to public as shown when querying that namespace. See System Parameters for all settings.
DNS binds only to 127.0.0.1 by default. Use the configuration above for local validation. For remote clients or CoreDNS, explicitly set nacos.naming.dns.bind-address to the intended trusted internal listening address. DNS listens on both UDP and TCP on the same port. The default port, 5353, is independent of the Nacos HTTP/gRPC ports. Before enabling it, confirm that the port is available for both protocols. Cluster nodes serving DNS queries should use the same namespace, suffix, and group settings.
2. Domain naming rules
With the configuration above:
| Query name | Service name | Group | Namespace |
|---|---|---|---|
dns-demo.nacos. | dns-demo | Configured default group DEFAULT_GROUP | Configured public |
dns-demo.prod.nacos. | dns-demo | Explicit group prod | Configured public |
The formats are {serviceName}.{domainSuffix} and {serviceName}.{groupName}.{domainSuffix}. The trailing . in the examples makes the name fully qualified, avoiding the addition of system search domains.
Service and group names each occupy one dot-separated label in the query name. Service names containing dots, such as com.example.Service, cannot be used directly in this format. Do not append namespace or cluster labels. For DNS discovery, use lowercase letters, digits, and hyphens in service names and explicit group names. The server configuration selects the namespace; individual DNS queries cannot switch it.
3. Verify with dig
Prepare a service named dns-demo in the public namespace and DEFAULT_GROUP, with at least one healthy and enabled instance. See Instance Lifecycle for registration and instance states.
To query IPv4 addresses from a local Nacos Server:
dig @127.0.0.1 -p 5353 dns-demo.nacos. ACheck the response status and ANSWER section. If the service has a healthy instance at 10.0.0.10, the answer includes a record such as:
dns-demo.nacos. 60 IN A 10.0.0.10Verify TCP queries on the same port:
dig @127.0.0.1 -p 5353 dns-demo.nacos. A +tcpWhen the service has healthy IPv6 instances, query AAAA records:
dig @127.0.0.1 -p 5353 dns-demo.nacos. AAAAInclude the group in the domain name to query another group. The following command requires the service to be in the prod group:
dig @127.0.0.1 -p 5353 dns-demo.prod.nacos. ATo query service ports and targets, request SRV records for the same name:
dig @127.0.0.1 -p 5353 dns-demo.nacos. SRVSRV answers include the instance port, weight, and target hostname with priority 0. The ADDITIONAL section supplies the target’s A/AAAA address. Do not add an extra _service._tcp prefix.
Resolution follows these rules:
- Only healthy, enabled instances are returned, filtered to the IP address family requested by A or AAAA.
- Each response’s ANSWER section contains at most 20 records, and their order can vary. For larger services, one query does not return the complete instance list.
- A/AAAA responses contain IP addresses only; use SRV for service ports and weights. Use the Java SDK for instance metadata or change subscriptions.
- Nacos service queries support A, AAAA, and SRV; TXT and MX service records are not provided. Clients must retry over TCP when a UDP response is truncated. TCP responses also have a 20-record ANSWER limit.
- DNS caching affects how quickly instance changes reach applications. During troubleshooting, compare a direct query to Nacos DNS with the application’s resolution result.
4. Connect applications and container networks
Use dig -p 5353 to verify Nacos DNS directly. Applications typically resolve names through system DNS. Configure suffix-based forwarding in your existing DNS service so that .nacos queries go to Nacos DNS while other domains keep using their existing resolvers. Built-in DNS also supports optional upstream forwarding, disabled by default. Enable nacos.naming.dns.forward-enabled=true and configure reachable upstream DNS addresses with nacos.naming.dns.forward-servers only when Nacos DNS should handle queries outside its own suffix. It is a conditional forwarder, not an open recursive resolver. See System Parameters for defaults.
4.1. Forward from CoreDNS
Add a zone to your existing Corefile, replacing 10.0.0.20 with a Nacos Server address reachable from CoreDNS:
nacos:53 { forward . 10.0.0.20:5353}This uses CoreDNS’s built-in forward plugin to send DNS requests to Nacos built-in DNS. It is a different integration from deploying the Nacos CoreDNS plugin. Keep the existing Corefile configuration for other domains.
4.2. Docker and Kubernetes
For Docker, add -p 5353:5353/udp -p 5353:5353/tcp to your existing docker run command and enable DNS inside the container. On a trusted internal network with access controls, explicitly set nacos.naming.dns.bind-address to 0.0.0.0 or a reachable container listening address; the default loopback binding cannot be reached through port publishing. Publishing only HTTP/gRPC ports does not expose DNS.
For Kubernetes, enable DNS on a listening address reachable through the Pod network, then create a separate ClusterIP Service. Replace the example selector with the actual Pod labels. The Service and Pods must be in the same Kubernetes namespace:
apiVersion: v1kind: Servicemetadata: name: nacos-dnsspec: selector: app: nacos ports: - name: dns-udp port: 5353 targetPort: 5353 protocol: UDP - name: dns-tcp port: 5353 targetPort: 5353 protocol: TCPExpose both UDP and TCP as described in Kubernetes Service protocol support, and check that network policies allow DNS callers. The Service provides an address for access; applications using system DNS still need the corresponding domain forwarding configuration.
5. Troubleshooting
| Symptom | What to check |
|---|---|
| Query times out or the connection is refused | Confirm DNS was enabled and the server restarted. Check bind-address (loopback by default), UDP/TCP listeners on port 5353, port conflicts, container mappings, and firewalls. The startup log message Nacos DNS server started on port helps confirm successful binding. |
NXDOMAIN | Check the suffix, service name, group, and configured namespace ID. Confirm there are healthy, enabled instances. If those are correct, inspect server logs for query errors. |
NOERROR with an empty ANSWER section | Check the requested address family. For example, a service with only IPv4 instances has no addresses to return for AAAA. |
NOTIMP | Use A, AAAA, or SRV for Nacos services. TXT and MX service records are not supported. |
| UDP works but TCP or larger responses fail | Check TCP port mappings and network policies; allowing only UDP is insufficient. |
| Direct queries work but applications fail to resolve or use stale addresses | Check the application’s DNS resolver, suffix forwarding, and cache TTL. Confirm the returned instance IP is reachable and the application uses the correct service port. |