mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 18:02:01 +00:00
e2e network test for multiple protocol services on same port
The test creates a Service exposing two protocols on the same port and a backend that replies on both protocols. 1. Test that Service with works for both protocol 2. Update Service to expose only the TCP port 3. Verify that TCP works and UDP does not work 4. Update Service to expose only the UDP port 5. Verify that TCP does not work and UDP does work Change-Id: Ic4f3a6509e332aa5694d20dfc3b223d7063a7871
This commit is contained in:
parent
1af56548af
commit
7cb135a888
@ -3618,6 +3618,114 @@ var _ = common.SIGDescribe("Services", func() {
|
|||||||
|
|
||||||
framework.Logf("Collection of services has been deleted")
|
framework.Logf("Collection of services has been deleted")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should serve endpoints on same port and different protocols", func(ctx context.Context) {
|
||||||
|
serviceName := "multiprotocol-test"
|
||||||
|
testLabels := map[string]string{"app": "multiport"}
|
||||||
|
ns := f.Namespace.Name
|
||||||
|
containerPort := 80
|
||||||
|
|
||||||
|
svcTCPport := v1.ServicePort{
|
||||||
|
Name: "tcp-port",
|
||||||
|
Port: 80,
|
||||||
|
TargetPort: intstr.FromInt(containerPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}
|
||||||
|
svcUDPport := v1.ServicePort{
|
||||||
|
Name: "udp-port",
|
||||||
|
Port: 80,
|
||||||
|
TargetPort: intstr.FromInt(containerPort),
|
||||||
|
Protocol: v1.ProtocolUDP,
|
||||||
|
}
|
||||||
|
|
||||||
|
ginkgo.By("creating service " + serviceName + " in namespace " + ns)
|
||||||
|
|
||||||
|
testService := v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: serviceName,
|
||||||
|
Labels: testLabels,
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{
|
||||||
|
Type: v1.ServiceTypeClusterIP,
|
||||||
|
Selector: testLabels,
|
||||||
|
Ports: []v1.ServicePort{svcTCPport, svcUDPport},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
service, err := cs.CoreV1().Services(ns).Create(ctx, &testService, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err, "failed to create Service")
|
||||||
|
|
||||||
|
containerPorts := []v1.ContainerPort{{
|
||||||
|
Name: svcTCPport.Name,
|
||||||
|
ContainerPort: int32(containerPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
}, {
|
||||||
|
Name: svcUDPport.Name,
|
||||||
|
ContainerPort: int32(containerPort),
|
||||||
|
Protocol: v1.ProtocolUDP,
|
||||||
|
}}
|
||||||
|
podname1 := "pod1"
|
||||||
|
ginkgo.By("creating pod " + podname1 + " in namespace " + ns)
|
||||||
|
createPodOrFail(ctx, f, ns, podname1, testLabels, containerPorts, "netexec", "--http-port", strconv.Itoa(containerPort), "--udp-port", strconv.Itoa(containerPort))
|
||||||
|
validateEndpointsPortsWithProtocolsOrFail(cs, ns, serviceName, fullPortsByPodName{podname1: containerPorts})
|
||||||
|
|
||||||
|
ginkgo.By("Checking if the Service forwards traffic to the TCP and UDP port")
|
||||||
|
execPod := e2epod.CreateExecPodOrFail(ctx, cs, ns, "execpod", nil)
|
||||||
|
err = testEndpointReachability(ctx, service.Spec.ClusterIP, 80, v1.ProtocolTCP, execPod, 30*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed to connect to Service TCP port: %v", err)
|
||||||
|
}
|
||||||
|
err = testEndpointReachability(ctx, service.Spec.ClusterIP, 80, v1.ProtocolUDP, execPod, 30*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed to connect to Service UDP port: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ginkgo.By("Checking if the Service forwards traffic to TCP only")
|
||||||
|
service, err = cs.CoreV1().Services(ns).Get(ctx, serviceName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("failed to get Service %q: %v", serviceName, err)
|
||||||
|
}
|
||||||
|
service.Spec.Ports = []v1.ServicePort{svcTCPport}
|
||||||
|
_, err = cs.CoreV1().Services(ns).Update(ctx, service, metav1.UpdateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("failed to get Service %q: %v", serviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test reachability
|
||||||
|
err = testEndpointReachability(ctx, service.Spec.ClusterIP, 80, v1.ProtocolTCP, execPod, 30*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed to connect to Service TCP port: %v", err)
|
||||||
|
}
|
||||||
|
// take into account the NetworkProgrammingLatency
|
||||||
|
// testEndpointReachability tries 3 times every 3 second
|
||||||
|
// we retry again during 30 seconds to check if the port stops forwarding
|
||||||
|
gomega.Eventually(ctx, func() error {
|
||||||
|
return testEndpointReachability(ctx, service.Spec.ClusterIP, 80, v1.ProtocolUDP, execPod, 6*time.Second)
|
||||||
|
}).WithTimeout(30 * time.Second).WithPolling(5 * time.Second).ShouldNot(gomega.BeNil())
|
||||||
|
|
||||||
|
ginkgo.By("Checking if the Service forwards traffic to UDP only")
|
||||||
|
service, err = cs.CoreV1().Services(ns).Get(ctx, serviceName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("failed to get Service %q: %v", serviceName, err)
|
||||||
|
}
|
||||||
|
service.Spec.Ports = []v1.ServicePort{svcUDPport}
|
||||||
|
_, err = cs.CoreV1().Services(ns).Update(ctx, service, metav1.UpdateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("failed to update Service %q: %v", serviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test reachability
|
||||||
|
err = testEndpointReachability(ctx, service.Spec.ClusterIP, 80, v1.ProtocolUDP, execPod, 30*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed to connect to Service UDP port: %v", err)
|
||||||
|
}
|
||||||
|
// take into account the NetworkProgrammingLatency
|
||||||
|
// testEndpointReachability tries 3 times every 3 second
|
||||||
|
// we retry again during 30 seconds to check if the port stops forwarding
|
||||||
|
gomega.Eventually(ctx, func() error {
|
||||||
|
return testEndpointReachability(ctx, service.Spec.ClusterIP, 80, v1.ProtocolTCP, execPod, 6*time.Second)
|
||||||
|
}).WithTimeout(30 * time.Second).WithPolling(5 * time.Second).ShouldNot(gomega.BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Release: v1.26
|
Release: v1.26
|
||||||
Testname: Service, same ports with different protocols on a Load Balancer Service
|
Testname: Service, same ports with different protocols on a Load Balancer Service
|
||||||
|
@ -218,3 +218,34 @@ func createSecondNodePortService(ctx context.Context, f *framework.Framework, co
|
|||||||
|
|
||||||
return createdService, httpPort
|
return createdService, httpPort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testEndpointReachability tests reachability to endpoints (i.e. IP, ServiceName) and ports. Test request is initiated from specified execPod.
|
||||||
|
// TCP and UDP protocol based service are supported at this moment
|
||||||
|
func testEndpointReachability(ctx context.Context, endpoint string, port int32, protocol v1.Protocol, execPod *v1.Pod, timeout time.Duration) error {
|
||||||
|
cmd := ""
|
||||||
|
switch protocol {
|
||||||
|
case v1.ProtocolTCP:
|
||||||
|
cmd = fmt.Sprintf("echo hostName | nc -v -t -w 2 %s %v", endpoint, port)
|
||||||
|
case v1.ProtocolUDP:
|
||||||
|
cmd = fmt.Sprintf("echo hostName | nc -v -u -w 2 %s %v", endpoint, port)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("service reachability check is not supported for %v", protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := wait.PollImmediateWithContext(ctx, framework.Poll, timeout, func(ctx context.Context) (bool, error) {
|
||||||
|
stdout, err := e2eoutput.RunHostCmd(execPod.Namespace, execPod.Name, cmd)
|
||||||
|
if err != nil {
|
||||||
|
framework.Logf("Service reachability failing with error: %v\nRetrying...", err)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
trimmed := strings.TrimSpace(stdout)
|
||||||
|
if trimmed != "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("service is not reachable within %v timeout on endpoint %s %d over %s protocol", timeout, endpoint, port, protocol)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user