service_common.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // +build linux windows
  2. package libnetwork
  3. import (
  4. "net"
  5. "github.com/Sirupsen/logrus"
  6. )
  7. func newService(name string, id string, ingressPorts []*PortConfig, aliases []string) *service {
  8. return &service{
  9. name: name,
  10. id: id,
  11. ingressPorts: ingressPorts,
  12. loadBalancers: make(map[string]*loadBalancer),
  13. aliases: aliases,
  14. }
  15. }
  16. func (c *controller) getLBIndex(sid, nid string, ingressPorts []*PortConfig) int {
  17. skey := serviceKey{
  18. id: sid,
  19. ports: portConfigs(ingressPorts).String(),
  20. }
  21. c.Lock()
  22. s, ok := c.serviceBindings[skey]
  23. c.Unlock()
  24. if !ok {
  25. return 0
  26. }
  27. s.Lock()
  28. lb := s.loadBalancers[nid]
  29. s.Unlock()
  30. return int(lb.fwMark)
  31. }
  32. func (c *controller) cleanupServiceBindings(cleanupNID string) {
  33. var cleanupFuncs []func()
  34. c.Lock()
  35. services := make([]*service, 0, len(c.serviceBindings))
  36. for _, s := range c.serviceBindings {
  37. services = append(services, s)
  38. }
  39. c.Unlock()
  40. for _, s := range services {
  41. s.Lock()
  42. for nid, lb := range s.loadBalancers {
  43. if cleanupNID != "" && nid != cleanupNID {
  44. continue
  45. }
  46. for eid, ip := range lb.backEnds {
  47. service := s
  48. loadBalancer := lb
  49. networkID := nid
  50. epID := eid
  51. epIP := ip
  52. cleanupFuncs = append(cleanupFuncs, func() {
  53. if err := c.rmServiceBinding(service.name, service.id, networkID, epID, loadBalancer.vip,
  54. service.ingressPorts, service.aliases, epIP); err != nil {
  55. logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
  56. service.id, networkID, epID, err)
  57. }
  58. })
  59. }
  60. }
  61. s.Unlock()
  62. }
  63. for _, f := range cleanupFuncs {
  64. f()
  65. }
  66. }
  67. func (c *controller) addServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error {
  68. n, err := c.NetworkByID(nid)
  69. if err != nil {
  70. return err
  71. }
  72. skey := serviceKey{
  73. id: sid,
  74. ports: portConfigs(ingressPorts).String(),
  75. }
  76. c.Lock()
  77. s, ok := c.serviceBindings[skey]
  78. if !ok {
  79. // Create a new service if we are seeing this service
  80. // for the first time.
  81. s = newService(name, sid, ingressPorts, aliases)
  82. c.serviceBindings[skey] = s
  83. }
  84. c.Unlock()
  85. // Add endpoint IP to special "tasks.svc_name" so that the
  86. // applications have access to DNS RR.
  87. n.(*network).addSvcRecords("tasks."+name, ip, nil, false)
  88. for _, alias := range aliases {
  89. n.(*network).addSvcRecords("tasks."+alias, ip, nil, false)
  90. }
  91. // Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR
  92. svcIP := vip
  93. if len(svcIP) == 0 {
  94. svcIP = ip
  95. }
  96. n.(*network).addSvcRecords(name, svcIP, nil, false)
  97. for _, alias := range aliases {
  98. n.(*network).addSvcRecords(alias, svcIP, nil, false)
  99. }
  100. s.Lock()
  101. defer s.Unlock()
  102. lb, ok := s.loadBalancers[nid]
  103. if !ok {
  104. // Create a new load balancer if we are seeing this
  105. // network attachment on the service for the first
  106. // time.
  107. lb = &loadBalancer{
  108. vip: vip,
  109. fwMark: fwMarkCtr,
  110. backEnds: make(map[string]net.IP),
  111. service: s,
  112. }
  113. fwMarkCtrMu.Lock()
  114. fwMarkCtr++
  115. fwMarkCtrMu.Unlock()
  116. s.loadBalancers[nid] = lb
  117. }
  118. lb.backEnds[eid] = ip
  119. // Add loadbalancer service and backend in all sandboxes in
  120. // the network only if vip is valid.
  121. if len(vip) != 0 {
  122. n.(*network).addLBBackend(ip, vip, lb.fwMark, ingressPorts)
  123. }
  124. return nil
  125. }
  126. func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error {
  127. var rmService bool
  128. n, err := c.NetworkByID(nid)
  129. if err != nil {
  130. return err
  131. }
  132. skey := serviceKey{
  133. id: sid,
  134. ports: portConfigs(ingressPorts).String(),
  135. }
  136. c.Lock()
  137. s, ok := c.serviceBindings[skey]
  138. c.Unlock()
  139. if !ok {
  140. return nil
  141. }
  142. s.Lock()
  143. lb, ok := s.loadBalancers[nid]
  144. if !ok {
  145. s.Unlock()
  146. return nil
  147. }
  148. _, ok = lb.backEnds[eid]
  149. if !ok {
  150. s.Unlock()
  151. return nil
  152. }
  153. delete(lb.backEnds, eid)
  154. if len(lb.backEnds) == 0 {
  155. // All the backends for this service have been
  156. // removed. Time to remove the load balancer and also
  157. // remove the service entry in IPVS.
  158. rmService = true
  159. delete(s.loadBalancers, nid)
  160. }
  161. if len(s.loadBalancers) == 0 {
  162. // All loadbalancers for the service removed. Time to
  163. // remove the service itself.
  164. c.Lock()
  165. delete(c.serviceBindings, skey)
  166. c.Unlock()
  167. }
  168. // Remove loadbalancer service(if needed) and backend in all
  169. // sandboxes in the network only if the vip is valid.
  170. if len(vip) != 0 {
  171. n.(*network).rmLBBackend(ip, vip, lb.fwMark, ingressPorts, rmService)
  172. }
  173. s.Unlock()
  174. // Delete the special "tasks.svc_name" backend record.
  175. n.(*network).deleteSvcRecords("tasks."+name, ip, nil, false)
  176. for _, alias := range aliases {
  177. n.(*network).deleteSvcRecords("tasks."+alias, ip, nil, false)
  178. }
  179. // If we are doing DNS RR add the endpoint IP to DNS record
  180. // right away.
  181. if len(vip) == 0 {
  182. n.(*network).deleteSvcRecords(name, ip, nil, false)
  183. for _, alias := range aliases {
  184. n.(*network).deleteSvcRecords(alias, ip, nil, false)
  185. }
  186. }
  187. // Remove the DNS record for VIP only if we are removing the service
  188. if rmService && len(vip) != 0 {
  189. n.(*network).deleteSvcRecords(name, vip, nil, false)
  190. for _, alias := range aliases {
  191. n.(*network).deleteSvcRecords(alias, vip, nil, false)
  192. }
  193. }
  194. return nil
  195. }