Reuse buffers for generated iptables rules

This commit is contained in:
Wojciech Tyczynski 2017-05-18 12:25:10 +02:00
parent 4d29c8608f
commit e3bb755270
2 changed files with 80 additions and 63 deletions

View File

@ -306,6 +306,10 @@ type Proxier struct {
// The following buffers are used to reuse memory and avoid allocations // The following buffers are used to reuse memory and avoid allocations
// that are significantly impacting performance. // that are significantly impacting performance.
iptablesLines *bytes.Buffer iptablesLines *bytes.Buffer
filterChains *bytes.Buffer
filterRules *bytes.Buffer
natChains *bytes.Buffer
natRules *bytes.Buffer
} }
type localPort struct { type localPort struct {
@ -422,6 +426,10 @@ func NewProxier(ipt utiliptables.Interface,
healthChecker: healthChecker, healthChecker: healthChecker,
healthzServer: healthzServer, healthzServer: healthzServer,
iptablesLines: bytes.NewBuffer(nil), iptablesLines: bytes.NewBuffer(nil),
filterChains: bytes.NewBuffer(nil),
filterRules: bytes.NewBuffer(nil),
natChains: bytes.NewBuffer(nil),
natRules: bytes.NewBuffer(nil),
}, nil }, nil
} }
@ -998,47 +1006,48 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
existingNATChains = utiliptables.GetChainLines(utiliptables.TableNAT, proxier.iptablesLines.Bytes()) existingNATChains = utiliptables.GetChainLines(utiliptables.TableNAT, proxier.iptablesLines.Bytes())
} }
filterChains := bytes.NewBuffer(nil) // Reset all buffers used later.
filterRules := bytes.NewBuffer(nil) proxier.filterChains.Reset()
natChains := bytes.NewBuffer(nil) proxier.filterRules.Reset()
natRules := bytes.NewBuffer(nil) proxier.natChains.Reset()
proxier.natRules.Reset()
// Write table headers. // Write table headers.
writeLine(filterChains, "*filter") writeLine(proxier.filterChains, "*filter")
writeLine(natChains, "*nat") writeLine(proxier.natChains, "*nat")
// Make sure we keep stats for the top-level chains, if they existed // Make sure we keep stats for the top-level chains, if they existed
// (which most should have because we created them above). // (which most should have because we created them above).
if chain, ok := existingFilterChains[kubeServicesChain]; ok { if chain, ok := existingFilterChains[kubeServicesChain]; ok {
writeLine(filterChains, chain) writeLine(proxier.filterChains, chain)
} else { } else {
writeLine(filterChains, utiliptables.MakeChainLine(kubeServicesChain)) writeLine(proxier.filterChains, utiliptables.MakeChainLine(kubeServicesChain))
} }
if chain, ok := existingNATChains[kubeServicesChain]; ok { if chain, ok := existingNATChains[kubeServicesChain]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(kubeServicesChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(kubeServicesChain))
} }
if chain, ok := existingNATChains[kubeNodePortsChain]; ok { if chain, ok := existingNATChains[kubeNodePortsChain]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(kubeNodePortsChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(kubeNodePortsChain))
} }
if chain, ok := existingNATChains[kubePostroutingChain]; ok { if chain, ok := existingNATChains[kubePostroutingChain]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(kubePostroutingChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(kubePostroutingChain))
} }
if chain, ok := existingNATChains[KubeMarkMasqChain]; ok { if chain, ok := existingNATChains[KubeMarkMasqChain]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(KubeMarkMasqChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(KubeMarkMasqChain))
} }
// Install the kubernetes-specific postrouting rules. We use a whole chain for // Install the kubernetes-specific postrouting rules. We use a whole chain for
// this so that it is easier to flush and change, for example if the mark // this so that it is easier to flush and change, for example if the mark
// value should ever change. // value should ever change.
writeLine(natRules, []string{ writeLine(proxier.natRules, []string{
"-A", string(kubePostroutingChain), "-A", string(kubePostroutingChain),
"-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`, "-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`,
"-m", "mark", "--mark", proxier.masqueradeMark, "-m", "mark", "--mark", proxier.masqueradeMark,
@ -1048,7 +1057,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// Install the kubernetes-specific masquerade mark rule. We use a whole chain for // Install the kubernetes-specific masquerade mark rule. We use a whole chain for
// this so that it is easier to flush and change, for example if the mark // this so that it is easier to flush and change, for example if the mark
// value should ever change. // value should ever change.
writeLine(natRules, []string{ writeLine(proxier.natRules, []string{
"-A", string(KubeMarkMasqChain), "-A", string(KubeMarkMasqChain),
"-j", "MARK", "--set-xmark", proxier.masqueradeMark, "-j", "MARK", "--set-xmark", proxier.masqueradeMark,
}...) }...)
@ -1069,9 +1078,9 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// Create the per-service chain, retaining counters if possible. // Create the per-service chain, retaining counters if possible.
svcChain := servicePortChainName(svcNameString, protocol) svcChain := servicePortChainName(svcNameString, protocol)
if chain, ok := existingNATChains[svcChain]; ok { if chain, ok := existingNATChains[svcChain]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(svcChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(svcChain))
} }
activeNATChains[svcChain] = true activeNATChains[svcChain] = true
@ -1080,9 +1089,9 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// Only for services request OnlyLocal traffic // Only for services request OnlyLocal traffic
// create the per-service LB chain, retaining counters if possible. // create the per-service LB chain, retaining counters if possible.
if lbChain, ok := existingNATChains[svcXlbChain]; ok { if lbChain, ok := existingNATChains[svcXlbChain]; ok {
writeLine(natChains, lbChain) writeLine(proxier.natChains, lbChain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(svcXlbChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(svcXlbChain))
} }
activeNATChains[svcXlbChain] = true activeNATChains[svcXlbChain] = true
} else if activeNATChains[svcXlbChain] { } else if activeNATChains[svcXlbChain] {
@ -1099,12 +1108,12 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
"--dport", fmt.Sprintf("%d", svcInfo.port), "--dport", fmt.Sprintf("%d", svcInfo.port),
} }
if proxier.masqueradeAll { if proxier.masqueradeAll {
writeLine(natRules, append(args, "-j", string(KubeMarkMasqChain))...) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
} }
if len(proxier.clusterCIDR) > 0 { if len(proxier.clusterCIDR) > 0 {
writeLine(natRules, append(args, "! -s", proxier.clusterCIDR, "-j", string(KubeMarkMasqChain))...) writeLine(proxier.natRules, append(args, "! -s", proxier.clusterCIDR, "-j", string(KubeMarkMasqChain))...)
} }
writeLine(natRules, append(args, "-j", string(svcChain))...) writeLine(proxier.natRules, append(args, "-j", string(svcChain))...)
// Capture externalIPs. // Capture externalIPs.
for _, externalIP := range svcInfo.externalIPs { for _, externalIP := range svcInfo.externalIPs {
@ -1149,7 +1158,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
"--dport", fmt.Sprintf("%d", svcInfo.port), "--dport", fmt.Sprintf("%d", svcInfo.port),
} }
// We have to SNAT packets to external IPs. // We have to SNAT packets to external IPs.
writeLine(natRules, append(args, "-j", string(KubeMarkMasqChain))...) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
// Allow traffic for external IPs that does not come from a bridge (i.e. not from a container) // Allow traffic for external IPs that does not come from a bridge (i.e. not from a container)
// nor from a local process to be forwarded to the service. // nor from a local process to be forwarded to the service.
@ -1158,16 +1167,16 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
externalTrafficOnlyArgs := append(args, externalTrafficOnlyArgs := append(args,
"-m", "physdev", "!", "--physdev-is-in", "-m", "physdev", "!", "--physdev-is-in",
"-m", "addrtype", "!", "--src-type", "LOCAL") "-m", "addrtype", "!", "--src-type", "LOCAL")
writeLine(natRules, append(externalTrafficOnlyArgs, "-j", string(svcChain))...) writeLine(proxier.natRules, append(externalTrafficOnlyArgs, "-j", string(svcChain))...)
dstLocalOnlyArgs := append(args, "-m", "addrtype", "--dst-type", "LOCAL") dstLocalOnlyArgs := append(args, "-m", "addrtype", "--dst-type", "LOCAL")
// Allow traffic bound for external IPs that happen to be recognized as local IPs to stay local. // Allow traffic bound for external IPs that happen to be recognized as local IPs to stay local.
// This covers cases like GCE load-balancers which get added to the local routing table. // This covers cases like GCE load-balancers which get added to the local routing table.
writeLine(natRules, append(dstLocalOnlyArgs, "-j", string(svcChain))...) writeLine(proxier.natRules, append(dstLocalOnlyArgs, "-j", string(svcChain))...)
// If the service has no endpoints then reject packets coming via externalIP // If the service has no endpoints then reject packets coming via externalIP
// Install ICMP Reject rule in filter table for destination=externalIP and dport=svcport // Install ICMP Reject rule in filter table for destination=externalIP and dport=svcport
if len(proxier.endpointsMap[svcName]) == 0 { if len(proxier.endpointsMap[svcName]) == 0 {
writeLine(filterRules, writeLine(proxier.filterRules,
"-A", string(kubeServicesChain), "-A", string(kubeServicesChain),
"-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString), "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
"-m", protocol, "-p", protocol, "-m", protocol, "-p", protocol,
@ -1184,9 +1193,9 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// create service firewall chain // create service firewall chain
fwChain := serviceFirewallChainName(svcNameString, protocol) fwChain := serviceFirewallChainName(svcNameString, protocol)
if chain, ok := existingNATChains[fwChain]; ok { if chain, ok := existingNATChains[fwChain]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(fwChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(fwChain))
} }
activeNATChains[fwChain] = true activeNATChains[fwChain] = true
// The service firewall rules are created based on ServiceSpec.loadBalancerSourceRanges field. // The service firewall rules are created based on ServiceSpec.loadBalancerSourceRanges field.
@ -1201,7 +1210,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
"--dport", fmt.Sprintf("%d", svcInfo.port), "--dport", fmt.Sprintf("%d", svcInfo.port),
} }
// jump to service firewall chain // jump to service firewall chain
writeLine(natRules, append(args, "-j", string(fwChain))...) writeLine(proxier.natRules, append(args, "-j", string(fwChain))...)
args = []string{ args = []string{
"-A", string(fwChain), "-A", string(fwChain),
@ -1213,18 +1222,18 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// If we are proxying globally, we need to masquerade in case we cross nodes. // If we are proxying globally, we need to masquerade in case we cross nodes.
// If we are proxying only locally, we can retain the source IP. // If we are proxying only locally, we can retain the source IP.
if !svcInfo.onlyNodeLocalEndpoints { if !svcInfo.onlyNodeLocalEndpoints {
writeLine(natRules, append(args, "-j", string(KubeMarkMasqChain))...) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
chosenChain = svcChain chosenChain = svcChain
} }
if len(svcInfo.loadBalancerSourceRanges) == 0 { if len(svcInfo.loadBalancerSourceRanges) == 0 {
// allow all sources, so jump directly to the KUBE-SVC or KUBE-XLB chain // allow all sources, so jump directly to the KUBE-SVC or KUBE-XLB chain
writeLine(natRules, append(args, "-j", string(chosenChain))...) writeLine(proxier.natRules, append(args, "-j", string(chosenChain))...)
} else { } else {
// firewall filter based on each source range // firewall filter based on each source range
allowFromNode := false allowFromNode := false
for _, src := range svcInfo.loadBalancerSourceRanges { for _, src := range svcInfo.loadBalancerSourceRanges {
writeLine(natRules, append(args, "-s", src, "-j", string(chosenChain))...) writeLine(proxier.natRules, append(args, "-s", src, "-j", string(chosenChain))...)
// ignore error because it has been validated // ignore error because it has been validated
_, cidr, _ := net.ParseCIDR(src) _, cidr, _ := net.ParseCIDR(src)
if cidr.Contains(proxier.nodeIP) { if cidr.Contains(proxier.nodeIP) {
@ -1235,13 +1244,13 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// loadbalancer's backend hosts. In this case, request will not hit the loadbalancer but loop back directly. // loadbalancer's backend hosts. In this case, request will not hit the loadbalancer but loop back directly.
// Need to add the following rule to allow request on host. // Need to add the following rule to allow request on host.
if allowFromNode { if allowFromNode {
writeLine(natRules, append(args, "-s", fmt.Sprintf("%s/32", ingress.IP), "-j", string(chosenChain))...) writeLine(proxier.natRules, append(args, "-s", fmt.Sprintf("%s/32", ingress.IP), "-j", string(chosenChain))...)
} }
} }
// If the packet was able to reach the end of firewall chain, then it did not get DNATed. // If the packet was able to reach the end of firewall chain, then it did not get DNATed.
// It means the packet cannot go thru the firewall, then mark it for DROP // It means the packet cannot go thru the firewall, then mark it for DROP
writeLine(natRules, append(args, "-j", string(KubeMarkDropChain))...) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkDropChain))...)
} }
} }
@ -1280,13 +1289,13 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
} }
if !svcInfo.onlyNodeLocalEndpoints { if !svcInfo.onlyNodeLocalEndpoints {
// Nodeports need SNAT, unless they're local. // Nodeports need SNAT, unless they're local.
writeLine(natRules, append(args, "-j", string(KubeMarkMasqChain))...) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
// Jump to the service chain. // Jump to the service chain.
writeLine(natRules, append(args, "-j", string(svcChain))...) writeLine(proxier.natRules, append(args, "-j", string(svcChain))...)
} else { } else {
// TODO: Make all nodePorts jump to the firewall chain. // TODO: Make all nodePorts jump to the firewall chain.
// Currently we only create it for loadbalancers (#33586). // Currently we only create it for loadbalancers (#33586).
writeLine(natRules, append(args, "-j", string(svcXlbChain))...) writeLine(proxier.natRules, append(args, "-j", string(svcXlbChain))...)
} }
// If the service has no endpoints then reject packets. The filter // If the service has no endpoints then reject packets. The filter
@ -1294,7 +1303,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// the nat table does, so we just stick this into the kube-services // the nat table does, so we just stick this into the kube-services
// chain. // chain.
if len(proxier.endpointsMap[svcName]) == 0 { if len(proxier.endpointsMap[svcName]) == 0 {
writeLine(filterRules, writeLine(proxier.filterRules,
"-A", string(kubeServicesChain), "-A", string(kubeServicesChain),
"-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString), "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
"-m", "addrtype", "--dst-type", "LOCAL", "-m", "addrtype", "--dst-type", "LOCAL",
@ -1307,7 +1316,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// If the service has no endpoints then reject packets. // If the service has no endpoints then reject packets.
if len(proxier.endpointsMap[svcName]) == 0 { if len(proxier.endpointsMap[svcName]) == 0 {
writeLine(filterRules, writeLine(proxier.filterRules,
"-A", string(kubeServicesChain), "-A", string(kubeServicesChain),
"-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString), "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString),
"-m", protocol, "-p", protocol, "-m", protocol, "-p", protocol,
@ -1332,9 +1341,9 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// Create the endpoint chain, retaining counters if possible. // Create the endpoint chain, retaining counters if possible.
if chain, ok := existingNATChains[utiliptables.Chain(endpointChain)]; ok { if chain, ok := existingNATChains[utiliptables.Chain(endpointChain)]; ok {
writeLine(natChains, chain) writeLine(proxier.natChains, chain)
} else { } else {
writeLine(natChains, utiliptables.MakeChainLine(endpointChain)) writeLine(proxier.natChains, utiliptables.MakeChainLine(endpointChain))
} }
activeNATChains[endpointChain] = true activeNATChains[endpointChain] = true
} }
@ -1342,7 +1351,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// First write session affinity rules, if applicable. // First write session affinity rules, if applicable.
if svcInfo.sessionAffinityType == api.ServiceAffinityClientIP { if svcInfo.sessionAffinityType == api.ServiceAffinityClientIP {
for _, endpointChain := range endpointChains { for _, endpointChain := range endpointChains {
writeLine(natRules, writeLine(proxier.natRules,
"-A", string(svcChain), "-A", string(svcChain),
"-m", "comment", "--comment", svcNameString, "-m", "comment", "--comment", svcNameString,
"-m", "recent", "--name", string(endpointChain), "-m", "recent", "--name", string(endpointChain),
@ -1368,7 +1377,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
} }
// The final (or only if n == 1) rule is a guaranteed match. // The final (or only if n == 1) rule is a guaranteed match.
args = append(args, "-j", string(endpointChain)) args = append(args, "-j", string(endpointChain))
writeLine(natRules, args...) writeLine(proxier.natRules, args...)
// Rules in the per-endpoint chain. // Rules in the per-endpoint chain.
args = []string{ args = []string{
@ -1376,7 +1385,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
"-m", "comment", "--comment", svcNameString, "-m", "comment", "--comment", svcNameString,
} }
// Handle traffic that loops back to the originator with SNAT. // Handle traffic that loops back to the originator with SNAT.
writeLine(natRules, append(args, writeLine(proxier.natRules, append(args,
"-s", fmt.Sprintf("%s/32", strings.Split(endpoints[i].endpoint, ":")[0]), "-s", fmt.Sprintf("%s/32", strings.Split(endpoints[i].endpoint, ":")[0]),
"-j", string(KubeMarkMasqChain))...) "-j", string(KubeMarkMasqChain))...)
// Update client-affinity lists. // Update client-affinity lists.
@ -1385,7 +1394,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
} }
// DNAT to final destination. // DNAT to final destination.
args = append(args, "-m", protocol, "-p", protocol, "-j", "DNAT", "--to-destination", endpoints[i].endpoint) args = append(args, "-m", protocol, "-p", protocol, "-j", "DNAT", "--to-destination", endpoints[i].endpoint)
writeLine(natRules, args...) writeLine(proxier.natRules, args...)
} }
// The logic below this applies only if this service is marked as OnlyLocal // The logic below this applies only if this service is marked as OnlyLocal
@ -1415,7 +1424,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
"-s", proxier.clusterCIDR, "-s", proxier.clusterCIDR,
"-j", string(svcChain), "-j", string(svcChain),
} }
writeLine(natRules, args...) writeLine(proxier.natRules, args...)
} }
numLocalEndpoints := len(localEndpointChains) numLocalEndpoints := len(localEndpointChains)
@ -1428,7 +1437,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
"-j", "-j",
string(KubeMarkDropChain), string(KubeMarkDropChain),
} }
writeLine(natRules, args...) writeLine(proxier.natRules, args...)
} else { } else {
// Setup probability filter rules only over local endpoints // Setup probability filter rules only over local endpoints
for i, endpointChain := range localEndpointChains { for i, endpointChain := range localEndpointChains {
@ -1447,7 +1456,7 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
} }
// The final (or only if n == 1) rule is a guaranteed match. // The final (or only if n == 1) rule is a guaranteed match.
args = append(args, "-j", string(endpointChain)) args = append(args, "-j", string(endpointChain))
writeLine(natRules, args...) writeLine(proxier.natRules, args...)
} }
} }
} }
@ -1463,33 +1472,37 @@ func (proxier *Proxier) syncProxyRules(reason syncReason) {
// We must (as per iptables) write a chain-line for it, which has // We must (as per iptables) write a chain-line for it, which has
// the nice effect of flushing the chain. Then we can remove the // the nice effect of flushing the chain. Then we can remove the
// chain. // chain.
writeLine(natChains, existingNATChains[chain]) writeLine(proxier.natChains, existingNATChains[chain])
writeLine(natRules, "-X", chainString) writeLine(proxier.natRules, "-X", chainString)
} }
} }
// Finally, tail-call to the nodeports chain. This needs to be after all // Finally, tail-call to the nodeports chain. This needs to be after all
// other service portal rules. // other service portal rules.
writeLine(natRules, writeLine(proxier.natRules,
"-A", string(kubeServicesChain), "-A", string(kubeServicesChain),
"-m", "comment", "--comment", `"kubernetes service nodeports; NOTE: this must be the last rule in this chain"`, "-m", "comment", "--comment", `"kubernetes service nodeports; NOTE: this must be the last rule in this chain"`,
"-m", "addrtype", "--dst-type", "LOCAL", "-m", "addrtype", "--dst-type", "LOCAL",
"-j", string(kubeNodePortsChain)) "-j", string(kubeNodePortsChain))
// Write the end-of-table markers. // Write the end-of-table markers.
writeLine(filterRules, "COMMIT") writeLine(proxier.filterRules, "COMMIT")
writeLine(natRules, "COMMIT") writeLine(proxier.natRules, "COMMIT")
// Sync rules. // Sync rules.
// NOTE: NoFlushTables is used so we don't flush non-kubernetes chains in the table. // NOTE: NoFlushTables is used so we don't flush non-kubernetes chains in the table
filterLines := append(filterChains.Bytes(), filterRules.Bytes()...) proxier.iptablesLines.Reset()
natLines := append(natChains.Bytes(), natRules.Bytes()...) proxier.iptablesLines.Write(proxier.filterChains.Bytes())
lines := append(filterLines, natLines...) proxier.iptablesLines.Write(proxier.filterRules.Bytes())
proxier.iptablesLines.Write(proxier.natChains.Bytes())
proxier.iptablesLines.Write(proxier.natRules.Bytes())
glog.V(3).Infof("Restoring iptables rules: %s", lines) if glog.V(4) {
err = proxier.iptables.RestoreAll(lines, utiliptables.NoFlushTables, utiliptables.RestoreCounters) glog.V(4).Infof("Restoring iptables rules: %s", proxier.iptablesLines.Bytes())
}
err = proxier.iptables.RestoreAll(proxier.iptablesLines.Bytes(), utiliptables.NoFlushTables, utiliptables.RestoreCounters)
if err != nil { if err != nil {
glog.Errorf("Failed to execute iptables-restore: %v\nRules:\n%s", err, lines) glog.Errorf("Failed to execute iptables-restore: %v\nRules:\n%s", err, proxier.iptablesLines.Bytes())
// Revert new local ports. // Revert new local ports.
revertPorts(replacementPortsMap, proxier.portsMap) revertPorts(replacementPortsMap, proxier.portsMap)
return return

View File

@ -396,6 +396,10 @@ func NewFakeProxier(ipt utiliptables.Interface) *Proxier {
portMapper: &fakePortOpener{[]*localPort{}}, portMapper: &fakePortOpener{[]*localPort{}},
healthChecker: newFakeHealthChecker(), healthChecker: newFakeHealthChecker(),
iptablesLines: bytes.NewBuffer(nil), iptablesLines: bytes.NewBuffer(nil),
filterChains: bytes.NewBuffer(nil),
filterRules: bytes.NewBuffer(nil),
natChains: bytes.NewBuffer(nil),
natRules: bytes.NewBuffer(nil),
} }
} }