Skip to content

Commit 9e36b3c

Browse files
committed
Support service aliases that differ by container
Signed-off-by: Ben Turner <[email protected]>
1 parent 6ecd8ad commit 9e36b3c

File tree

2 files changed

+89
-48
lines changed

2 files changed

+89
-48
lines changed

Diff for: service.go

+18-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"sync"
77

88
"github.com/docker/libnetwork/common"
9+
mapset "github.com/deckarep/golang-set"
910
)
1011

1112
var (
@@ -47,9 +48,6 @@ type service struct {
4748
// List of ingress ports exposed by the service
4849
ingressPorts portConfigs
4950

50-
// Service aliases
51-
aliases []string
52-
5351
// This maps tracks for each IP address the list of endpoints ID
5452
// associated with it. At stable state the endpoint ID expected is 1
5553
// but during transition and service change it is possible to have
@@ -79,6 +77,19 @@ func (s *service) printIPToEndpoint(ip string) (string, bool) {
7977
return s.ipToEndpoint.String(ip)
8078
}
8179

80+
// aliasSet returns the union of service aliases for all backends.
81+
func (s *service) aliasSet() (mapset.Set) {
82+
set := mapset.NewSet()
83+
for _, lb := range s.loadBalancers {
84+
for _, be := range lb.backEnds {
85+
for _, alias := range be.serviceAliases {
86+
set.Add(alias)
87+
}
88+
}
89+
}
90+
return set
91+
}
92+
8293
type loadBalancer struct {
8394
vip net.IP
8495
fwMark uint32
@@ -92,7 +103,8 @@ type loadBalancer struct {
92103
}
93104

94105
type loadBalancerBackend struct {
95-
ip net.IP
96-
containerName string
97-
taskAliases []string
106+
ip net.IP
107+
containerName string
108+
serviceAliases []string
109+
taskAliases []string
98110
}

Diff for: service_common.go

+71-42
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ import (
66
"net"
77

88
"github.com/Sirupsen/logrus"
9+
mapset "github.com/deckarep/golang-set"
910
"github.com/docker/libnetwork/common"
1011
)
1112

12-
func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, addService bool, method string) error {
13+
func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, method string) error {
1314
n, err := c.NetworkByID(nID)
1415
if err != nil {
1516
return err
1617
}
1718

18-
logrus.Debugf("addEndpointNameResolution %s %s add_service:%t", eID, svcName, addService)
19+
logrus.Debugf("addEndpointNameResolution %s %s add_service", eID, svcName)
1920

2021
// Add container resolution mappings
2122
c.addContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)
@@ -27,18 +28,14 @@ func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, contain
2728
}
2829

2930
// Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR
31+
svcIP := vip
3032
if len(vip) == 0 {
31-
n.(*network).addSvcRecords(eID, svcName, ip, nil, false, method)
32-
for _, alias := range serviceAliases {
33-
n.(*network).addSvcRecords(eID, alias, ip, nil, false, method)
34-
}
33+
svcIP = ip
3534
}
3635

37-
if addService && len(vip) != 0 {
38-
n.(*network).addSvcRecords(eID, svcName, vip, nil, false, method)
39-
for _, alias := range serviceAliases {
40-
n.(*network).addSvcRecords(eID, alias, vip, nil, false, method)
41-
}
36+
n.(*network).addSvcRecords(eID, svcName, svcIP, nil, false, method)
37+
for _, alias := range serviceAliases {
38+
n.(*network).addSvcRecords(eID, alias, svcIP, nil, false, method)
4239
}
4340

4441
return nil
@@ -62,39 +59,38 @@ func (c *controller) addContainerNameResolution(nID, eID, containerName string,
6259
return nil
6360
}
6461

65-
func (c *controller) deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, rmService, multipleEntries bool, method string) error {
62+
func (c *controller) deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, tasksServiceAliases, taskAliases []string, ip net.IP, rmService, multipleEntries bool, method string) error {
6663
n, err := c.NetworkByID(nID)
6764
if err != nil {
6865
return err
6966
}
7067

7168
logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t", eID, svcName, rmService, multipleEntries)
72-
7369
// Delete container resolution mappings
7470
c.delContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)
7571

72+
if multipleEntries {
73+
return nil
74+
}
75+
7676
// Delete the special "tasks.svc_name" backend record.
77-
if !multipleEntries {
78-
n.(*network).deleteSvcRecords(eID, "tasks."+svcName, ip, nil, false, method)
79-
for _, alias := range serviceAliases {
80-
n.(*network).deleteSvcRecords(eID, "tasks."+alias, ip, nil, false, method)
81-
}
77+
n.(*network).deleteSvcRecords(eID, "tasks."+svcName, ip, nil, false, method)
78+
for _, alias := range tasksServiceAliases {
79+
n.(*network).deleteSvcRecords(eID, "tasks."+alias, ip, nil, false, method)
8280
}
8381

8482
// If we are doing DNS RR delete the endpoint IP from DNS record right away.
85-
if !multipleEntries && len(vip) == 0 {
86-
n.(*network).deleteSvcRecords(eID, svcName, ip, nil, false, method)
87-
for _, alias := range serviceAliases {
88-
n.(*network).deleteSvcRecords(eID, alias, ip, nil, false, method)
89-
}
83+
svcIP := vip
84+
if len(vip) == 0 {
85+
svcIP = ip
9086
}
9187

92-
// Remove the DNS record for VIP only if we are removing the service
93-
if rmService && len(vip) != 0 && !multipleEntries {
94-
n.(*network).deleteSvcRecords(eID, svcName, vip, nil, false, method)
95-
for _, alias := range serviceAliases {
96-
n.(*network).deleteSvcRecords(eID, alias, vip, nil, false, method)
97-
}
88+
if rmService {
89+
n.(*network).deleteSvcRecords(eID, svcName, svcIP, nil, false, method)
90+
}
91+
92+
for _, alias := range serviceAliases {
93+
n.(*network).deleteSvcRecords(eID, alias, svcIP, nil, false, method)
9894
}
9995

10096
return nil
@@ -118,13 +114,12 @@ func (c *controller) delContainerNameResolution(nID, eID, containerName string,
118114
return nil
119115
}
120116

121-
func newService(name string, id string, ingressPorts []*PortConfig, serviceAliases []string) *service {
117+
func newService(name string, id string, ingressPorts []*PortConfig) *service {
122118
return &service{
123119
name: name,
124120
id: id,
125121
ingressPorts: ingressPorts,
126122
loadBalancers: make(map[string]*loadBalancer),
127-
aliases: serviceAliases,
128123
ipToEndpoint: common.NewSetMatrix(),
129124
}
130125
}
@@ -180,7 +175,7 @@ func (c *controller) cleanupServiceBindings(cleanupNID string) {
180175

181176
cleanupFuncs = append(cleanupFuncs, func() {
182177
if err := c.rmServiceBinding(service.name, service.id, networkID, epID, be.containerName, loadBalancer.vip,
183-
service.ingressPorts, service.aliases, be.taskAliases, epIP, "cleanupServiceBindings"); err != nil {
178+
service.ingressPorts, be.serviceAliases, be.taskAliases, epIP, "cleanupServiceBindings"); err != nil {
184179
logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
185180
service.id, networkID, epID, err)
186181
}
@@ -197,8 +192,6 @@ func (c *controller) cleanupServiceBindings(cleanupNID string) {
197192
}
198193

199194
func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases, taskAliases []string, ip net.IP, method string) error {
200-
var addService bool
201-
202195
n, err := c.NetworkByID(nID)
203196
if err != nil {
204197
return err
@@ -217,7 +210,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
217210
if !ok {
218211
// Create a new service if we are seeing this service
219212
// for the first time.
220-
s = newService(svcName, svcID, ingressPorts, serviceAliases)
213+
s = newService(svcName, svcID, ingressPorts)
221214
c.serviceBindings[skey] = s
222215
}
223216
c.Unlock()
@@ -250,12 +243,12 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
250243
fwMarkCtrMu.Unlock()
251244

252245
s.loadBalancers[nID] = lb
253-
addService = true
254246
}
255247

256248
lb.backEnds[eID] = loadBalancerBackend{ip: ip,
257-
containerName: containerName,
258-
taskAliases: taskAliases}
249+
containerName: containerName,
250+
serviceAliases: serviceAliases,
251+
taskAliases: taskAliases}
259252

260253
ok, entries := s.assignIPToEndpoint(ip.String(), eID)
261254
if !ok || entries > 1 {
@@ -270,15 +263,14 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
270263
}
271264

272265
// Add the appropriate name resolutions
273-
c.addEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, addService, "addServiceBinding")
266+
c.addEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, "addServiceBinding")
274267

275268
logrus.Debugf("addServiceBinding from %s END for %s %s", method, svcName, eID)
276269

277270
return nil
278271
}
279272

280273
func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases []string, taskAliases []string, ip net.IP, method string) error {
281-
282274
var rmService bool
283275

284276
n, err := c.NetworkByID(nID)
@@ -308,7 +300,7 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
308300
return nil
309301
}
310302

311-
_, ok = lb.backEnds[eID]
303+
be, ok := lb.backEnds[eID]
312304
if !ok {
313305
logrus.Warnf("rmServiceBinding %s %s %s aborted lb.backEnds[eid] !ok", method, svcName, eID)
314306
return nil
@@ -347,8 +339,45 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
347339
n.(*network).rmLBBackend(ip, vip, lb.fwMark, ingressPorts, rmService)
348340
}
349341

342+
// Always clean up all possible aliases for the special "tasks.<alias>" names.
343+
tasksServiceAliases := serviceAliases
344+
logrus.Debugf("tasksServiceAliases %s", tasksServiceAliases)
345+
346+
if len(vip) == 0 {
347+
// If not using a VIP then always remove the service and all its aliases.
348+
rmService = true
349+
} else if !rmService {
350+
// Make sure to only remove the VIP when the last alias referencing it has
351+
// been removed, but remove any service aliases that are no longer needed.
352+
epAliasSet := mapset.NewSet()
353+
for _, alias := range serviceAliases {
354+
epAliasSet.Add(alias)
355+
}
356+
357+
// This had better be redundant but just in case...
358+
for _, alias := range be.serviceAliases {
359+
epAliasSet.Add(alias)
360+
}
361+
362+
logrus.Debugf("epAliasSet %s", epAliasSet)
363+
364+
sAliasSet := s.aliasSet()
365+
logrus.Debugf("sAliasSet %s", sAliasSet)
366+
367+
for alias := range sAliasSet.Iter() {
368+
epAliasSet.Remove(alias)
369+
}
370+
371+
serviceAliases = make([]string, 0, epAliasSet.Cardinality())
372+
for alias := range epAliasSet.Iter() {
373+
serviceAliases = append(serviceAliases, alias.(string))
374+
}
375+
}
376+
377+
logrus.Debugf("serviceAliases %s", serviceAliases)
378+
350379
// Delete the name resolutions
351-
c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding")
380+
c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, tasksServiceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding")
352381

353382
logrus.Debugf("rmServiceBinding from %s END for %s %s", method, svcName, eID)
354383
return nil

0 commit comments

Comments
 (0)