Commit b1475565 authored by Wojciech Tyczynski's avatar Wojciech Tyczynski

Edge-based iptables proxy

parent c5cbdbe3
...@@ -250,7 +250,7 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err ...@@ -250,7 +250,7 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
} }
proxier = proxierIPTables proxier = proxierIPTables
servicesHandler = proxierIPTables servicesHandler = proxierIPTables
endpointsHandler = proxierIPTables endpointsEventHandler = proxierIPTables
// No turning back. Remove artifacts that might still exist from the userspace Proxier. // No turning back. Remove artifacts that might still exist from the userspace Proxier.
glog.V(0).Info("Tearing down userspace rules.") glog.V(0).Info("Tearing down userspace rules.")
userspace.CleanupLeftovers(iptInterface) userspace.CleanupLeftovers(iptInterface)
......
...@@ -195,8 +195,8 @@ func newServiceInfo(serviceName proxy.ServicePortName, port *api.ServicePort, se ...@@ -195,8 +195,8 @@ func newServiceInfo(serviceName proxy.ServicePortName, port *api.ServicePort, se
return info return info
} }
type endpointsMap map[types.NamespacedName]*api.Endpoints
type proxyServiceMap map[proxy.ServicePortName]*serviceInfo type proxyServiceMap map[proxy.ServicePortName]*serviceInfo
type proxyEndpointMap map[proxy.ServicePortName][]*endpointsInfo type proxyEndpointMap map[proxy.ServicePortName][]*endpointsInfo
// Proxier is an iptables based proxy for connections between a localhost:lport // Proxier is an iptables based proxy for connections between a localhost:lport
...@@ -210,9 +210,14 @@ type Proxier struct { ...@@ -210,9 +210,14 @@ type Proxier struct {
// pointers are shared with higher layers of kube-proxy. They are guaranteed // pointers are shared with higher layers of kube-proxy. They are guaranteed
// to not be modified in the meantime, but also require to be not modified // to not be modified in the meantime, but also require to be not modified
// by Proxier. // by Proxier.
// nil until we have seen an On*Update event. allEndpoints endpointsMap
allServices []*api.Service // allServices is nil until we have seen an OnServiceUpdate event.
allEndpoints []*api.Endpoints allServices []*api.Service
// endpointsSynced is set to true when endpoints are synced after startup.
// This is used to avoid updating iptables with some partial data after
// kube-proxy restart.
endpointsSynced bool
throttle flowcontrol.RateLimiter throttle flowcontrol.RateLimiter
...@@ -327,6 +332,7 @@ func NewProxier(ipt utiliptables.Interface, ...@@ -327,6 +332,7 @@ func NewProxier(ipt utiliptables.Interface,
serviceMap: make(proxyServiceMap), serviceMap: make(proxyServiceMap),
endpointsMap: make(proxyEndpointMap), endpointsMap: make(proxyEndpointMap),
portsMap: make(map[localPort]closeable), portsMap: make(map[localPort]closeable),
allEndpoints: make(endpointsMap),
syncPeriod: syncPeriod, syncPeriod: syncPeriod,
minSyncPeriod: minSyncPeriod, minSyncPeriod: minSyncPeriod,
throttle: throttle, throttle: throttle,
...@@ -531,19 +537,42 @@ func (proxier *Proxier) OnServiceUpdate(allServices []*api.Service) { ...@@ -531,19 +537,42 @@ func (proxier *Proxier) OnServiceUpdate(allServices []*api.Service) {
proxier.syncProxyRules(syncReasonServices) proxier.syncProxyRules(syncReasonServices)
} }
// OnEndpointsUpdate takes in a slice of updated endpoints. func (proxier *Proxier) OnEndpointsAdd(endpoints *api.Endpoints) {
func (proxier *Proxier) OnEndpointsUpdate(allEndpoints []*api.Endpoints) { namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
proxier.mu.Lock() proxier.mu.Lock()
defer proxier.mu.Unlock() defer proxier.mu.Unlock()
if proxier.allEndpoints == nil { proxier.allEndpoints[namespacedName] = endpoints
glog.V(2).Info("Received first Endpoints update") proxier.syncProxyRules(syncReasonEndpoints)
} }
proxier.allEndpoints = allEndpoints
func (proxier *Proxier) OnEndpointsUpdate(_, endpoints *api.Endpoints) {
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
proxier.mu.Lock()
defer proxier.mu.Unlock()
proxier.allEndpoints[namespacedName] = endpoints
proxier.syncProxyRules(syncReasonEndpoints)
}
func (proxier *Proxier) OnEndpointsDelete(endpoints *api.Endpoints) {
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
proxier.mu.Lock()
defer proxier.mu.Unlock()
delete(proxier.allEndpoints, namespacedName)
proxier.syncProxyRules(syncReasonEndpoints)
}
func (proxier *Proxier) OnEndpointsSynced() {
proxier.mu.Lock()
defer proxier.mu.Unlock()
proxier.endpointsSynced = true
proxier.syncProxyRules(syncReasonEndpoints) proxier.syncProxyRules(syncReasonEndpoints)
} }
// Convert a slice of api.Endpoints objects into a map of service-port -> endpoints. // Convert a slice of api.Endpoints objects into a map of service-port -> endpoints.
func buildNewEndpointsMap(allEndpoints []*api.Endpoints, curMap proxyEndpointMap, hostname string) (newMap proxyEndpointMap, hcEndpoints map[types.NamespacedName]int, staleSet map[endpointServicePair]bool) { func buildNewEndpointsMap(allEndpoints endpointsMap, curMap proxyEndpointMap, hostname string) (newMap proxyEndpointMap, hcEndpoints map[types.NamespacedName]int, staleSet map[endpointServicePair]bool) {
// return values // return values
newMap = make(proxyEndpointMap) newMap = make(proxyEndpointMap)
...@@ -551,8 +580,8 @@ func buildNewEndpointsMap(allEndpoints []*api.Endpoints, curMap proxyEndpointMap ...@@ -551,8 +580,8 @@ func buildNewEndpointsMap(allEndpoints []*api.Endpoints, curMap proxyEndpointMap
staleSet = make(map[endpointServicePair]bool) staleSet = make(map[endpointServicePair]bool)
// Update endpoints for services. // Update endpoints for services.
for i := range allEndpoints { for _, endpoints := range allEndpoints {
accumulateEndpointsMap(allEndpoints[i], hostname, &newMap) accumulateEndpointsMap(endpoints, hostname, &newMap)
} }
// Check stale connections against endpoints missing from the update. // Check stale connections against endpoints missing from the update.
// TODO: we should really only mark a connection stale if the proto was UDP // TODO: we should really only mark a connection stale if the proto was UDP
...@@ -607,7 +636,6 @@ func buildNewEndpointsMap(allEndpoints []*api.Endpoints, curMap proxyEndpointMap ...@@ -607,7 +636,6 @@ func buildNewEndpointsMap(allEndpoints []*api.Endpoints, curMap proxyEndpointMap
// NOTE: endpoints object should NOT be modified. // NOTE: endpoints object should NOT be modified.
// //
// TODO: this could be simplified: // TODO: this could be simplified:
// - hostPortInfo and endpointsInfo overlap too much
// - the test for this is overlapped by the test for buildNewEndpointsMap // - the test for this is overlapped by the test for buildNewEndpointsMap
// - naming is poor and responsibilities are muddled // - naming is poor and responsibilities are muddled
func accumulateEndpointsMap(endpoints *api.Endpoints, hostname string, newEndpoints *proxyEndpointMap) { func accumulateEndpointsMap(endpoints *api.Endpoints, hostname string, newEndpoints *proxyEndpointMap) {
...@@ -732,7 +760,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) { ...@@ -732,7 +760,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
glog.V(4).Infof("syncProxyRules(%s) took %v", reason, time.Since(start)) glog.V(4).Infof("syncProxyRules(%s) took %v", reason, time.Since(start))
}() }()
// don't sync rules till we've received services and endpoints // don't sync rules till we've received services and endpoints
if proxier.allEndpoints == nil || proxier.allServices == nil { if !proxier.endpointsSynced || proxier.allServices == nil {
glog.V(2).Info("Not syncing iptables until Services and Endpoints have been received from master") glog.V(2).Info("Not syncing iptables until Services and Endpoints have been received from master")
return return
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment