mirror of
https://github.com/cloudnativelabs/kube-router.git
synced 2025-10-07 16:01:08 +02:00
Fix IPVS persistence flag (#160)
* Fix IPVS persistence flag * Improve service proxy logging * Fix Destination string * Enhanced ipvs ServiceFlags handling
This commit is contained in:
parent
3987ae14e4
commit
d433fa55ea
@ -234,7 +234,6 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
|
|||||||
activeServiceEndpointMap := make(map[string][]string)
|
activeServiceEndpointMap := make(map[string][]string)
|
||||||
|
|
||||||
for k, svc := range serviceInfoMap {
|
for k, svc := range serviceInfoMap {
|
||||||
|
|
||||||
var protocol uint16
|
var protocol uint16
|
||||||
if svc.protocol == "tcp" {
|
if svc.protocol == "tcp" {
|
||||||
protocol = syscall.IPPROTO_TCP
|
protocol = syscall.IPPROTO_TCP
|
||||||
@ -269,7 +268,7 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
|
|||||||
}
|
}
|
||||||
ipvsNodeportSvc, err = ipvsAddService(vip, protocol, uint16(svc.nodePort), svc.sessionAffinity)
|
ipvsNodeportSvc, err = ipvsAddService(vip, protocol, uint16(svc.nodePort), svc.sessionAffinity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to create ipvs service for node port")
|
glog.Errorf("Failed to create ipvs service for node port due to: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if nsc.nodeportBindOnAllIp {
|
if nsc.nodeportBindOnAllIp {
|
||||||
@ -326,10 +325,12 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
|
|||||||
key := generateIpPortId(ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)))
|
key := generateIpPortId(ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)))
|
||||||
endpoints, ok := activeServiceEndpointMap[key]
|
endpoints, ok := activeServiceEndpointMap[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
glog.Infof("Found a IPVS service %s:%s:%s which is no longer needed so cleaning up", ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)))
|
glog.Infof("Found a IPVS service %s which is no longer needed so cleaning up",
|
||||||
|
ipvsServiceString(ipvsSvc))
|
||||||
err := h.DelService(ipvsSvc)
|
err := h.DelService(ipvsSvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to delete stale IPVS service: %s", err.Error())
|
glog.Errorf("Failed to delete stale IPVS service %s due to:",
|
||||||
|
ipvsServiceString(ipvsSvc), err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -346,11 +347,12 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !validEp {
|
if !validEp {
|
||||||
glog.Infof("Found a IPVS service %s:%s:%s, destination %s which is no longer needed so cleaning up",
|
glog.Infof("Found a destination %s in service %s which is no longer needed so cleaning up",
|
||||||
ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)), dst.Address.String())
|
ipvsDestinationString(dst), ipvsServiceString(ipvsSvc))
|
||||||
err := h.DelDestination(ipvsSvc, dst)
|
err := h.DelDestination(ipvsSvc, dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to delete server from ipvs service")
|
glog.Errorf("Failed to delete destination %s from ipvs service %s",
|
||||||
|
ipvsDestinationString(dst), ipvsServiceString(ipvsSvc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -707,19 +709,76 @@ func deleteMasqueradeIptablesRule() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ipvsServiceString(s *ipvs.Service) string {
|
||||||
|
var flags, protocol string
|
||||||
|
|
||||||
|
switch s.Protocol {
|
||||||
|
case syscall.IPPROTO_TCP:
|
||||||
|
protocol = "TCP"
|
||||||
|
case syscall.IPPROTO_UDP:
|
||||||
|
protocol = "UDP"
|
||||||
|
default:
|
||||||
|
protocol = "UNKNOWN"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Flags&0x0001 != 0 {
|
||||||
|
flags = flags + "[persistent port]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Flags&0x0002 != 0 {
|
||||||
|
flags = flags + "[hashed entry]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Flags&0x0004 != 0 {
|
||||||
|
flags = flags + "[one-packet scheduling]"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s:%s:%v (Flags: %s)", protocol, s.Address, s.Port, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipvsDestinationString(d *ipvs.Destination) string {
|
||||||
|
return fmt.Sprintf("%s:%v (Weight: %v)", d.Address, d.Port, d.Weight)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipvsSetPersistence(svc *ipvs.Service, p bool) {
|
||||||
|
if p {
|
||||||
|
svc.Flags |= 0x0001
|
||||||
|
svc.Netmask |= 0xFFFFFFFF
|
||||||
|
// TODO: once service manifest supports timeout time remove hardcoding
|
||||||
|
svc.Timeout = 180 * 60
|
||||||
|
} else {
|
||||||
|
svc.Flags &^= 0x0001
|
||||||
|
svc.Netmask &^= 0xFFFFFFFF
|
||||||
|
svc.Timeout = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ipvsAddService(vip net.IP, protocol, port uint16, persistent bool) (*ipvs.Service, error) {
|
func ipvsAddService(vip net.IP, protocol, port uint16, persistent bool) (*ipvs.Service, error) {
|
||||||
svcs, err := h.GetServices()
|
svcs, err := h.GetServices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, svc := range svcs {
|
for _, svc := range svcs {
|
||||||
if strings.Compare(vip.String(), svc.Address.String()) == 0 &&
|
if vip.Equal(svc.Address) && protocol == svc.Protocol && port == svc.Port {
|
||||||
protocol == svc.Protocol && port == svc.Port {
|
if (persistent && (svc.Flags&0x0001) == 0) || (!persistent && (svc.Flags&0x0001) != 0) {
|
||||||
glog.Infof("ipvs service %s:%s:%s already exists so returning", vip.String(),
|
ipvsSetPersistence(svc, persistent)
|
||||||
protocol, strconv.Itoa(int(port)))
|
|
||||||
|
err = h.UpdateService(svc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
glog.Infof("Updated persistence/session-affinity for service: %s", ipvsServiceString(svc))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make this debug output when we get log levels
|
||||||
|
// glog.Fatal("ipvs service %s:%s:%s already exists so returning", vip.String(),
|
||||||
|
// protocol, strconv.Itoa(int(port)))
|
||||||
|
|
||||||
return svc, nil
|
return svc, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svc := ipvs.Service{
|
svc := ipvs.Service{
|
||||||
Address: vip,
|
Address: vip,
|
||||||
AddressFamily: syscall.AF_INET,
|
AddressFamily: syscall.AF_INET,
|
||||||
@ -728,17 +787,13 @@ func ipvsAddService(vip net.IP, protocol, port uint16, persistent bool) (*ipvs.S
|
|||||||
SchedName: ipvs.RoundRobin,
|
SchedName: ipvs.RoundRobin,
|
||||||
}
|
}
|
||||||
|
|
||||||
if persistent {
|
ipvsSetPersistence(&svc, persistent)
|
||||||
// set bit to enable service persistence
|
|
||||||
svc.Flags |= (1 << 24)
|
err = h.NewService(&svc)
|
||||||
svc.Netmask |= 0xFFFFFFFF
|
if err != nil {
|
||||||
// TODO: once service manifest supports timeout time remove hardcoding
|
return nil, err
|
||||||
svc.Timeout = 180 * 60
|
|
||||||
}
|
}
|
||||||
if err := h.NewService(&svc); err != nil {
|
glog.Infof("Successfully added service: %s", ipvsServiceString(&svc))
|
||||||
return nil, fmt.Errorf("Failed to create service: %s:%s:%s", vip.String(), strconv.Itoa(int(protocol)), strconv.Itoa(int(port)))
|
|
||||||
}
|
|
||||||
glog.Infof("Successfully added service: %s:%s:%s", vip.String(), protocol, strconv.Itoa(int(port)))
|
|
||||||
return &svc, nil
|
return &svc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,17 +801,18 @@ func ipvsAddServer(service *ipvs.Service, dest *ipvs.Destination) error {
|
|||||||
|
|
||||||
err := h.NewDestination(service, dest)
|
err := h.NewDestination(service, dest)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
glog.Infof("Successfully added destination %s:%s to the service %s:%s:%s", dest.Address,
|
glog.Infof("Successfully added destination %s to the service %s",
|
||||||
strconv.Itoa(int(dest.Port)), service.Address, service.Protocol, strconv.Itoa(int(service.Port)))
|
ipvsDestinationString(dest), ipvsServiceString(service))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(err.Error(), IPVS_SERVER_EXISTS) {
|
if strings.Contains(err.Error(), IPVS_SERVER_EXISTS) {
|
||||||
glog.Infof("ipvs destination %s:%s already exists in the ipvs service %s:%s:%s so not adding destination", dest.Address,
|
// TODO: Make this debug output when we get log levels
|
||||||
strconv.Itoa(int(dest.Port)), service.Address, strconv.Itoa(int(service.Protocol)), strconv.Itoa(int(service.Port)))
|
// glog.Infof("ipvs destination %s already exists in the ipvs service %s so not adding destination",
|
||||||
|
// ipvsDestinationString(dest), ipvsServiceString(service))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("Failed to add ipvs destination %s:%s to the ipvs service %s:%s:%s due to : %s", dest.Address,
|
return fmt.Errorf("Failed to add ipvs destination %s to the ipvs service %s due to : %s", dest.Address,
|
||||||
strconv.Itoa(int(dest.Port)), service.Address, strconv.Itoa(int(service.Protocol)), strconv.Itoa(int(service.Port)), err.Error())
|
ipvsDestinationString(dest), ipvsServiceString(service), err.Error())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user