mirror of https://github.com/k3s-io/k3s
Merge pull request #36055 from m1093782566/m109-fix-proxy-hasjump
Automatic merge from submit-queue [kube-proxy] Fix Jump() bug in pkg/proxy/iptables/proxier_test.go <!-- Thanks for sending a pull request! Here are some tips for you: 1. If this is your first time, read our contributor guidelines https://github.com/kubernetes/kubernetes/blob/master/CONTRIBUTING.md and developer guide https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md 2. If you want *faster* PR reviews, read how: https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md 3. Follow the instructions for writing a release note: https://github.com/kubernetes/kubernetes/blob/master/docs/devel/pull-requests.md#release-notes --> **Which issue this PR fixes** Fixes #36043pull/6/head
commit
5c2117764b
|
@ -257,11 +257,12 @@ func TestExecConntrackTool(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newFakeServiceInfo(service proxy.ServicePortName, ip net.IP, protocol api.Protocol, onlyNodeLocalEndpoints bool) *serviceInfo {
|
||||
func newFakeServiceInfo(service proxy.ServicePortName, ip net.IP, port int, protocol api.Protocol, onlyNodeLocalEndpoints bool) *serviceInfo {
|
||||
return &serviceInfo{
|
||||
sessionAffinityType: api.ServiceAffinityNone, // default
|
||||
stickyMaxAgeMinutes: 180, // TODO: paramaterize this in the API.
|
||||
clusterIP: ip,
|
||||
port: port,
|
||||
protocol: protocol,
|
||||
onlyNodeLocalEndpoints: onlyNodeLocalEndpoints,
|
||||
}
|
||||
|
@ -285,10 +286,10 @@ func TestDeleteEndpointConnections(t *testing.T) {
|
|||
}
|
||||
|
||||
serviceMap := make(map[proxy.ServicePortName]*serviceInfo)
|
||||
svc1 := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: "svc1"}, Port: ""}
|
||||
svc2 := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: "svc2"}, Port: ""}
|
||||
serviceMap[svc1] = newFakeServiceInfo(svc1, net.IPv4(10, 20, 30, 40), api.ProtocolUDP, false)
|
||||
serviceMap[svc2] = newFakeServiceInfo(svc1, net.IPv4(10, 20, 30, 41), api.ProtocolTCP, false)
|
||||
svc1 := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: "svc1"}, Port: "80"}
|
||||
svc2 := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: "svc2"}, Port: "80"}
|
||||
serviceMap[svc1] = newFakeServiceInfo(svc1, net.IPv4(10, 20, 30, 40), 80, api.ProtocolUDP, false)
|
||||
serviceMap[svc2] = newFakeServiceInfo(svc1, net.IPv4(10, 20, 30, 41), 80, api.ProtocolTCP, false)
|
||||
|
||||
fakeProxier := Proxier{exec: &fexec, serviceMap: serviceMap}
|
||||
|
||||
|
@ -505,18 +506,146 @@ func NewFakeProxier(ipt utiliptables.Interface) *Proxier {
|
|||
}
|
||||
|
||||
func hasJump(rules []iptablestest.Rule, destChain, destIP, destPort string) bool {
|
||||
match := false
|
||||
for _, r := range rules {
|
||||
if r[iptablestest.Jump] == destChain {
|
||||
match = true
|
||||
if destIP != "" {
|
||||
return strings.Contains(r[iptablestest.Destination], destIP)
|
||||
if strings.Contains(r[iptablestest.Destination], destIP) && (strings.Contains(r[iptablestest.DPort], destPort) || r[iptablestest.DPort] == "") {
|
||||
return true
|
||||
}
|
||||
match = false
|
||||
}
|
||||
if destPort != "" {
|
||||
return strings.Contains(r[iptablestest.DPort], destPort)
|
||||
if strings.Contains(r[iptablestest.DPort], destPort) && (strings.Contains(r[iptablestest.Destination], destIP) || r[iptablestest.Destination] == "") {
|
||||
return true
|
||||
}
|
||||
match = false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return match
|
||||
}
|
||||
|
||||
func TestHasJump(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
rules []iptablestest.Rule
|
||||
destChain string
|
||||
destIP string
|
||||
destPort string
|
||||
expected bool
|
||||
}{
|
||||
"case 1": {
|
||||
// Match the 1st rule(both dest IP and dest Port)
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "10.20.30.41/32", "--dport ": "80", "-p ": "tcp", "-j ": "REJECT"},
|
||||
{"--dport ": "3001", "-p ": "tcp", "-j ": "KUBE-MARK-MASQ"},
|
||||
},
|
||||
destChain: "REJECT",
|
||||
destIP: "10.20.30.41",
|
||||
destPort: "80",
|
||||
expected: true,
|
||||
},
|
||||
"case 2": {
|
||||
// Match the 2nd rule(dest Port)
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "10.20.30.41/32", "-p ": "tcp", "-j ": "REJECT"},
|
||||
{"--dport ": "3001", "-p ": "tcp", "-j ": "REJECT"},
|
||||
},
|
||||
destChain: "REJECT",
|
||||
destIP: "",
|
||||
destPort: "3001",
|
||||
expected: true,
|
||||
},
|
||||
"case 3": {
|
||||
// Match both dest IP and dest Port
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "1.2.3.4/32", "--dport ": "80", "-p ": "tcp", "-j ": "KUBE-XLB-GF53O3C2HZEXL2XN"},
|
||||
},
|
||||
destChain: "KUBE-XLB-GF53O3C2HZEXL2XN",
|
||||
destIP: "1.2.3.4",
|
||||
destPort: "80",
|
||||
expected: true,
|
||||
},
|
||||
"case 4": {
|
||||
// Match dest IP but doesn't match dest Port
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "1.2.3.4/32", "--dport ": "80", "-p ": "tcp", "-j ": "KUBE-XLB-GF53O3C2HZEXL2XN"},
|
||||
},
|
||||
destChain: "KUBE-XLB-GF53O3C2HZEXL2XN",
|
||||
destIP: "1.2.3.4",
|
||||
destPort: "8080",
|
||||
expected: false,
|
||||
},
|
||||
"case 5": {
|
||||
// Match dest Port but doesn't match dest IP
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "1.2.3.4/32", "--dport ": "80", "-p ": "tcp", "-j ": "KUBE-XLB-GF53O3C2HZEXL2XN"},
|
||||
},
|
||||
destChain: "KUBE-XLB-GF53O3C2HZEXL2XN",
|
||||
destIP: "10.20.30.40",
|
||||
destPort: "80",
|
||||
expected: false,
|
||||
},
|
||||
"case 6": {
|
||||
// Match the 2nd rule(dest IP)
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "10.20.30.41/32", "-p ": "tcp", "-j ": "REJECT"},
|
||||
{"-d ": "1.2.3.4/32", "-p ": "tcp", "-j ": "REJECT"},
|
||||
{"--dport ": "3001", "-p ": "tcp", "-j ": "REJECT"},
|
||||
},
|
||||
destChain: "REJECT",
|
||||
destIP: "1.2.3.4",
|
||||
destPort: "8080",
|
||||
expected: true,
|
||||
},
|
||||
"case 7": {
|
||||
// Match the 2nd rule(dest Port)
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "10.20.30.41/32", "-p ": "tcp", "-j ": "REJECT"},
|
||||
{"--dport ": "3001", "-p ": "tcp", "-j ": "REJECT"},
|
||||
},
|
||||
destChain: "REJECT",
|
||||
destIP: "1.2.3.4",
|
||||
destPort: "3001",
|
||||
expected: true,
|
||||
},
|
||||
"case 8": {
|
||||
// Match the 1st rule(dest IP)
|
||||
rules: []iptablestest.Rule{
|
||||
{"-d ": "10.20.30.41/32", "-p ": "tcp", "-j ": "REJECT"},
|
||||
{"--dport ": "3001", "-p ": "tcp", "-j ": "REJECT"},
|
||||
},
|
||||
destChain: "REJECT",
|
||||
destIP: "10.20.30.41",
|
||||
destPort: "8080",
|
||||
expected: true,
|
||||
},
|
||||
"case 9": {
|
||||
rules: []iptablestest.Rule{
|
||||
{"-j ": "KUBE-SEP-LWSOSDSHMKPJHHJV"},
|
||||
},
|
||||
destChain: "KUBE-SEP-LWSOSDSHMKPJHHJV",
|
||||
destIP: "",
|
||||
destPort: "",
|
||||
expected: true,
|
||||
},
|
||||
"case 10": {
|
||||
rules: []iptablestest.Rule{
|
||||
{"-j ": "KUBE-SEP-FOO"},
|
||||
},
|
||||
destChain: "KUBE-SEP-BAR",
|
||||
destIP: "",
|
||||
destPort: "",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for k, tc := range testCases {
|
||||
if got := hasJump(tc.rules, tc.destChain, tc.destIP, tc.destPort); got != tc.expected {
|
||||
t.Errorf("%v: expected %v, got %v", k, tc.expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasDNAT(rules []iptablestest.Rule, endpoint string) bool {
|
||||
|
@ -541,8 +670,8 @@ func TestClusterIPReject(t *testing.T) {
|
|||
svcName := "svc1"
|
||||
svcIP := net.IPv4(10, 20, 30, 41)
|
||||
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: ""}
|
||||
fp.serviceMap[svc] = newFakeServiceInfo(svc, svcIP, api.ProtocolTCP, false)
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: "80"}
|
||||
fp.serviceMap[svc] = newFakeServiceInfo(svc, svcIP, 80, api.ProtocolTCP, false)
|
||||
fp.syncProxyRules()
|
||||
|
||||
svcChain := string(servicePortChainName(svc, strings.ToLower(string(api.ProtocolTCP))))
|
||||
|
@ -551,7 +680,7 @@ func TestClusterIPReject(t *testing.T) {
|
|||
errorf(fmt.Sprintf("Unexpected rule for chain %v service %v without endpoints", svcChain, svcName), svcRules, t)
|
||||
}
|
||||
kubeSvcRules := ipt.GetRules(string(kubeServicesChain))
|
||||
if !hasJump(kubeSvcRules, iptablestest.Reject, svcIP.String(), "") {
|
||||
if !hasJump(kubeSvcRules, iptablestest.Reject, svcIP.String(), "80") {
|
||||
errorf(fmt.Sprintf("Failed to find a %v rule for service %v with no endpoints", iptablestest.Reject, svcName), kubeSvcRules, t)
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +692,7 @@ func TestClusterIPEndpointsJump(t *testing.T) {
|
|||
svcIP := net.IPv4(10, 20, 30, 41)
|
||||
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: "80"}
|
||||
fp.serviceMap[svc] = newFakeServiceInfo(svc, svcIP, api.ProtocolTCP, true)
|
||||
fp.serviceMap[svc] = newFakeServiceInfo(svc, svcIP, 80, api.ProtocolTCP, true)
|
||||
ep := "10.180.0.1:80"
|
||||
fp.endpointsMap[svc] = []*endpointsInfo{{ep, false}}
|
||||
|
||||
|
@ -573,7 +702,7 @@ func TestClusterIPEndpointsJump(t *testing.T) {
|
|||
epChain := string(servicePortEndpointChainName(svc, strings.ToLower(string(api.ProtocolTCP)), ep))
|
||||
|
||||
kubeSvcRules := ipt.GetRules(string(kubeServicesChain))
|
||||
if !hasJump(kubeSvcRules, svcChain, svcIP.String(), "") {
|
||||
if !hasJump(kubeSvcRules, svcChain, svcIP.String(), "80") {
|
||||
errorf(fmt.Sprintf("Failed to find jump from KUBE-SERVICES to %v chain", svcChain), kubeSvcRules, t)
|
||||
}
|
||||
|
||||
|
@ -602,7 +731,7 @@ func TestLoadBalancer(t *testing.T) {
|
|||
svcIP := net.IPv4(10, 20, 30, 41)
|
||||
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: "80"}
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, api.ProtocolTCP, false)
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, 80, api.ProtocolTCP, false)
|
||||
fp.serviceMap[svc] = typeLoadBalancer(svcInfo)
|
||||
|
||||
ep1 := "10.180.0.1:80"
|
||||
|
@ -616,7 +745,7 @@ func TestLoadBalancer(t *testing.T) {
|
|||
//lbChain := string(serviceLBChainName(svc, proto))
|
||||
|
||||
kubeSvcRules := ipt.GetRules(string(kubeServicesChain))
|
||||
if !hasJump(kubeSvcRules, fwChain, svcInfo.loadBalancerStatus.Ingress[0].IP, "") {
|
||||
if !hasJump(kubeSvcRules, fwChain, svcInfo.loadBalancerStatus.Ingress[0].IP, "80") {
|
||||
errorf(fmt.Sprintf("Failed to find jump to firewall chain %v", fwChain), kubeSvcRules, t)
|
||||
}
|
||||
|
||||
|
@ -633,7 +762,7 @@ func TestNodePort(t *testing.T) {
|
|||
svcIP := net.IPv4(10, 20, 30, 41)
|
||||
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: "80"}
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, api.ProtocolTCP, false)
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, 80, api.ProtocolTCP, false)
|
||||
svcInfo.nodePort = 3001
|
||||
fp.serviceMap[svc] = svcInfo
|
||||
|
||||
|
@ -658,7 +787,7 @@ func TestOnlyLocalLoadBalancing(t *testing.T) {
|
|||
svcIP := net.IPv4(10, 20, 30, 41)
|
||||
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: "80"}
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, api.ProtocolTCP, true)
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, 80, api.ProtocolTCP, true)
|
||||
fp.serviceMap[svc] = typeLoadBalancer(svcInfo)
|
||||
|
||||
nonLocalEp := "10.180.0.1:80"
|
||||
|
@ -716,7 +845,7 @@ func onlyLocalNodePorts(t *testing.T, fp *Proxier, ipt *iptablestest.FakeIPTable
|
|||
svcIP := net.IPv4(10, 20, 30, 41)
|
||||
|
||||
svc := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "ns1", Name: svcName}, Port: "80"}
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, api.ProtocolTCP, true)
|
||||
svcInfo := newFakeServiceInfo(svc, svcIP, 80, api.ProtocolTCP, true)
|
||||
svcInfo.nodePort = 3001
|
||||
fp.serviceMap[svc] = svcInfo
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ func getToken(line, seperator string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// GetChain returns a list of rules for the givne chain.
|
||||
// GetChain returns a list of rules for the given chain.
|
||||
// The chain name must match exactly.
|
||||
// The matching is pretty dumb, don't rely on it for anything but testing.
|
||||
func (f *FakeIPTables) GetRules(chainName string) (rules []Rule) {
|
||||
|
|
Loading…
Reference in New Issue