mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 18:02:01 +00:00
Add e2e multiple endpoint services test
- ensures that when multiple services with the same selector will function even if one of the services is deleted
This commit is contained in:
parent
a28a692917
commit
e6428ae214
@ -611,11 +611,11 @@ func (config *NetworkingTestConfig) createNodePortServiceSpec(svcName string, se
|
||||
}
|
||||
|
||||
func (config *NetworkingTestConfig) createNodePortService(selector map[string]string) {
|
||||
config.NodePortService = config.createService(config.createNodePortServiceSpec(nodePortServiceName, selector, false))
|
||||
config.NodePortService = config.CreateService(config.createNodePortServiceSpec(nodePortServiceName, selector, false))
|
||||
}
|
||||
|
||||
func (config *NetworkingTestConfig) createSessionAffinityService(selector map[string]string) {
|
||||
config.SessionAffinityService = config.createService(config.createNodePortServiceSpec(sessionAffinityServiceName, selector, true))
|
||||
config.SessionAffinityService = config.CreateService(config.createNodePortServiceSpec(sessionAffinityServiceName, selector, true))
|
||||
}
|
||||
|
||||
// DeleteNodePortService deletes NodePort service.
|
||||
@ -651,7 +651,8 @@ func (config *NetworkingTestConfig) createTestPods() {
|
||||
}
|
||||
}
|
||||
|
||||
func (config *NetworkingTestConfig) createService(serviceSpec *v1.Service) *v1.Service {
|
||||
// CreateService creates the provided service in config.Namespace and returns created service
|
||||
func (config *NetworkingTestConfig) CreateService(serviceSpec *v1.Service) *v1.Service {
|
||||
_, err := config.getServiceClient().Create(context.TODO(), serviceSpec, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err, fmt.Sprintf("Failed to create %s service: %v", serviceSpec.Name, err))
|
||||
|
||||
|
@ -226,6 +226,38 @@ var _ = SIGDescribe("Networking", func() {
|
||||
config.DialFromEndpointContainer("udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
})
|
||||
|
||||
// This test ensures that in a situation where multiple services exist with the same selector,
|
||||
// deleting one of the services does not affect the connectivity of the remaining service
|
||||
ginkgo.It("should function for multiple endpoint-Services with same selector", func() {
|
||||
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||
ginkgo.By("creating a second service with same selector")
|
||||
svc2, httpPort := createSecondNodePortService(f, config)
|
||||
|
||||
// original service should work
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||
config.DialFromEndpointContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, config.NodeHTTPPort))
|
||||
config.DialFromEndpointContainer("http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
|
||||
// Dial second service
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (svc2.clusterIP)", config.EndpointPods[0].Name, svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||
config.DialFromEndpointContainer("http", svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, httpPort))
|
||||
config.DialFromEndpointContainer("http", config.NodeIP, httpPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
|
||||
ginkgo.By("deleting the original node port service")
|
||||
config.DeleteNodePortService()
|
||||
|
||||
// Second service should continue to function unaffected
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (svc2.clusterIP)", config.EndpointPods[0].Name, svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||
config.DialFromEndpointContainer("http", svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, httpPort))
|
||||
config.DialFromEndpointContainer("http", config.NodeIP, httpPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||
})
|
||||
|
||||
ginkgo.It("should update endpoints: http", func() {
|
||||
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
|
||||
@ -33,6 +34,9 @@ import (
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
)
|
||||
|
||||
// secondNodePortSvcName is the name of the secondary node port service
|
||||
const secondNodePortSvcName = "second-node-port-service"
|
||||
|
||||
var (
|
||||
// agnHostImage is the image URI of AgnHost
|
||||
agnHostImage = imageutils.GetE2EImage(imageutils.Agnhost)
|
||||
@ -162,3 +166,41 @@ func execSourceIPTest(sourcePod v1.Pod, targetAddr string) (string, string) {
|
||||
}
|
||||
return sourcePod.Status.PodIP, host
|
||||
}
|
||||
|
||||
// createSecondNodePortService creates a service with the same selector as config.NodePortService and same HTTP Port
|
||||
func createSecondNodePortService(f *framework.Framework, config *e2enetwork.NetworkingTestConfig) (*v1.Service, int) {
|
||||
svc := &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: secondNodePortSvcName,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeNodePort,
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: e2enetwork.ClusterHTTPPort,
|
||||
Name: "http",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
TargetPort: intstr.FromInt(e2enetwork.EndpointHTTPPort),
|
||||
},
|
||||
},
|
||||
Selector: config.NodePortService.Spec.Selector,
|
||||
},
|
||||
}
|
||||
|
||||
createdService := config.CreateService(svc)
|
||||
|
||||
err := framework.WaitForServiceEndpointsNum(f.ClientSet, config.Namespace, secondNodePortSvcName, len(config.EndpointPods), time.Second, wait.ForeverTestTimeout)
|
||||
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", secondNodePortSvcName, config.Namespace)
|
||||
|
||||
var httpPort int
|
||||
for _, p := range createdService.Spec.Ports {
|
||||
switch p.Protocol {
|
||||
case v1.ProtocolTCP:
|
||||
httpPort = int(p.NodePort)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return createdService, httpPort
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user