CoreDNS’s etcd plugin turns your DNS server into a dynamic service discovery engine, letting services register themselves and be found by others without manual DNS record updates.

Here’s etcd in action, registering a simple web service and then looking it up.

First, let’s register a service named my-web-app in the dev zone. We’ll use etcdctl to put a key-value pair into etcd. The key format is crucial: /skydns/dev/my-web-app/1. The /skydns prefix is convention for CoreDNS’s etcd plugin, dev is the zone, my-web-app is the service name, and 1 is a record identifier. The value will be a JSON object specifying the service’s IP address and port.

ETCDCTL_API=3 etcdctl put /skydns/dev/my-web-app/1 '{"host":"10.0.1.100", "port":8080}'

Now, let’s assume you have a CoreDNS server configured with the etcd plugin. A simple Corefile might look like this:

.:53 {
    etcd {
        zones dev
        path /skydns
    }
    cache 30
    forward . 8.8.8.8
    reload
    log
}

With this setup, any client querying my-web-app.dev will get the IP address 10.0.1.100 and port 8080. You can verify this with dig:

dig @127.0.0.1 my-web-app.dev

The response will show an A record pointing to 10.0.1.100. If you query for the SRV record, you’ll get the port information:

dig @127.0.0.1 _my-web-app._tcp.dev SRV

The response will include an SRV record like 0 10 8080 my-web-app.dev..

The problem this solves is the manual, error-prone process of updating DNS records whenever a service instance starts, stops, or changes its IP. With etcd, service registration is automated. When a service deploys, its registration process writes its endpoint details to etcd. When it shuts down gracefully, it can remove its entry. CoreDNS, watching etcd, automatically reflects these changes in DNS queries.

Internally, CoreDNS’s etcd plugin works by establishing a connection to your etcd cluster. It watches the keys under the configured path (e.g., /skydns) for changes. When a key is added, deleted, or modified, the plugin parses the key-value pair. The key determines the DNS name and zone, while the value (expected in JSON format) provides the IP address and port. This information is then translated into DNS records (A, SRV, etc.) that CoreDNS serves. The zones directive in the Corefile tells the plugin which DNS zones it’s responsible for managing via etcd.

The etcd plugin supports multiple record types and configurations. For instance, you can register multiple instances of the same service. Each instance would get a unique key, like /skydns/dev/my-web-app/1, /skydns/dev/my-web-app/2, etc. CoreDNS will then return multiple A records for my-web-app.dev, allowing clients to load balance across them. You can also specify weights and priorities within the JSON value for more sophisticated SRV record generation. The plugin also handles TTLs by default, which can be overridden.

A common point of confusion is the exact structure of the etcd keys and the JSON values. The /skydns prefix is not strictly mandatory but is the conventional default that the plugin looks for. If you configure a different path in your Corefile, you must use that path as the prefix for your etcd keys. Similarly, the JSON structure requires specific fields like "host" and "port". If these are missing or malformed, CoreDNS won’t be able to generate the correct DNS records, and queries will fail. The plugin will log errors if it encounters malformed entries.

To make this truly dynamic, your service registration logic needs to be robust. This typically involves a sidecar container or a startup script that registers the service’s IP and port with etcd upon container start and deregisters on container stop. The etcd plugin for CoreDNS then picks this up automatically.

The next concept you’ll likely encounter is how to manage the lifecycle of these etcd entries, especially during unexpected service terminations, and how to implement health checking to automatically remove stale entries.

Want structured learning?

Take the full Coredns course →