Kube-proxy: perf-enhancement: Reduce NAT table KUBE-SERVICES/NODEPORTS chain rules

The nat KUBE-SERVICES chain is called from OUTPUT and PREROUTING stages. In
clusters with large number of services, the nat-KUBE-SERVICES chain is the largest
chain with for eg: 33k rules. This patch aims to move the KubeMarkMasq rules from
the kubeServicesChain into the respective KUBE-SVC-* chains. This way during each
packet-rule matching we won't have to traverse the MASQ rules of all services which
get accumulated in the KUBE-SERVICES and/or KUBE-NODEPORTS chains. Since the
jump to KUBE-MARK-MASQ ultimately sets the 0x400 mark for nodeIP SNAT, it should not
matter whether the jump is made from KUBE-SERVICES or KUBE-SVC-* chains.

Specifically we change:

1) For ClusterIP svc, we move the KUBE-MARK-MASQ jump rule from KUBE-SERVICES
chain into KUBE-SVC-* chain.
2) For ExternalIP svc, we move the KUBE-MARK-MASQ jump rule in the case of
non-ServiceExternalTrafficPolicyTypeLocal from KUBE-SERVICES
chain into KUBE-SVC-* chain.
3) For NodePorts svc, we move the KUBE-MARK-MASQ jump rule in case of
non-ServiceExternalTrafficPolicyTypeLocal from KUBE-NODEPORTS chain to
KUBE-SVC-* chain.
4) For load-balancer svc, we don't change anything since it is already svc specific
due to creation of KUBE-FW-* chains per svc.

This would cut the rules per svc in KUBE-SERVICES and KUBE-NODEPORTS in half.
This commit is contained in:
Surya Seetharaman
2020-11-25 15:19:54 +01:00
parent 667e50abc8
commit d3fe48e848
4 changed files with 156 additions and 24 deletions

View File

@@ -1183,6 +1183,44 @@ func TestWriteLine(t *testing.T) {
}
}
func TestWriteRuleLine(t *testing.T) {
testCases := []struct {
name string
chainName string
words []string
expected string
}{
{
name: "write no line due to no words",
chainName: "KUBE-SVC-FOO",
words: []string{},
expected: "",
},
{
name: "write one line",
chainName: "KUBE-XLB-FOO",
words: []string{"test1"},
expected: "-A KUBE-XLB-FOO test1\n",
},
{
name: "write multi word line",
chainName: "lolChain",
words: []string{"test1", "test2", "test3"},
expected: "-A lolChain test1 test2 test3\n",
},
}
testBuffer := bytes.NewBuffer(nil)
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
testBuffer.Reset()
WriteRuleLine(testBuffer, testCase.chainName, testCase.words...)
if !strings.EqualFold(testBuffer.String(), testCase.expected) {
t.Fatalf("write word is %v\n expected: %s, got: %s", testCase.words, testCase.expected, testBuffer.String())
}
})
}
}
func TestWriteBytesLine(t *testing.T) {
testCases := []struct {
name string