Skip to content

Commit ba7697b

Browse files
authored
Support for Services with externalIPs (#201)
Fixes #26
1 parent 84741b6 commit ba7697b

File tree

1 file changed

+46
-9
lines changed

1 file changed

+46
-9
lines changed

app/controllers/network_services_controller.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ type serviceInfo struct {
9090
nodePort int
9191
sessionAffinity bool
9292
hairpin bool
93+
externalIPs []string
9394
}
9495

9596
// map of all services, with unique service id(namespace name, service name, port) as key
@@ -245,10 +246,20 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
245246
vip := &netlink.Addr{IPNet: &net.IPNet{IP: svc.clusterIP, Mask: net.IPv4Mask(255, 255, 255, 255)}, Scope: syscall.RT_SCOPE_LINK}
246247
err := netlink.AddrAdd(dummyVipInterface, vip)
247248
if err != nil && err.Error() != IFACE_HAS_ADDR {
248-
glog.Errorf("Failed to assign cluster ip to dummy interface %s", err)
249+
glog.Errorf("Failed to assign cluster ip %s to dummy interface %s", svc.clusterIP.String(), err.Error())
249250
continue
250251
}
251252

253+
// assign external IP's of the service to the dummy interface
254+
for _, externalIP := range svc.externalIPs {
255+
vip := &netlink.Addr{IPNet: &net.IPNet{IP: net.ParseIP(externalIP), Mask: net.IPv4Mask(255, 255, 255, 255)}, Scope: syscall.RT_SCOPE_LINK}
256+
err := netlink.AddrAdd(dummyVipInterface, vip)
257+
if err != nil && err.Error() != IFACE_HAS_ADDR {
258+
glog.Errorf("Failed to assign external ip: %s to dummy interface %s", externalIP, err.Error())
259+
continue
260+
}
261+
}
262+
252263
// create IPVS service for the service to be exposed through the cluster ip
253264
ipvsClusterVipSvc, err := ipvsAddService(svc.clusterIP, protocol, uint16(svc.port), svc.sessionAffinity)
254265
if err != nil {
@@ -279,8 +290,26 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
279290
activeServiceEndpointMap[nodeServiceId] = make([]string, 0)
280291
}
281292

282-
// add IPVS remote server to the IPVS service
283293
endpoints := endpointsInfoMap[k]
294+
295+
ipvsExternalIpServices := make([]*ipvs.Service, 0)
296+
// create IPVS service for the service to be exposed through the
297+
for _, externalIP := range svc.externalIPs {
298+
ipvsExternalIPSvc, err := ipvsAddService(net.ParseIP(externalIP), protocol, uint16(svc.port), svc.sessionAffinity)
299+
if err != nil {
300+
glog.Errorf("Failed to create ipvs service for External IP due to: %s", err.Error())
301+
continue
302+
}
303+
ipvsExternalIpServices = append(ipvsExternalIpServices, ipvsExternalIPSvc)
304+
externalIpServiceId := generateIpPortId(externalIP, svc.protocol, strconv.Itoa(svc.port))
305+
activeServiceEndpointMap[externalIpServiceId] = make([]string, 0)
306+
for _, endpoint := range endpoints {
307+
activeServiceEndpointMap[externalIpServiceId] =
308+
append(activeServiceEndpointMap[externalIpServiceId], endpoint.ip)
309+
}
310+
}
311+
312+
// add IPVS remote server to the IPVS service
284313
for _, endpoint := range endpoints {
285314
dst := ipvs.Destination{
286315
Address: net.ParseIP(endpoint.ip),
@@ -306,6 +335,13 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
306335
activeServiceEndpointMap[nodeServiceId] =
307336
append(activeServiceEndpointMap[clusterServiceId], endpoint.ip)
308337
}
338+
339+
for _, ipvsExternalIpService := range ipvsExternalIpServices {
340+
err := ipvsAddServer(ipvsExternalIpService, &dst)
341+
if err != nil {
342+
glog.Errorf(err.Error())
343+
}
344+
}
309345
}
310346
}
311347

@@ -417,14 +453,15 @@ func buildServicesInfo() serviceInfoMap {
417453

418454
for _, port := range svc.Spec.Ports {
419455
svcInfo := serviceInfo{
420-
clusterIP: net.ParseIP(svc.Spec.ClusterIP),
421-
port: int(port.Port),
422-
protocol: strings.ToLower(string(port.Protocol)),
423-
nodePort: int(port.NodePort),
424-
name: svc.ObjectMeta.Name,
425-
namespace: svc.ObjectMeta.Namespace,
456+
clusterIP: net.ParseIP(svc.Spec.ClusterIP),
457+
port: int(port.Port),
458+
protocol: strings.ToLower(string(port.Protocol)),
459+
nodePort: int(port.NodePort),
460+
name: svc.ObjectMeta.Name,
461+
namespace: svc.ObjectMeta.Namespace,
462+
externalIPs: make([]string, len(svc.Spec.ExternalIPs)),
426463
}
427-
464+
copy(svcInfo.externalIPs, svc.Spec.ExternalIPs)
428465
svcInfo.sessionAffinity = (svc.Spec.SessionAffinity == "ClientIP")
429466
_, svcInfo.hairpin = svc.ObjectMeta.Annotations["kube-router.io/service.hairpin"]
430467

0 commit comments

Comments
 (0)