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
Merged

Support IPv6 #508

merged 13 commits into from
Oct 10, 2017

Conversation

drewkerrigan
Copy link
Contributor

@drewkerrigan drewkerrigan commented Sep 30, 2017

Get DC/OS with IPv6

Start a new DC/OS cluster with this image:

wget https://downloads.dcos.io/dcos/testing/pull/1842/dcos_generate_config.sh

Replace existing Mesos-DNS

On each master, update Mesos-DNS config:

In /opt/mesosphere/etc/mesos-dns.json:

Change "IPSources": ["host", "netinfo"], -> "IPSources": ["netinfo", "host"],

Then get the new mesos-dns with the following commands:

cd /opt/mesosphere/packages/mesos-dns--600da87080b7634f2380594499004a7ff0b34662/bin
mv mesos-dns mesos-dns.bak
curl -O https://959-26509179-gh.circle-artifacts.com/0/tmp/circle-artifacts.Dv9WDHl/mesos-dns--linux-amd64 --output mesos-dns--linux-amd64
mv mesos-dns--linux-amd64 mesos-dns
chmod 755 mesos-dns
systemctl restart dcos-mesos-dns.service

Create a test app on dcos6 network

{
    "id": "/ipv6-nginx",
    "cmd": "nginx -g 'daemon off;'",
    "instances": 1,
    "cpus": 0.1,
    "mem": 32,
    "container": {
        "type": "DOCKER",
        "docker": {
            "image": "nginx:stable"
        },
        "portMappings": [
            {
                "containerPort": 80,
                "protocol": "tcp",
                "name": "web"
            }
        ]
    },
    "requirePorts": false,
    "networks": [
        {
            "name": "dcos6",
            "mode": "container"
        }
    ],
    "healthChecks": [],
    "fetch": [],
    "constraints": []
}

Test the changes

dig ipv6-nginx.marathon.mesos ANY

dig ipv6-nginx.marathon.mesos AAAA

dig _ipv6-nginx._tcp.marathon.mesos SRV

curl leader.mesos:8123/v1/hosts/ipv6-nginx.marathon.mesos

curl leader.mesos:8123/v1/services/_ipv6-nginx._tcp.marathon.mesos

curl leader.mesos:8123/v1/enumerate

Copy link

@urbanserj urbanserj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@jdef jdef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completed an initial, quick pass over the non-test changes. Will take another spin through later.

ipv4 is preferred in several places to ipv6 - why? should this preference instead be controlled by config param?

also, what's up with the flapping mesos-go deps?

i initially thought to review each commit individually but ended up just reviewing the "merged" commit stream. in the future it would be great to have a more well-structured commit stream to simplify the review process

}
if ipv4 != nil {
rg.insertRR(a, ipv4.String(), A)
// Prefer ipv4 for slaveIP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this a preference? can you elaborate here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid point - I can instead make SlaveIPs a map of lists of strings so that we can later add records for both ipv4 and ipv6 for .slave.mesos recs

srv := net.JoinHostPort(a, slave.PID.Port)
rg.insertRR("_slave._tcp."+domain+".", srv, SRV)
} else {
logging.VeryVerbose.Printf("string '%q' for slave with id %q is not a valid IP address", address, slave.ID)
address = labels.DomainFrag(address, labels.Sep, spec)
logging.VeryVerbose.Printf("string '%q' for slave with id %q is not a valid IP address", slave.PID.Host, slave.ID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you didn't do this, but since you're changing the line: please remove the single-quotes wrapping the %q

} else if ip.To16() != nil {
return AAAA
}
return A
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this panic instead? it's unlikely that we'd ever end up here but I hate silent failures

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, my only concern is that there are a bunch of tests with master "ip addresses" like 6, or bob, etc. I assume the tests are just flawed and I can make them into valid ipv4 addresses to pass the tests, but I'm not sure if there's a valid use case for masters with non-ip hostnames in master pids / addresses. Should we maybe just not create records and error log for those cases? I'm also fine with panic.

if parsedIP := net.ParseIP(ip); parsedIP != nil {
return rrsKindForIP(parsedIP)
}
return A
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

panic? otherwise, what are the cases where returning A makes sense here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment.

// hostToIPs attempts to parse hostname into an ip. If that doesn't work it will perform a
// lookup and try to find one ipv4 and one ipv6 in the results.
func hostToIPs(hostname string) (ipv4, ipv6 net.IP, ok bool) {
ok = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok = false in superfluous, please remove

ipv4 = t4.IP
ok = true
} else {
logging.Error.Printf("cannot translate hostname %q into an ip4 address", hostname)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we log this for ipv4 but not for ipv6? should this be verbose?

}
}
}
return ipv4, ipv6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just return here w/o args is sufficient

ok = true
}
}
return ipv4, ipv6, ok
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just return here w/o args is sufficient

@@ -389,6 +415,14 @@ func (res *Resolver) handleSRV(rs *records.RecordGenerator, name string, m, r *d
}
m.Extra = append(m.Extra, aRR)
added[host] = struct{}{}
} else if aaaa, ok := rs.AAAAs.First(host); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why only append these if ipv4 isn't found? why can't we return both? (or is that not kosher?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct, this was an oversight

@@ -718,6 +760,8 @@ func (res *Resolver) RestService(req *restful.Request, resp *restful.Response) {
var ip string
if r, ok := rs.As.First(host); ok {
ip = r
} else if r, ok := rs.AAAAs.First(host); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is ipv4 preferred?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another oversight, should have both.

@drewkerrigan
Copy link
Contributor Author

drewkerrigan commented Oct 5, 2017

@jdef PTAL.

re: "ipv4 is preferred in several places to ipv6 - why?"

  • This was mainly due to some flawed assumptions I made. After taking another go at it, I realized we can and should use both when available.

re: "also, what's up with the flapping mesos-go deps?"

  • I initially thought that I would need an updated mesos-go ([WIP] Support masters on ipv6 mesos/mesos-go#328 has an updated upid package) but later decided to just copy a subset of upid into records/state/upid with the fixed Parse function. We should eventually get mesos-go updated though. I also noticed you already had another PR to update mesos-go to the new api/v0 (Upgrade to latest mesos-go #496).

re: "in the future it would be great to have a more well-structured commit stream to simplify the review process"

  • I can restructure commits before merge or sooner if you'd like - no excuses here :-)

Copy link
Contributor

@jdef jdef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better, thanks. left a few more comments.

also, mind updating the docs to indicate that ipv6 is now supported?

rg.insertTaskRR(arec+".slave"+tail, sIP.String(), rrsKindForIP(sIP), enumTask)
rg.insertTaskRR(canonical+".slave"+tail, sIP.String(), rrsKindForIP(sIP), enumTask)
} else {
// ack: slave IP may not be an actual IP if labels.DomainFrag was used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. this is suspect. if not debugging/fixing this issue here, should probably create an issue to track

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #509 and I'll reference from the comment.

@@ -166,8 +166,8 @@ func statuses(st ...Status) taskOpt {
}
}

func slaveIP(ip string) taskOpt {
return func(t *Task) { t.SlaveIP = ip }
func slaveIPs(ip string) taskOpt {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: func slaveIPs(ip ...string) taskOpt { ... }

if err != nil {
errs.Add(err)
continue
if _, aFound := aAdded[host]; !aFound {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth using different priorities for ipv4 records vs ipv6 records? via http://ipv6friday.org/blog/2012/01/ipv6-and-dns/

An IPv4 client should check the lowest priority first and find out that there’s no available host in that priority and switch to the second priority. An IPv6 client finds a host in the lowest priority. A dual stack client will also find the IPv6 host first and stick to that. DNS SRV records are for you to define how you want to be reached.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the SRV records themselves have the Priority field, so this would only make sense if we were creating different SRV hostname records for ipv4 and ipv6 which we aren't currently. The code you commented on is only referring to the additional section. So in the example:

;; QUESTION SECTION:
;_ipv6-nginx._tcp.marathon.mesos. IN	SRV

;; ANSWER SECTION:
_ipv6-nginx._tcp.marathon.mesos. 60 IN	SRV	0 0 80 ipv6-nginx-6ijia-s1.marathon.mesos.

;; ADDITIONAL SECTION:
ipv6-nginx-6ijia-s1.marathon.mesos. 60 IN A	12.0.2.2
ipv6-nginx-6ijia-s1.marathon.mesos. 60 IN AAAA	fd01:b::2:8000:2

Where there are both IPv4 and IPv6 records for a single host (ipv6-nginx-6ijia-s1.marathon.mesos.), it would be up to the client to decide which they prefer. Priority would only apply if we were doing something like ipv6-nginx-6ijia-s1.marathon.mesos. for A and ipv6-nginx-6ijia-s1.preferred.marathon.mesos. for AAAA, and then we would have 2 separate SRV records for _ipv6-nginx._tcp.marathon.mesos..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, thanks for clarifying.

@drewkerrigan
Copy link
Contributor Author

@jdef PTAL, I made some minor updates to the docs and addressed the other comments.

@drewkerrigan
Copy link
Contributor Author

@jdef @urbanserj ping - updated the description with steps to test it out if you're interested.

Copy link
Contributor

@jdef jdef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Is there a plan to write some DC/OS ipv6 integration tests that will exercise these changes?

@drewkerrigan
Copy link
Contributor Author

@jdef yes we'll add integration tests with the related DC/OS PR

@drewkerrigan drewkerrigan merged commit be53925 into master Oct 10, 2017
@GoelDeepak GoelDeepak deleted the ack/ipv6 branch February 10, 2018 02:42
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants