COREDNS-NOMAD(7)

πŸ“¦ version 1.15.0, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME

okay so this is coredns-nomad β€” it's the nomad plugin for CoreDNS, and it literally enables reading zone data from a Nomad cluster. that's it, that's the vibe ✨

(also hi, you're reading the COREDNS-NOMAD(7) page from the CoreDNS Plugins manual β€” welcome bestie 🫢)


🌸 DESCRIPTION

so this plugin serves DNS records for services that are registered with Nomad. Nomad 1.3+ ships with support for discovering services ([over here](https://www.hashicorp.com/en/blog/nomad-service-discovery) if you wanna read up) and it's got an in-built service catalogue available via the HTTP API. this plugin basically extends that HTTP API and gives you a DNS interface for querying the service catalogue. iconic behaviour, honestly πŸ‘‘

you look stuff up with the format [service].[namespace].service.nomad. rn the plugin handles A, AAAA and SRV records. for the full deets go peek at the Usage Example section below πŸ‘€


πŸŽ€ EXAMPLE JOB TEMPLATE

here's what the job template looks like, verbatim, don't touch:

job "dns" {
  type = "service"

  group "dns" {
    network {
      port "dns" {
        static = 1053
      }
    }
    task "dns" {
      driver = "docker"

      config {
        image = "coredns/coredns:latest"
        ports = ["dns"]
        args = ["-conf", "/secrets/coredns/Corefile", "-dns.port", "1053"]
      }

      service {
        name         = "hostmaster"
        provider     = "nomad"
        port         = "dns"
        address_mode = "driver"
      }

      identity {
        env = true
      }

      template {
        data          = <<EOF
. {
  forward . 1.1.1.1
}

service.nomad. {
  errors
  debug
  health
  log
  nomad service.nomad {
    address unix:///secrets/api.sock
    ttl 10
  }
  cache 30
}
EOF
        destination   = "secrets/coredns/Corefile"
        change_mode   = "signal"
        change_signal = "SIGHUP"
      }
    }
  }
}

✨ SYNTAX ✨

the minimal form, bestie:

nomad [ZONE] {

if you only specify the plugin and nothing else, the nomad plugin will default to the service.nomad zone. no thoughts, just defaults πŸ’…

and the full form:

nomad [ZONE] {
    address URL
    filter FILTER
    token TOKEN
    ttl DURATION
}
  • address β€” the address where a Nomad agent (server) is available. URL defaults to http://127.0.0.1:4646.
  • filter β€” lets you filter Nomad services. FILTER defaults to "". it uses the [filtering syntax](https://developer.hashicorp.com/nomad/api-docs#filtering) (iykyk).
  • token β€” the SecretID of an ACL token used to authenticate API requests with, if the Nomad cluster has ACL enabled. TOKEN defaults to "".
  • ttl β€” lets you set a custom TTL for responses. DURATION defaults to 30 seconds. the minimum TTL allowed is 0 seconds and the max is capped at 3600 seconds. setting TTL to 0 will prevent records from being cached. the unit for the value is seconds ⏱️

πŸ“Š METRICS

if monitoring is enabled (via the prometheus directive) then these metrics get exported:

  • coredns_nomad_success_requests_total{namespace,server} β€” counter of DNS requests handled successfully 🟒
  • coredns_nomad_failed_requests_total{namespace,server} β€” counter of DNS requests that failed πŸ’€

the server label indicates which server handled the request. namespace indicates the namespace of the service in the query.


🫢 READY

this plugin reports readiness to the ready plugin. it will only be ready when it has successfully connected to the Nomad server. it queries the [/v1/agent/self](https://developer.hashicorp.com/nomad/api-docs/agent#query-self) endpoint to check if it's ready. so like, it's not just gonna say it's ready β€” it checks. main character energy with receipts πŸ’…


🌈 EXAMPLES

okay so enable nomad and resolve all services with .nomad as the suffix. the cache plugin is used to cache the responses for 30 seconds, which avoids a lookup to the Nomad server for every single request (because that would be a lot 😭):

service.nomad.:1053 {
    log
    cache
    errors
    nomad service.nomad {
        address http://127.0.0.1:4646 http://127.0.0.2:4646 http://127.0.0.3:4646
        ttl 10
    }
    cache 30
}

πŸ” AUTHENTICATION

the nomad plugin uses a default Nomad configuration to create an API client. options like the HTTP address and the token can be specified in the Corefile. however, the Nomad Go SDK can also additionally read these environment variables:

  • NOMAD_TOKEN
  • NOMAD_ADDR
  • NOMAD_REGION
  • NOMAD_NAMESPACE
  • NOMAD_HTTP_AUTH
  • NOMAD_CACERT
  • NOMAD_CAPATH
  • NOMAD_CLIENT_CERT
  • NOMAD_CLIENT_KEY
  • NOMAD_TLS_SERVER_NAME
  • NOMAD_SKIP_VERIFY

you can read about them in detail [here](https://developer.hashicorp.com/nomad/docs/reference/runtime-environment-settings) 🧚


πŸ‘‘ USAGE EXAMPLE

πŸ“ A RECORD

dig redis.default.service.nomad @127.0.0.1 -p 1053

; <<>> DiG 9.18.1-1ubuntu1.2-Ubuntu <<>> redis.default.service.nomad @127.0.0.1 -p 1053
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54986
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: bdc9237f49a1f744 (echoed)
;; QUESTION SECTION:
;redis.default.service.nomad.        IN    A

;; ANSWER SECTION:
redis.default.service.nomad.    10    IN    A    192.168.29.76
redis.default.service.nomad.    10    IN    A    192.168.29.76
redis.default.service.nomad.    10    IN    A    192.168.29.76

;; Query time: 4 msec
;; SERVER: 127.0.0.1#1053(127.0.0.1) (UDP)
;; WHEN: Thu Jan 05 12:12:25 IST 2023
;; MSG SIZE  rcvd: 165

πŸ¦‹ SRV RECORD

since an A record doesn't contain the port number, you use an SRV record to query the port number of a service. slay 🎯

dig redis.default.service.nomad @127.0.0.1 -p 1053 SRV

; <<>> DiG 9.18.1-1ubuntu1.2-Ubuntu <<>> redis.default.service.nomad @127.0.0.1 -p 1053 SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49945
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 4
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 14572535f3ba6648 (echoed)
;; QUESTION SECTION:
;redis.default.service.nomad.        IN    SRV

;; ANSWER SECTION:
redis.default.service.nomad.    8    IN    SRV    10 10 25395 redis.default.service.nomad.
redis.default.service.nomad.    8    IN    SRV    10 10 20888 redis.default.service.nomad.
redis.default.service.nomad.    8    IN    SRV    10 10 26292 redis.default.service.nomad.

;; ADDITIONAL SECTION:
redis.default.service.nomad.    8    IN    A    192.168.29.76
redis.default.service.nomad.    8    IN    A    192.168.29.76
redis.default.service.nomad.    8    IN    A    192.168.29.76

;; Query time: 0 msec
;; SERVER: 127.0.0.1#1053(127.0.0.1) (UDP)
;; WHEN: Thu Jan 05 12:12:20 IST 2023
;; MSG SIZE  rcvd: 339

🧚 SOA RECORD

$ dig @localhost -p 1053 1dns.default.service.nomad.

; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> @localhost -p 1053 1dns.default.service.nomad.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 21012
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 6d146bb140b4d8ca (echoed)
;; QUESTION SECTION:
;1dns.default.service.nomad.    IN      A

;; ANSWER SECTION:
1dns.default.service.nomad. 5   IN      SOA     ns1.1dns.default.service.nomad. ns1.1dns.default.service.nomad. 1 3600 600 604800 3600

;; Query time: 0 msec
;; SERVER: 127.0.0.1#1053(localhost) (UDP)
;; WHEN: Wed Aug 23 21:14:41 EEST 2023
;; MSG SIZE  rcvd: 189

that's the whole page bestie, no cap β€” every flag, every env var, every dig output, all of it πŸ’–

anyway this was CoreDNS, March 2026 edition β€” go forth and resolve, mwah πŸ’‹

πŸ“¦ where this page comes from