mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 18:31:15 +00:00
Merge pull request #104407 from aojea/host_network_collision
hostNetwork tests can't share the same port
This commit is contained in:
commit
851b4a2c9a
@ -2188,87 +2188,7 @@ var _ = common.SIGDescribe("Services", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should respect internalTrafficPolicy=Local Pod to Pod (hostNetwork: true) [Feature:ServiceInternalTrafficPolicy]", func() {
|
ginkgo.It("should respect internalTrafficPolicy=Local Pod and Node, to Pod (hostNetwork: true) [Feature:ServiceInternalTrafficPolicy]", func() {
|
||||||
// windows kube-proxy does not support this feature yet
|
|
||||||
// TODO: remove this skip when windows-based proxies implement internalTrafficPolicy
|
|
||||||
e2eskipper.SkipIfNodeOSDistroIs("windows")
|
|
||||||
|
|
||||||
// This behavior is not supported if Kube-proxy is in "userspace" mode.
|
|
||||||
// So we check the kube-proxy mode and skip this test if that's the case.
|
|
||||||
if proxyMode, err := proxyMode(f); err == nil {
|
|
||||||
if proxyMode == "userspace" {
|
|
||||||
e2eskipper.Skipf("The test doesn't work with kube-proxy in userspace mode")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
framework.Logf("Couldn't detect KubeProxy mode - test failure may be expected: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes, err := e2enode.GetBoundedReadySchedulableNodes(cs, 2)
|
|
||||||
framework.ExpectNoError(err)
|
|
||||||
nodeCounts := len(nodes.Items)
|
|
||||||
if nodeCounts < 2 {
|
|
||||||
e2eskipper.Skipf("The test requires at least two ready nodes on %s, but found %v", framework.TestContext.Provider, nodeCounts)
|
|
||||||
}
|
|
||||||
node0 := nodes.Items[0]
|
|
||||||
node1 := nodes.Items[1]
|
|
||||||
|
|
||||||
serviceName := "svc-itp"
|
|
||||||
ns := f.Namespace.Name
|
|
||||||
servicePort := 8000
|
|
||||||
|
|
||||||
ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP and internalTrafficPolicy=Local in namespace " + ns)
|
|
||||||
local := v1.ServiceInternalTrafficPolicyLocal
|
|
||||||
jig := e2eservice.NewTestJig(cs, ns, serviceName)
|
|
||||||
svc, err := jig.CreateTCPService(func(svc *v1.Service) {
|
|
||||||
svc.Spec.Ports = []v1.ServicePort{
|
|
||||||
{Port: 8000, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(8000)},
|
|
||||||
}
|
|
||||||
svc.Spec.InternalTrafficPolicy = &local
|
|
||||||
})
|
|
||||||
framework.ExpectNoError(err)
|
|
||||||
|
|
||||||
ginkgo.By("Creating 1 webserver pod to be part of the TCP service")
|
|
||||||
webserverPod0 := e2epod.NewAgnhostPod(ns, "echo-hostname-0", nil, nil, nil, "netexec", "--http-port", strconv.Itoa(servicePort))
|
|
||||||
webserverPod0.Labels = jig.Labels
|
|
||||||
webserverPod0.Spec.HostNetwork = true
|
|
||||||
e2epod.SetNodeSelection(&webserverPod0.Spec, e2epod.NodeSelection{Name: node0.Name})
|
|
||||||
|
|
||||||
_, err = cs.CoreV1().Pods(ns).Create(context.TODO(), webserverPod0, metav1.CreateOptions{})
|
|
||||||
framework.ExpectNoError(err)
|
|
||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, webserverPod0.Name, f.Namespace.Name, framework.PodStartTimeout))
|
|
||||||
|
|
||||||
validateEndpointsPortsOrFail(cs, ns, serviceName, portsByPodName{webserverPod0.Name: {servicePort}})
|
|
||||||
|
|
||||||
ginkgo.By("Creating 2 pause pods that will try to connect to the webservers")
|
|
||||||
pausePod0 := e2epod.NewAgnhostPod(ns, "pause-pod-0", nil, nil, nil)
|
|
||||||
e2epod.SetNodeSelection(&pausePod0.Spec, e2epod.NodeSelection{Name: node0.Name})
|
|
||||||
|
|
||||||
pausePod0, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod0, metav1.CreateOptions{})
|
|
||||||
framework.ExpectNoError(err)
|
|
||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, pausePod0.Name, f.Namespace.Name, framework.PodStartTimeout))
|
|
||||||
|
|
||||||
pausePod1 := e2epod.NewAgnhostPod(ns, "pause-pod-1", nil, nil, nil)
|
|
||||||
e2epod.SetNodeSelection(&pausePod1.Spec, e2epod.NodeSelection{Name: node1.Name})
|
|
||||||
|
|
||||||
pausePod1, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod1, metav1.CreateOptions{})
|
|
||||||
framework.ExpectNoError(err)
|
|
||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, pausePod1.Name, f.Namespace.Name, framework.PodStartTimeout))
|
|
||||||
|
|
||||||
// assert 5 times that the first pause pod can connect to the Service locally and the second one errors with a timeout
|
|
||||||
serviceAddress := net.JoinHostPort(svc.Spec.ClusterIP, strconv.Itoa(servicePort))
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
// the first pause pod should be on the same node as the webserver, so it can connect to the local pod using clusterIP
|
|
||||||
// note that the expected hostname is the node name because the backend pod is on host network
|
|
||||||
execHostnameTest(*pausePod0, serviceAddress, node0.Name)
|
|
||||||
|
|
||||||
// the second pause pod is on a different node, so it should see a connection error every time
|
|
||||||
cmd := fmt.Sprintf(`curl -q -s --connect-timeout 5 %s/hostname`, serviceAddress)
|
|
||||||
_, err := framework.RunHostCmd(pausePod1.Namespace, pausePod1.Name, cmd)
|
|
||||||
framework.ExpectError(err, "expected error when trying to connect to cluster IP")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("should respect internalTrafficPolicy=Local Pod (hostNetwork: true) to Pod (hostNetwork: true) [Feature:ServiceInternalTrafficPolicy]", func() {
|
|
||||||
// windows kube-proxy does not support this feature yet
|
// windows kube-proxy does not support this feature yet
|
||||||
// TODO: remove this skip when windows-based proxies implement internalTrafficPolicy
|
// TODO: remove this skip when windows-based proxies implement internalTrafficPolicy
|
||||||
e2eskipper.SkipIfNodeOSDistroIs("windows")
|
e2eskipper.SkipIfNodeOSDistroIs("windows")
|
||||||
@ -2295,20 +2215,23 @@ var _ = common.SIGDescribe("Services", func() {
|
|||||||
serviceName := "svc-itp"
|
serviceName := "svc-itp"
|
||||||
ns := f.Namespace.Name
|
ns := f.Namespace.Name
|
||||||
servicePort := 80
|
servicePort := 80
|
||||||
|
// If the pod can't bind to this port, it will fail to start, and it will fail the test,
|
||||||
|
// because is using hostNetwork. Using a not common port will reduce this possibility.
|
||||||
|
endpointPort := 10180
|
||||||
|
|
||||||
ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP and internalTrafficPolicy=Local in namespace " + ns)
|
ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP and internalTrafficPolicy=Local in namespace " + ns)
|
||||||
local := v1.ServiceInternalTrafficPolicyLocal
|
local := v1.ServiceInternalTrafficPolicyLocal
|
||||||
jig := e2eservice.NewTestJig(cs, ns, serviceName)
|
jig := e2eservice.NewTestJig(cs, ns, serviceName)
|
||||||
svc, err := jig.CreateTCPService(func(svc *v1.Service) {
|
svc, err := jig.CreateTCPService(func(svc *v1.Service) {
|
||||||
svc.Spec.Ports = []v1.ServicePort{
|
svc.Spec.Ports = []v1.ServicePort{
|
||||||
{Port: 80, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(80)},
|
{Port: 80, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(endpointPort)},
|
||||||
}
|
}
|
||||||
svc.Spec.InternalTrafficPolicy = &local
|
svc.Spec.InternalTrafficPolicy = &local
|
||||||
})
|
})
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
ginkgo.By("Creating 1 webserver pod to be part of the TCP service")
|
ginkgo.By("Creating 1 webserver pod to be part of the TCP service")
|
||||||
webserverPod0 := e2epod.NewAgnhostPod(ns, "echo-hostname-0", nil, nil, nil, "netexec", "--http-port", strconv.Itoa(servicePort))
|
webserverPod0 := e2epod.NewAgnhostPod(ns, "echo-hostname-0", nil, nil, nil, "netexec", "--http-port", strconv.Itoa(endpointPort))
|
||||||
webserverPod0.Labels = jig.Labels
|
webserverPod0.Labels = jig.Labels
|
||||||
webserverPod0.Spec.HostNetwork = true
|
webserverPod0.Spec.HostNetwork = true
|
||||||
e2epod.SetNodeSelection(&webserverPod0.Spec, e2epod.NodeSelection{Name: node0.Name})
|
e2epod.SetNodeSelection(&webserverPod0.Spec, e2epod.NodeSelection{Name: node0.Name})
|
||||||
@ -2317,11 +2240,10 @@ var _ = common.SIGDescribe("Services", func() {
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, webserverPod0.Name, f.Namespace.Name, framework.PodStartTimeout))
|
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, webserverPod0.Name, f.Namespace.Name, framework.PodStartTimeout))
|
||||||
|
|
||||||
validateEndpointsPortsOrFail(cs, ns, serviceName, portsByPodName{webserverPod0.Name: {servicePort}})
|
validateEndpointsPortsOrFail(cs, ns, serviceName, portsByPodName{webserverPod0.Name: {endpointPort}})
|
||||||
|
|
||||||
ginkgo.By("Creating 2 pause pods that will try to connect to the webservers")
|
ginkgo.By("Creating 2 pause pods that will try to connect to the webserver")
|
||||||
pausePod0 := e2epod.NewAgnhostPod(ns, "pause-pod-0", nil, nil, nil)
|
pausePod0 := e2epod.NewAgnhostPod(ns, "pause-pod-0", nil, nil, nil)
|
||||||
pausePod0.Spec.HostNetwork = true
|
|
||||||
e2epod.SetNodeSelection(&pausePod0.Spec, e2epod.NodeSelection{Name: node0.Name})
|
e2epod.SetNodeSelection(&pausePod0.Spec, e2epod.NodeSelection{Name: node0.Name})
|
||||||
|
|
||||||
pausePod0, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod0, metav1.CreateOptions{})
|
pausePod0, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod0, metav1.CreateOptions{})
|
||||||
@ -2329,7 +2251,6 @@ var _ = common.SIGDescribe("Services", func() {
|
|||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, pausePod0.Name, f.Namespace.Name, framework.PodStartTimeout))
|
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, pausePod0.Name, f.Namespace.Name, framework.PodStartTimeout))
|
||||||
|
|
||||||
pausePod1 := e2epod.NewAgnhostPod(ns, "pause-pod-1", nil, nil, nil)
|
pausePod1 := e2epod.NewAgnhostPod(ns, "pause-pod-1", nil, nil, nil)
|
||||||
pausePod1.Spec.HostNetwork = true
|
|
||||||
e2epod.SetNodeSelection(&pausePod1.Spec, e2epod.NodeSelection{Name: node1.Name})
|
e2epod.SetNodeSelection(&pausePod1.Spec, e2epod.NodeSelection{Name: node1.Name})
|
||||||
|
|
||||||
pausePod1, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod1, metav1.CreateOptions{})
|
pausePod1, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod1, metav1.CreateOptions{})
|
||||||
@ -2348,6 +2269,35 @@ var _ = common.SIGDescribe("Services", func() {
|
|||||||
_, err := framework.RunHostCmd(pausePod1.Namespace, pausePod1.Name, cmd)
|
_, err := framework.RunHostCmd(pausePod1.Namespace, pausePod1.Name, cmd)
|
||||||
framework.ExpectError(err, "expected error when trying to connect to cluster IP")
|
framework.ExpectError(err, "expected error when trying to connect to cluster IP")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ginkgo.By("Creating 2 pause hostNetwork pods that will try to connect to the webserver")
|
||||||
|
pausePod2 := e2epod.NewAgnhostPod(ns, "pause-pod-2", nil, nil, nil)
|
||||||
|
pausePod2.Spec.HostNetwork = true
|
||||||
|
e2epod.SetNodeSelection(&pausePod2.Spec, e2epod.NodeSelection{Name: node0.Name})
|
||||||
|
|
||||||
|
pausePod2, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod2, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, pausePod2.Name, f.Namespace.Name, framework.PodStartTimeout))
|
||||||
|
|
||||||
|
pausePod3 := e2epod.NewAgnhostPod(ns, "pause-pod-3", nil, nil, nil)
|
||||||
|
pausePod3.Spec.HostNetwork = true
|
||||||
|
e2epod.SetNodeSelection(&pausePod3.Spec, e2epod.NodeSelection{Name: node1.Name})
|
||||||
|
|
||||||
|
pausePod3, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pausePod3, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(f.ClientSet, pausePod3.Name, f.Namespace.Name, framework.PodStartTimeout))
|
||||||
|
|
||||||
|
// assert 5 times that the first pause pod can connect to the Service locally and the second one errors with a timeout
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
// the first pause pod should be on the same node as the webserver, so it can connect to the local pod using clusterIP
|
||||||
|
// note that the expected hostname is the node name because the backend pod is on host network
|
||||||
|
execHostnameTest(*pausePod2, serviceAddress, node0.Name)
|
||||||
|
|
||||||
|
// the second pause pod is on a different node, so it should see a connection error every time
|
||||||
|
cmd := fmt.Sprintf(`curl -q -s --connect-timeout 5 %s/hostname`, serviceAddress)
|
||||||
|
_, err := framework.RunHostCmd(pausePod3.Namespace, pausePod3.Name, cmd)
|
||||||
|
framework.ExpectError(err, "expected error when trying to connect to cluster IP")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user