|
@@ -15,29 +15,35 @@ func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, contain
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
- logrus.Debugf("addEndpointNameResolution %s %s add_service:%t", eID, svcName, addService)
|
|
|
|
|
|
+ logrus.Debugf("addEndpointNameResolution %s %s add_service:%t sAliases:%v tAliases:%v", eID, svcName, addService, serviceAliases, taskAliases)
|
|
|
|
|
|
// Add container resolution mappings
|
|
// Add container resolution mappings
|
|
c.addContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)
|
|
c.addContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)
|
|
|
|
|
|
|
|
+ serviceID := svcID
|
|
|
|
+ if serviceID == "" {
|
|
|
|
+ // This is the case of a normal container not part of a service
|
|
|
|
+ serviceID = eID
|
|
|
|
+ }
|
|
|
|
+
|
|
// Add endpoint IP to special "tasks.svc_name" so that the applications have access to DNS RR.
|
|
// Add endpoint IP to special "tasks.svc_name" so that the applications have access to DNS RR.
|
|
- n.(*network).addSvcRecords(eID, "tasks."+svcName, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method)
|
|
for _, alias := range serviceAliases {
|
|
for _, alias := range serviceAliases {
|
|
- n.(*network).addSvcRecords(eID, "tasks."+alias, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method)
|
|
}
|
|
}
|
|
|
|
|
|
// Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR
|
|
// Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR
|
|
if len(vip) == 0 {
|
|
if len(vip) == 0 {
|
|
- n.(*network).addSvcRecords(eID, svcName, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, svcName, serviceID, ip, nil, false, method)
|
|
for _, alias := range serviceAliases {
|
|
for _, alias := range serviceAliases {
|
|
- n.(*network).addSvcRecords(eID, alias, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, alias, serviceID, ip, nil, false, method)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if addService && len(vip) != 0 {
|
|
if addService && len(vip) != 0 {
|
|
- n.(*network).addSvcRecords(eID, svcName, vip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, svcName, serviceID, vip, nil, false, method)
|
|
for _, alias := range serviceAliases {
|
|
for _, alias := range serviceAliases {
|
|
- n.(*network).addSvcRecords(eID, alias, vip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, alias, serviceID, vip, nil, false, method)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -52,11 +58,11 @@ func (c *controller) addContainerNameResolution(nID, eID, containerName string,
|
|
logrus.Debugf("addContainerNameResolution %s %s", eID, containerName)
|
|
logrus.Debugf("addContainerNameResolution %s %s", eID, containerName)
|
|
|
|
|
|
// Add resolution for container name
|
|
// Add resolution for container name
|
|
- n.(*network).addSvcRecords(eID, containerName, ip, nil, true, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, containerName, eID, ip, nil, true, method)
|
|
|
|
|
|
// Add resolution for taskaliases
|
|
// Add resolution for taskaliases
|
|
for _, alias := range taskAliases {
|
|
for _, alias := range taskAliases {
|
|
- n.(*network).addSvcRecords(eID, alias, ip, nil, true, method)
|
|
|
|
|
|
+ n.(*network).addSvcRecords(eID, alias, eID, ip, nil, true, method)
|
|
}
|
|
}
|
|
|
|
|
|
return nil
|
|
return nil
|
|
@@ -68,32 +74,38 @@ func (c *controller) deleteEndpointNameResolution(svcName, svcID, nID, eID, cont
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
- logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t", eID, svcName, rmService, multipleEntries)
|
|
|
|
|
|
+ logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t sAliases:%v tAliases:%v", eID, svcName, rmService, multipleEntries, serviceAliases, taskAliases)
|
|
|
|
|
|
// Delete container resolution mappings
|
|
// Delete container resolution mappings
|
|
c.delContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)
|
|
c.delContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)
|
|
|
|
|
|
|
|
+ serviceID := svcID
|
|
|
|
+ if serviceID == "" {
|
|
|
|
+ // This is the case of a normal container not part of a service
|
|
|
|
+ serviceID = eID
|
|
|
|
+ }
|
|
|
|
+
|
|
// Delete the special "tasks.svc_name" backend record.
|
|
// Delete the special "tasks.svc_name" backend record.
|
|
if !multipleEntries {
|
|
if !multipleEntries {
|
|
- n.(*network).deleteSvcRecords(eID, "tasks."+svcName, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method)
|
|
for _, alias := range serviceAliases {
|
|
for _, alias := range serviceAliases {
|
|
- n.(*network).deleteSvcRecords(eID, "tasks."+alias, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// If we are doing DNS RR delete the endpoint IP from DNS record right away.
|
|
// If we are doing DNS RR delete the endpoint IP from DNS record right away.
|
|
if !multipleEntries && len(vip) == 0 {
|
|
if !multipleEntries && len(vip) == 0 {
|
|
- n.(*network).deleteSvcRecords(eID, svcName, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, svcName, serviceID, ip, nil, false, method)
|
|
for _, alias := range serviceAliases {
|
|
for _, alias := range serviceAliases {
|
|
- n.(*network).deleteSvcRecords(eID, alias, ip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, alias, serviceID, ip, nil, false, method)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Remove the DNS record for VIP only if we are removing the service
|
|
// Remove the DNS record for VIP only if we are removing the service
|
|
if rmService && len(vip) != 0 && !multipleEntries {
|
|
if rmService && len(vip) != 0 && !multipleEntries {
|
|
- n.(*network).deleteSvcRecords(eID, svcName, vip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, svcName, serviceID, vip, nil, false, method)
|
|
for _, alias := range serviceAliases {
|
|
for _, alias := range serviceAliases {
|
|
- n.(*network).deleteSvcRecords(eID, alias, vip, nil, false, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, alias, serviceID, vip, nil, false, method)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -108,11 +120,11 @@ func (c *controller) delContainerNameResolution(nID, eID, containerName string,
|
|
logrus.Debugf("delContainerNameResolution %s %s", eID, containerName)
|
|
logrus.Debugf("delContainerNameResolution %s %s", eID, containerName)
|
|
|
|
|
|
// Delete resolution for container name
|
|
// Delete resolution for container name
|
|
- n.(*network).deleteSvcRecords(eID, containerName, ip, nil, true, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, containerName, eID, ip, nil, true, method)
|
|
|
|
|
|
// Delete resolution for taskaliases
|
|
// Delete resolution for taskaliases
|
|
for _, alias := range taskAliases {
|
|
for _, alias := range taskAliases {
|
|
- n.(*network).deleteSvcRecords(eID, alias, ip, nil, true, method)
|
|
|
|
|
|
+ n.(*network).deleteSvcRecords(eID, alias, eID, ip, nil, true, method)
|
|
}
|
|
}
|
|
|
|
|
|
return nil
|
|
return nil
|
|
@@ -152,6 +164,7 @@ func (c *controller) getLBIndex(sid, nid string, ingressPorts []*PortConfig) int
|
|
func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
|
func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
|
var cleanupFuncs []func()
|
|
var cleanupFuncs []func()
|
|
|
|
|
|
|
|
+ logrus.Debugf("cleanupServiceBindings for %s", cleanupNID)
|
|
c.Lock()
|
|
c.Lock()
|
|
services := make([]*service, 0, len(c.serviceBindings))
|
|
services := make([]*service, 0, len(c.serviceBindings))
|
|
for _, s := range c.serviceBindings {
|
|
for _, s := range c.serviceBindings {
|
|
@@ -171,16 +184,27 @@ func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
|
|
|
|
- for eid, be := range lb.backEnds {
|
|
|
|
|
|
+ // The network is being deleted, erase all the associated service discovery records
|
|
|
|
+ // TODO(fcrisciani) separate the Load Balancer from the Service discovery, this operation
|
|
|
|
+ // can be done safely here, but the rmServiceBinding is still keeping consistency in the
|
|
|
|
+ // data structures that are tracking the endpoint to IP mapping.
|
|
|
|
+ c.Lock()
|
|
|
|
+ logrus.Debugf("cleanupServiceBindings erasing the svcRecords for %s", nid)
|
|
|
|
+ delete(c.svcRecords, nid)
|
|
|
|
+ c.Unlock()
|
|
|
|
+
|
|
|
|
+ for eid, ip := range lb.backEnds {
|
|
|
|
+ epID := eid
|
|
|
|
+ epIP := ip
|
|
service := s
|
|
service := s
|
|
loadBalancer := lb
|
|
loadBalancer := lb
|
|
networkID := nid
|
|
networkID := nid
|
|
- epID := eid
|
|
|
|
- epIP := be.ip
|
|
|
|
-
|
|
|
|
cleanupFuncs = append(cleanupFuncs, func() {
|
|
cleanupFuncs = append(cleanupFuncs, func() {
|
|
- if err := c.rmServiceBinding(service.name, service.id, networkID, epID, be.containerName, loadBalancer.vip,
|
|
|
|
- service.ingressPorts, service.aliases, be.taskAliases, epIP, "cleanupServiceBindings"); err != nil {
|
|
|
|
|
|
+ // ContainerName and taskAliases are not available here, this is still fine because the Service discovery
|
|
|
|
+ // cleanup already happened before. The only thing that rmServiceBinding is still doing here a part from the Load
|
|
|
|
+ // Balancer bookeeping, is to keep consistent the mapping of endpoint to IP.
|
|
|
|
+ if err := c.rmServiceBinding(service.name, service.id, networkID, epID, "", loadBalancer.vip,
|
|
|
|
+ service.ingressPorts, service.aliases, []string{}, epIP, "cleanupServiceBindings", false); err != nil {
|
|
logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
|
|
logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
|
|
service.id, networkID, epID, err)
|
|
service.id, networkID, epID, err)
|
|
}
|
|
}
|
|
@@ -228,8 +252,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
|
|
}
|
|
}
|
|
s.Unlock()
|
|
s.Unlock()
|
|
}
|
|
}
|
|
- logrus.Debugf("addServiceBinding from %s START for %s %s", method, svcName, eID)
|
|
|
|
-
|
|
|
|
|
|
+ logrus.Debugf("addServiceBinding from %s START for %s %s p:%p nid:%s skey:%v", method, svcName, eID, s, nID, skey)
|
|
defer s.Unlock()
|
|
defer s.Unlock()
|
|
|
|
|
|
lb, ok := s.loadBalancers[nID]
|
|
lb, ok := s.loadBalancers[nID]
|
|
@@ -242,7 +265,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
|
|
lb = &loadBalancer{
|
|
lb = &loadBalancer{
|
|
vip: vip,
|
|
vip: vip,
|
|
fwMark: fwMarkCtr,
|
|
fwMark: fwMarkCtr,
|
|
- backEnds: make(map[string]loadBalancerBackend),
|
|
|
|
|
|
+ backEnds: make(map[string]net.IP),
|
|
service: s,
|
|
service: s,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -253,9 +276,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
|
|
addService = true
|
|
addService = true
|
|
}
|
|
}
|
|
|
|
|
|
- lb.backEnds[eID] = loadBalancerBackend{ip: ip,
|
|
|
|
- containerName: containerName,
|
|
|
|
- taskAliases: taskAliases}
|
|
|
|
|
|
+ lb.backEnds[eID] = ip
|
|
|
|
|
|
ok, entries := s.assignIPToEndpoint(ip.String(), eID)
|
|
ok, entries := s.assignIPToEndpoint(ip.String(), eID)
|
|
if !ok || entries > 1 {
|
|
if !ok || entries > 1 {
|
|
@@ -277,7 +298,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-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 {
|
|
|
|
|
|
+func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases []string, taskAliases []string, ip net.IP, method string, deleteSvcRecords bool) error {
|
|
|
|
|
|
var rmService bool
|
|
var rmService bool
|
|
|
|
|
|
@@ -294,7 +315,6 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
|
|
c.Lock()
|
|
c.Lock()
|
|
s, ok := c.serviceBindings[skey]
|
|
s, ok := c.serviceBindings[skey]
|
|
c.Unlock()
|
|
c.Unlock()
|
|
- logrus.Debugf("rmServiceBinding from %s START for %s %s", method, svcName, eID)
|
|
|
|
if !ok {
|
|
if !ok {
|
|
logrus.Warnf("rmServiceBinding %s %s %s aborted c.serviceBindings[skey] !ok", method, svcName, eID)
|
|
logrus.Warnf("rmServiceBinding %s %s %s aborted c.serviceBindings[skey] !ok", method, svcName, eID)
|
|
return nil
|
|
return nil
|
|
@@ -302,6 +322,7 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
|
|
|
|
|
|
s.Lock()
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
defer s.Unlock()
|
|
|
|
+ logrus.Debugf("rmServiceBinding from %s START for %s %s p:%p nid:%s sKey:%v deleteSvc:%t", method, svcName, eID, s, nID, skey, deleteSvcRecords)
|
|
lb, ok := s.loadBalancers[nID]
|
|
lb, ok := s.loadBalancers[nID]
|
|
if !ok {
|
|
if !ok {
|
|
logrus.Warnf("rmServiceBinding %s %s %s aborted s.loadBalancers[nid] !ok", method, svcName, eID)
|
|
logrus.Warnf("rmServiceBinding %s %s %s aborted s.loadBalancers[nid] !ok", method, svcName, eID)
|
|
@@ -322,17 +343,7 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
|
|
rmService = true
|
|
rmService = true
|
|
|
|
|
|
delete(s.loadBalancers, nID)
|
|
delete(s.loadBalancers, nID)
|
|
- }
|
|
|
|
-
|
|
|
|
- if len(s.loadBalancers) == 0 {
|
|
|
|
- // All loadbalancers for the service removed. Time to
|
|
|
|
- // remove the service itself.
|
|
|
|
- c.Lock()
|
|
|
|
-
|
|
|
|
- // Mark the object as deleted so that the add won't use it wrongly
|
|
|
|
- s.deleted = true
|
|
|
|
- delete(c.serviceBindings, skey)
|
|
|
|
- c.Unlock()
|
|
|
|
|
|
+ logrus.Debugf("rmServiceBinding %s delete %s, p:%p in loadbalancers len:%d", eID, nID, lb, len(s.loadBalancers))
|
|
}
|
|
}
|
|
|
|
|
|
ok, entries := s.removeIPToEndpoint(ip.String(), eID)
|
|
ok, entries := s.removeIPToEndpoint(ip.String(), eID)
|
|
@@ -348,7 +359,22 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
|
|
}
|
|
}
|
|
|
|
|
|
// Delete the name resolutions
|
|
// Delete the name resolutions
|
|
- c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding")
|
|
|
|
|
|
+ if deleteSvcRecords {
|
|
|
|
+ c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if len(s.loadBalancers) == 0 {
|
|
|
|
+ // All loadbalancers for the service removed. Time to
|
|
|
|
+ // remove the service itself.
|
|
|
|
+ c.Lock()
|
|
|
|
+
|
|
|
|
+ // Mark the object as deleted so that the add won't use it wrongly
|
|
|
|
+ s.deleted = true
|
|
|
|
+ // NOTE The delete from the serviceBindings map has to be the last operation else we are allowing a race between this service
|
|
|
|
+ // that is getting deleted and a new service that will be created if the entry is not anymore there
|
|
|
|
+ delete(c.serviceBindings, skey)
|
|
|
|
+ c.Unlock()
|
|
|
|
+ }
|
|
|
|
|
|
logrus.Debugf("rmServiceBinding from %s END for %s %s", method, svcName, eID)
|
|
logrus.Debugf("rmServiceBinding from %s END for %s %s", method, svcName, eID)
|
|
return nil
|
|
return nil
|