@@ -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