Userspace proxy should remove conntrack entries
This changes the userspace proxy so that it cleans up its conntrack settings when a service is removed (as the iptables proxy already does). This could theoretically cause problems when a UDP service as deleted and recreated quickly (with the same IP address). As long as packets from the same UDP source IP and port were going to the same destination IP and port, the the conntrack would apply and the packets would be sent to the old destination. This is astronomically unlikely if you did not specify the IP address to use in the service, and even then, only happens with an "established" UDP connection. However, in cases where a service could be "switched" between using the iptables proxy and the userspace proxy, this case becomes much more frequent.
This commit is contained in:
committed by
Solly Ross
parent
655b338256
commit
5447db3048
@@ -33,6 +33,9 @@ import (
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilproxy "k8s.io/kubernetes/pkg/proxy/util"
|
||||
utilexec "k8s.io/kubernetes/pkg/util/exec"
|
||||
"k8s.io/kubernetes/pkg/util/iptables"
|
||||
)
|
||||
|
||||
@@ -106,6 +109,7 @@ type Proxier struct {
|
||||
hostIP net.IP
|
||||
proxyPorts PortAllocator
|
||||
makeProxySocket ProxySocketFunc
|
||||
exec utilexec.Interface
|
||||
}
|
||||
|
||||
// assert Proxier is a ProxyProvider
|
||||
@@ -150,15 +154,15 @@ func IsProxyLocked(err error) bool {
|
||||
// if iptables fails to update or acquire the initial lock. Once a proxier is
|
||||
// created, it will keep iptables up to date in the background and will not
|
||||
// terminate if a particular iptables call fails.
|
||||
func NewProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, pr utilnet.PortRange, syncPeriod, minSyncPeriod, udpIdleTimeout time.Duration) (*Proxier, error) {
|
||||
return NewCustomProxier(loadBalancer, listenIP, iptables, pr, syncPeriod, minSyncPeriod, udpIdleTimeout, newProxySocket)
|
||||
func NewProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, exec utilexec.Interface, pr utilnet.PortRange, syncPeriod, minSyncPeriod, udpIdleTimeout time.Duration) (*Proxier, error) {
|
||||
return NewCustomProxier(loadBalancer, listenIP, iptables, exec, pr, syncPeriod, minSyncPeriod, udpIdleTimeout, newProxySocket)
|
||||
}
|
||||
|
||||
// NewCustomProxier functions similarly to NewProxier, returing a new Proxier
|
||||
// for the given LoadBalancer and address. The new proxier is constructed using
|
||||
// the ProxySocket constructor provided, however, instead of constructing the
|
||||
// default ProxySockets.
|
||||
func NewCustomProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, pr utilnet.PortRange, syncPeriod, minSyncPeriod, udpIdleTimeout time.Duration, makeProxySocket ProxySocketFunc) (*Proxier, error) {
|
||||
func NewCustomProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, exec utilexec.Interface, pr utilnet.PortRange, syncPeriod, minSyncPeriod, udpIdleTimeout time.Duration, makeProxySocket ProxySocketFunc) (*Proxier, error) {
|
||||
if listenIP.Equal(localhostIPv4) || listenIP.Equal(localhostIPv6) {
|
||||
return nil, ErrProxyOnLocalhost
|
||||
}
|
||||
@@ -176,10 +180,10 @@ func NewCustomProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptab
|
||||
proxyPorts := newPortAllocator(pr)
|
||||
|
||||
glog.V(2).Infof("Setting proxy IP to %v and initializing iptables", hostIP)
|
||||
return createProxier(loadBalancer, listenIP, iptables, hostIP, proxyPorts, syncPeriod, minSyncPeriod, udpIdleTimeout, makeProxySocket)
|
||||
return createProxier(loadBalancer, listenIP, iptables, exec, hostIP, proxyPorts, syncPeriod, minSyncPeriod, udpIdleTimeout, makeProxySocket)
|
||||
}
|
||||
|
||||
func createProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, hostIP net.IP, proxyPorts PortAllocator, syncPeriod, minSyncPeriod, udpIdleTimeout time.Duration, makeProxySocket ProxySocketFunc) (*Proxier, error) {
|
||||
func createProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, exec utilexec.Interface, hostIP net.IP, proxyPorts PortAllocator, syncPeriod, minSyncPeriod, udpIdleTimeout time.Duration, makeProxySocket ProxySocketFunc) (*Proxier, error) {
|
||||
// convenient to pass nil for tests..
|
||||
if proxyPorts == nil {
|
||||
proxyPorts = newPortAllocator(utilnet.PortRange{})
|
||||
@@ -206,6 +210,7 @@ func createProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables
|
||||
hostIP: hostIP,
|
||||
proxyPorts: proxyPorts,
|
||||
makeProxySocket: makeProxySocket,
|
||||
exec: exec,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -469,11 +474,18 @@ func (proxier *Proxier) OnServiceUpdate(services []api.Service) {
|
||||
proxier.loadBalancer.NewService(serviceName, info.sessionAffinityType, info.stickyMaxAgeMinutes)
|
||||
}
|
||||
}
|
||||
|
||||
staleUDPServices := sets.NewString()
|
||||
proxier.mu.Lock()
|
||||
defer proxier.mu.Unlock()
|
||||
for name, info := range proxier.serviceMap {
|
||||
if !activeServices[name] {
|
||||
glog.V(1).Infof("Stopping service %q", name)
|
||||
|
||||
if proxier.serviceMap[name].protocol == api.ProtocolUDP {
|
||||
staleUDPServices.Insert(proxier.serviceMap[name].portal.ip.String())
|
||||
}
|
||||
|
||||
err := proxier.closePortal(name, info)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to close portal for %q: %v", name, err)
|
||||
@@ -485,6 +497,8 @@ func (proxier *Proxier) OnServiceUpdate(services []api.Service) {
|
||||
proxier.loadBalancer.DeleteService(name)
|
||||
}
|
||||
}
|
||||
|
||||
utilproxy.DeleteServiceConnections(proxier.exec, staleUDPServices.List())
|
||||
}
|
||||
|
||||
func sameConfig(info *ServiceInfo, service *api.Service, port *api.ServicePort) bool {
|
||||
|
||||
Reference in New Issue
Block a user