Fix a couple of edge cases in service discovery

The first issue is an ordering problem where sandbox
attached version of endpoint object should be pushed
to the watch database first so that any other create endpoint
which is in progress can make use of it immediately to update
the container hosts file. And only after that the current
container should try to retrieve the service records from the
service data base and upate it's hosts file. With the previous
order there is a small time window, when another endpoint create
will find this endpoint but it doesn't have the sandbox context
while the svc record population from svc db has already happened
so that container will totally miss to populate the service record
of the newly created endpoint.

The second issue is trying to rebuild the /etc/hosts file from scratch
during endpoint join and this may sometimes happen after the service
record add for another endpoint  has happened on the container
file. Obviously this rebuilding will wipe out that service record which
was just added. Removed the rebuilding of /etc/hosts file during
endpoint join. The initial population of /etc/hosts file should only
happen during sandbox creation time. In the endpoint join just added
the backward-compatible self ip -> hostname entry as just another
record.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
Jana Radhakrishnan 2015-11-25 15:25:56 -08:00
parent 99cf6ccf90
commit 84abbcefa8
2 changed files with 11 additions and 32 deletions

View File

@ -386,6 +386,9 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
}
}()
// Watch for service records
network.getController().watchSvcRecord(ep)
address := ""
if ip := ep.getFirstInterfaceAddress(); ip != nil {
address = ip.String()
@ -394,9 +397,6 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
return err
}
// Watch for service records
network.getController().watchSvcRecord(ep)
if err = sb.updateDNS(network.enableIPv6); err != nil {
return err
}

View File

@ -62,7 +62,6 @@ type sandbox struct {
osSbox osl.Sandbox
controller *controller
refCnt int
hostsOnce sync.Once
endpoints epHeap
epPriority map[string]int
joinLeaveDone chan struct{}
@ -601,41 +600,21 @@ func (sb *sandbox) buildHostsFile() error {
}
func (sb *sandbox) updateHostsFile(ifaceIP string, svcRecords []etchosts.Record) error {
var err error
var mhost string
if sb.config.originHostsPath != "" {
return nil
}
max := func(a, b int) int {
if a < b {
return b
}
return a
if sb.config.domainName != "" {
mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName,
sb.config.hostName)
} else {
mhost = sb.config.hostName
}
extraContent := make([]etchosts.Record, 0,
max(len(sb.config.extraHosts), len(svcRecords)))
sb.hostsOnce.Do(func() {
// Rebuild the hosts file accounting for the passed
// interface IP and service records
for _, extraHost := range sb.config.extraHosts {
extraContent = append(extraContent,
etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
}
err = etchosts.Build(sb.config.hostsPath, ifaceIP,
sb.config.hostName, sb.config.domainName, extraContent)
})
if err != nil {
return err
}
extraContent = extraContent[:0]
extraContent := make([]etchosts.Record, 0, len(svcRecords)+1)
extraContent = append(extraContent, etchosts.Record{Hosts: mhost, IP: ifaceIP})
for _, svc := range svcRecords {
extraContent = append(extraContent, svc)
}