Skip to content
This repository has been archived by the owner on Oct 23, 2024. It is now read-only.

Support IPv6 #508

Merged
merged 13 commits into from
Oct 10, 2017
8 changes: 8 additions & 0 deletions dnstest/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ func A(hdr dns.RR_Header, ip net.IP) *dns.A {
}
}

// AAAA returns an AAAA record set with the given arguments.
func AAAA(hdr dns.RR_Header, ip net.IP) *dns.AAAA {
return &dns.AAAA{
Hdr: hdr,
AAAA: ip.To16(),
}
}

// SRV returns a SRV record set with the given arguments.
func SRV(hdr dns.RR_Header, target string, port, priority, weight uint16) *dns.SRV {
return &dns.SRV{
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/configuration-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ It is sufficient to specify just one of the `zk` or `masters` field. If both are

`timeout` is the timeout threshold, in seconds, for connections and requests to external DNS requests. The default value is 5 seconds.

`listener` is the IP address of Mesos-DNS. In SOA replies, Mesos-DNS identifies hostname `mesos-dns.domain` as the primary nameserver for the domain. It uses this IP address in an A record for `mesos-dns.domain`. The default value is "0.0.0.0", which instructs Mesos-DNS to create an A record for every IP address associated with a network interface on the server that runs the Mesos-DNS process.
`listener` is the IP address of Mesos-DNS. In SOA replies, Mesos-DNS identifies hostname `mesos-dns.domain` as the primary nameserver for the domain. It uses this IP address in an A or AAAA record for `mesos-dns.domain`. The default value is "0.0.0.0", which instructs Mesos-DNS to create an A record for every IP address associated with a network interface on the server that runs the Mesos-DNS process.

`dnson` is a boolean field that controls whether Mesos-DNS listens for DNS requests or not. The default value is `true`.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ curl http://10.190.238.173:8123/v1/config
```
## `GET /v1/hosts/{host}`

Lists in JSON format the IP address(es) that correspond to a hostname. It is the equivalent of DNS A record lookup. Note, the HTTP interface only translates hostnames in the Mesos domain.
Lists in JSON format the IP address(es) that correspond to a hostname. It is the equivalent of DNS A and AAAA record lookup. Note, the HTTP interface only translates hostnames in the Mesos domain.

```console
$ curl http://10.190.238.173:8123/v1/hosts/nginx.marathon.mesos
Expand Down
42 changes: 33 additions & 9 deletions docs/docs/naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ title: Service Naming

# Service Naming

Mesos-DNS defines a DNS domain for Mesos tasks (default `.mesos`, see [instructions on configuration](configuration-parameters.html)). Running tasks can be discovered by looking up A and, optionally, SRV records within the Mesos domain.
Mesos-DNS defines a DNS domain for Mesos tasks (default `.mesos`, see [instructions on configuration](configuration-parameters.html)). Running tasks can be discovered by looking up A, AAAA, and, optionally, SRV records within the Mesos domain.

## A Records
## A and AAAA Records

An A record associates a hostname to an IP address.
For task `task` launched by framework `framework`, Mesos-DNS generates an A record for hostname `task.framework.domain` that provides one of the following:
A and AAAA records associate a hostname to an IPv4 or IPv6 address respectively.
For task `task` launched by framework `framework`, Mesos-DNS generates an A or AAAA record for hostname `task.framework.domain` that provides one of the following:

- the IP address of the task's network container (provided by a Mesos containerizer); or
- the IP address of the specific slave running the task.
Expand Down Expand Up @@ -64,7 +64,31 @@ For example, a query of the A records for `search.marathon.slave.mesos` would yi
- `MesosContainerizer.NetworkSettings.IPAddress`.

In general support for these will not be available before Mesos 0.24.


If the following conditions are true...

- the Mesos-DNS IP-source configuration prioritizes container IPs; and
- the Mesos containerizer that launches the task provides a container IP `fd01:b::2:8000:2` for the task `search.marathon.mesos`

...then a lookup for AAAA would give:

``` console
$ dig search.marathon.mesos

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> search.marathon.mesos
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45066
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;search.marathon.mesos. IN AAAA

;; ANSWER SECTION:
search.marathon.mesos. 60 IN AAAA fd01:b::2:8000:2
```


## SRV Records

An SRV record associates a service name to a hostname and an IP port.
Expand Down Expand Up @@ -102,10 +126,10 @@ The following table illustrates the rules that govern SRV generation:
## Other Records

Mesos-DNS generates a few special records:
- for the leading master: A record (`leader.domain`) and SRV records (`_leader._tcp.domain` and `_leader._udp.domain`); and
- for all framework schedulers: A records (`{framework}.domain`) and SRV records (`_framework._tcp.{framework}.domain`)
- for every known Mesos master: A records (`master.domain`) and SRV records (`_master._tcp.domain` and `_master._udp.domain`); and
- for every known Mesos slave: A records (`slave.domain`) and SRV records (`_slave._tcp.domain`).
- for the leading master: A or AAAA record (`leader.domain`) and SRV records (`_leader._tcp.domain` and `_leader._udp.domain`); and
- for all framework schedulers: A and AAAA records (`{framework}.domain`) and SRV records (`_framework._tcp.{framework}.domain`)
- for every known Mesos master: A or AAAA records (`master.domain`) and SRV records (`_master._tcp.domain` and `_master._udp.domain`); and
- for every known Mesos slave: A or AAAA records (`slave.domain`) and SRV records (`_slave._tcp.domain`).

Note that, if you configure Mesos-DNS to detect the leading master through Zookeeper, then this is the only master it knows about.
If you configure Mesos-DNS using the `masters` field, it will generate master records for every master in the list.
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ Mesos-DNS is designed to be a minimal, stateless service that is easy to deploy
<img src="{{ site.baseurl}}/img/architecture.png" width="610" height="320" alt="">
</p>

Mesos-DNS periodically queries the Mesos master(s), retrieves the state of all running tasks from all running frameworks, and generates DNS records for these tasks (A and SRV records). As tasks start, finish, fail, or restart on the Mesos cluster, Mesos-DNS updates the DNS records to reflect the latest state. The configuration of Mesos-DNS is minimal. You simply point it to the Mesos masters at launch. Frameworks do not need to communicate with Mesos-DNS at all. Applications and services running on Mesos slaves can discover the IP addresses and ports of other applications they depend upon by issuing DNS lookup requests or by issuing HTTP request through a REST API. Mesos-DNS replies directly to requests for tasks launched by Mesos. For DNS requests for other hostnames or services, Mesos-DNS uses an external nameserver to derive replies. Alternatively, you can configure your existing DNS server to forward only the requests for Mesos tasks to Mesos-DNS.
Mesos-DNS periodically queries the Mesos master(s), retrieves the state of all running tasks from all running frameworks, and generates DNS records for these tasks (A, AAAA, and SRV records). As tasks start, finish, fail, or restart on the Mesos cluster, Mesos-DNS updates the DNS records to reflect the latest state. The configuration of Mesos-DNS is minimal. You simply point it to the Mesos masters at launch. Frameworks do not need to communicate with Mesos-DNS at all. Applications and services running on Mesos slaves can discover the IP addresses and ports of other applications they depend upon by issuing DNS lookup requests or by issuing HTTP request through a REST API. Mesos-DNS replies directly to requests for tasks launched by Mesos. For DNS requests for other hostnames or services, Mesos-DNS uses an external nameserver to derive replies. Alternatively, you can configure your existing DNS server to forward only the requests for Mesos tasks to Mesos-DNS.

Mesos-DNS is simple and stateless. It does not require consensus mechanisms, persistent storage, or a replicated log. This is possible because Mesos-DNS does not implement heartbeats, health monitoring, or lifetime management for applications. This functionality is already available by the Mesos master, slaves, and frameworks. Mesos-DNS can be made fault-tolerant by launching with a framework like [Marathon](https://github.com/mesosphere/marathon), that can monitor application health and re-launch it on failures. On restart after a failure, Mesos-DNS retrieves the latest state from the Mesos master(s) and serves DNS requests without further coordination. It can be easily replicated to improve availability or to load balance DNS requests in clusters with large numbers of slaves.
81 changes: 80 additions & 1 deletion factories/fake.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"activated_slaves": 3,
"activated_slaves": 4,
"build_date": "2014-07-18 18:52:23",
"build_time": 1405709543,
"build_user": "root",
Expand Down Expand Up @@ -38,6 +38,69 @@
"zk_session_timeout": "10secs"
},
"frameworks": [
{
"active": true,
"checkpoint": false,
"completed_tasks": [],
"failover_timeout": 1200,
"hostname": "localhost",
"pid": "scheduler(1)@[2001:db8::1]:25501",
"id": "20140703-014514-3041283216-5050-5349-0001",
"name": "ipv6-framework",
"offers": [],
"registered_time": 1414913537.10742,
"reregistered_time": 1414913537.10744,
"resources": {
"cpus": 0,
"disk": 0,
"mem": 0
},
"role": "*",
"tasks": [
{
"executor_id": "",
"framework_id": "20140703-014514-3041283216-5050-5349-0001",
"id": "toy-store.b8db9f73-562f-11e4-a088-c20493233aa5",
"name": "toy-store",
"resources": {
"cpus": 1,
"disk": 0,
"mem": 1024,
"ports": "[31354-31354, 31355-31355]"
},
"slave_id": "20140803-194712-3041283216-5050-2116-3",
"state": "TASK_RUNNING",
"statuses": [
{
"state": "TASK_RUNNING",
"timestamp": 1507139816.34576,
"container_status": {
"container_id": {
"value": "da87d8aa-98f1-4fc3-a260-f92c116fc926"
},
"network_infos": [
{
"ip_addresses": [
{
"protocol": "IPv4",
"ip_address": "12.0.1.2"
},
{
"protocol": "IPv6",
"ip_address": "fd01:b::1:8000:2"
}
],
"name": "dcos6"
}
]
}
}
]
}
],
"unregistered_time": 0,
"user": "root"
},
{
"active": true,
"checkpoint": false,
Expand Down Expand Up @@ -619,6 +682,22 @@
"mem": 31016,
"ports": "[31000-32000]"
}
},
{
"attributes": {
"host": "dev-123-1g.c.mesos.internal"
},
"hostname": "2001:db8::1",
"id": "20140803-194712-3041283216-5050-2116-3",
"pid": "slave(1)@[2001:db8::1]:5051",
"registered_time": 1414913537.56731,
"reregistered_time": 1414913537.56735,
"resources": {
"cpus": 8,
"disk": 1855784,
"mem": 31016,
"ports": "[31000-32000]"
}
}
],
"staged_tasks": 310,
Expand Down
7 changes: 4 additions & 3 deletions models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ type AXFRResourceRecordSet map[string][]string
// This is the internal structure of how mesos-dns works today and the transformation of string -> DNS Struct
// happens on actual query time. Why this logic happens at query time? Who knows.

// AXFRRecords are the As, and SRVs that actually make up the Mesos-DNS zone
// AXFRRecords are the As, AAAAs, and SRVs that actually make up the Mesos-DNS zone
type AXFRRecords struct {
As AXFRResourceRecordSet
SRVs AXFRResourceRecordSet
As AXFRResourceRecordSet
AAAAs AXFRResourceRecordSet
SRVs AXFRResourceRecordSet
}

// AXFR is a rough representation of a "transfer" of the Mesos-DNS data
Expand Down
8 changes: 6 additions & 2 deletions records/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,13 @@ func localAddies() []string {
if err != nil {
logging.Error.Println(err)
}
t4 := ip.To4()
if t4 != nil {
// The servers in cservers above could include
// ipv6, so we should include local ipv6 for
// that filtering
if t4 := ip.To4(); t4 != nil {
bad = append(bad, t4.String())
} else if t6 := ip.To16(); t6 != nil {
bad = append(bad, t6.String())
}
}

Expand Down
9 changes: 3 additions & 6 deletions records/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ import (
)

func TestNonLocalAddies(t *testing.T) {
nlocal := []string{"127.0.0.1"}
nlocal := localAddies()
addies := nonLocalAddies(nlocal)

for i := 0; i < len(addies); i++ {
if "127.0.0.1" == addies[i] {
t.Error("finding a local address")
}
if len(addies) > 0 {
t.Error("finding a local address")
}
}

Expand Down
Loading