mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	Merge pull request #46197 from xiangpengzhao/fix-allocate-clusterip
Automatic merge from submit-queue (batch tested with PRs 47850, 47835, 46197, 47250, 48284) Allocate clusterIP when change service type from ExternalName to ClusterIP **What this PR does / why we need it**: **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #35354 #46190 **Special notes for your reviewer**: /cc @smarterclayton @thockin **Release note**: ```release-note NONE ```
This commit is contained in:
		| @@ -225,7 +225,6 @@ func assertFilesContain(fileNames []string, fileDir string, pod *v1.Pod, client | ||||
| } | ||||
|  | ||||
| func validateDNSResults(f *framework.Framework, pod *v1.Pod, fileNames []string) { | ||||
|  | ||||
| 	By("submitting the pod to kubernetes") | ||||
| 	podClient := f.ClientSet.Core().Pods(f.Namespace.Name) | ||||
| 	defer func() { | ||||
| @@ -254,7 +253,6 @@ func validateDNSResults(f *framework.Framework, pod *v1.Pod, fileNames []string) | ||||
| } | ||||
|  | ||||
| func validateTargetedProbeOutput(f *framework.Framework, pod *v1.Pod, fileNames []string, value string) { | ||||
|  | ||||
| 	By("submitting the pod to kubernetes") | ||||
| 	podClient := f.ClientSet.Core().Pods(f.Namespace.Name) | ||||
| 	defer func() { | ||||
| @@ -401,6 +399,10 @@ var _ = framework.KubeDescribe("DNS", func() { | ||||
| 	}) | ||||
|  | ||||
| 	It("should provide DNS for ExternalName services", func() { | ||||
| 		// TODO(xiangpengzhao): allow AWS when pull-kubernetes-e2e-kops-aws and pull-kubernetes-e2e-gce-etcd3 | ||||
| 		// have the same "service-cluster-ip-range". See: https://github.com/kubernetes/kubernetes/issues/47224 | ||||
| 		framework.SkipUnlessProviderIs("gce") | ||||
|  | ||||
| 		// Create a test ExternalName service. | ||||
| 		By("Creating a test externalName service") | ||||
| 		serviceName := "dns-test-service-3" | ||||
| @@ -446,7 +448,7 @@ var _ = framework.KubeDescribe("DNS", func() { | ||||
| 		By("changing the service to type=ClusterIP") | ||||
| 		_, err = framework.UpdateService(f.ClientSet, f.Namespace.Name, serviceName, func(s *v1.Service) { | ||||
| 			s.Spec.Type = v1.ServiceTypeClusterIP | ||||
| 			s.Spec.ClusterIP = "127.1.2.3" | ||||
| 			s.Spec.ClusterIP = "10.0.0.123" | ||||
| 			s.Spec.Ports = []v1.ServicePort{ | ||||
| 				{Port: 80, Name: "http", Protocol: "TCP"}, | ||||
| 			} | ||||
| @@ -461,6 +463,6 @@ var _ = framework.KubeDescribe("DNS", func() { | ||||
| 		By("creating a third pod to probe DNS") | ||||
| 		pod3 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, true) | ||||
|  | ||||
| 		validateTargetedProbeOutput(f, pod3, []string{wheezyFileName, jessieFileName}, "127.1.2.3") | ||||
| 		validateTargetedProbeOutput(f, pod3, []string{wheezyFileName, jessieFileName}, "10.0.0.123") | ||||
| 	}) | ||||
| }) | ||||
|   | ||||
| @@ -35,6 +35,7 @@ import ( | ||||
| 	"k8s.io/apimachinery/pkg/util/sets" | ||||
| 	"k8s.io/apimachinery/pkg/util/uuid" | ||||
| 	"k8s.io/apimachinery/pkg/util/wait" | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset" | ||||
| 	"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" | ||||
| 	"k8s.io/kubernetes/pkg/client/retry" | ||||
| @@ -177,6 +178,31 @@ func (j *ServiceTestJig) CreateUDPServiceOrFail(namespace string, tweak func(svc | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // CreateExternalNameServiceOrFail creates a new ExternalName type Service based on the jig's defaults. | ||||
| // Callers can provide a function to tweak the Service object before it is created. | ||||
| func (j *ServiceTestJig) CreateExternalNameServiceOrFail(namespace string, tweak func(svc *v1.Service)) *v1.Service { | ||||
| 	svc := &v1.Service{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Namespace: namespace, | ||||
| 			Name:      j.Name, | ||||
| 			Labels:    j.Labels, | ||||
| 		}, | ||||
| 		Spec: v1.ServiceSpec{ | ||||
| 			Selector:     j.Labels, | ||||
| 			ExternalName: "foo.example.com", | ||||
| 			Type:         v1.ServiceTypeExternalName, | ||||
| 		}, | ||||
| 	} | ||||
| 	if tweak != nil { | ||||
| 		tweak(svc) | ||||
| 	} | ||||
| 	result, err := j.Client.Core().Services(namespace).Create(svc) | ||||
| 	if err != nil { | ||||
| 		Failf("Failed to create ExternalName Service %q: %v", svc.Name, err) | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| func (j *ServiceTestJig) ChangeServiceType(namespace, name string, newType v1.ServiceType, timeout time.Duration) { | ||||
| 	ingressIP := "" | ||||
| 	svc := j.UpdateServiceOrFail(namespace, name, func(s *v1.Service) { | ||||
| @@ -373,8 +399,22 @@ func (j *ServiceTestJig) SanityCheckService(svc *v1.Service, svcType v1.ServiceT | ||||
| 	if svc.Spec.Type != svcType { | ||||
| 		Failf("unexpected Spec.Type (%s) for service, expected %s", svc.Spec.Type, svcType) | ||||
| 	} | ||||
|  | ||||
| 	if svcType != v1.ServiceTypeExternalName { | ||||
| 		if svc.Spec.ExternalName != "" { | ||||
| 			Failf("unexpected Spec.ExternalName (%s) for service, expected empty", svc.Spec.ExternalName) | ||||
| 		} | ||||
| 		if svc.Spec.ClusterIP != api.ClusterIPNone && svc.Spec.ClusterIP == "" { | ||||
| 			Failf("didn't get ClusterIP for non-ExternamName service") | ||||
| 		} | ||||
| 	} else { | ||||
| 		if svc.Spec.ClusterIP != "" { | ||||
| 			Failf("unexpected Spec.ClusterIP (%s) for ExternamName service, expected empty", svc.Spec.ClusterIP) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	expectNodePorts := false | ||||
| 	if svcType != v1.ServiceTypeClusterIP { | ||||
| 	if svcType != v1.ServiceTypeClusterIP && svcType != v1.ServiceTypeExternalName { | ||||
| 		expectNodePorts = true | ||||
| 	} | ||||
| 	for i, port := range svc.Spec.Ports { | ||||
|   | ||||
| @@ -789,6 +789,101 @@ var _ = framework.KubeDescribe("Services", func() { | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	It("should be able to change the type from ExternalName to ClusterIP", func() { | ||||
| 		serviceName := "externalname-service" | ||||
| 		ns := f.Namespace.Name | ||||
| 		jig := framework.NewServiceTestJig(cs, serviceName) | ||||
|  | ||||
| 		By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) | ||||
| 		externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) | ||||
| 		defer func() { | ||||
| 			framework.Logf("Cleaning up the ExternalName to ClusterIP test service") | ||||
| 			err := cs.Core().Services(ns).Delete(serviceName, nil) | ||||
| 			Expect(err).NotTo(HaveOccurred()) | ||||
| 		}() | ||||
| 		jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) | ||||
| 		By("changing the ExternalName service to type=ClusterIP") | ||||
| 		clusterIPService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { | ||||
| 			s.Spec.Type = v1.ServiceTypeClusterIP | ||||
| 			s.Spec.ExternalName = "" | ||||
| 			s.Spec.Ports = []v1.ServicePort{ | ||||
| 				{Port: 80, Name: "http", Protocol: "TCP"}, | ||||
| 			} | ||||
| 		}) | ||||
| 		jig.SanityCheckService(clusterIPService, v1.ServiceTypeClusterIP) | ||||
| 	}) | ||||
|  | ||||
| 	It("should be able to change the type from ExternalName to NodePort", func() { | ||||
| 		serviceName := "externalname-service" | ||||
| 		ns := f.Namespace.Name | ||||
| 		jig := framework.NewServiceTestJig(cs, serviceName) | ||||
|  | ||||
| 		By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) | ||||
| 		externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) | ||||
| 		defer func() { | ||||
| 			framework.Logf("Cleaning up the ExternalName to NodePort test service") | ||||
| 			err := cs.Core().Services(ns).Delete(serviceName, nil) | ||||
| 			Expect(err).NotTo(HaveOccurred()) | ||||
| 		}() | ||||
| 		jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) | ||||
| 		By("changing the ExternalName service to type=NodePort") | ||||
| 		nodePortService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { | ||||
| 			s.Spec.Type = v1.ServiceTypeNodePort | ||||
| 			s.Spec.ExternalName = "" | ||||
| 			s.Spec.Ports = []v1.ServicePort{ | ||||
| 				{Port: 80, Name: "http", Protocol: "TCP"}, | ||||
| 			} | ||||
| 		}) | ||||
| 		jig.SanityCheckService(nodePortService, v1.ServiceTypeNodePort) | ||||
| 	}) | ||||
|  | ||||
| 	It("should be able to change the type from ClusterIP to ExternalName", func() { | ||||
| 		serviceName := "clusterip-service" | ||||
| 		ns := f.Namespace.Name | ||||
| 		jig := framework.NewServiceTestJig(cs, serviceName) | ||||
|  | ||||
| 		By("creating a service " + serviceName + " with the type=ClusterIP in namespace " + ns) | ||||
| 		clusterIPService := jig.CreateTCPServiceOrFail(ns, nil) | ||||
| 		defer func() { | ||||
| 			framework.Logf("Cleaning up the ClusterIP to ExternalName test service") | ||||
| 			err := cs.Core().Services(ns).Delete(serviceName, nil) | ||||
| 			Expect(err).NotTo(HaveOccurred()) | ||||
| 		}() | ||||
| 		jig.SanityCheckService(clusterIPService, v1.ServiceTypeClusterIP) | ||||
| 		By("changing the ClusterIP service to type=ExternalName") | ||||
| 		externalNameService := jig.UpdateServiceOrFail(ns, clusterIPService.Name, func(s *v1.Service) { | ||||
| 			s.Spec.Type = v1.ServiceTypeExternalName | ||||
| 			s.Spec.ExternalName = "foo.example.com" | ||||
| 			s.Spec.ClusterIP = "" | ||||
| 		}) | ||||
| 		jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) | ||||
| 	}) | ||||
|  | ||||
| 	It("should be able to change the type from NodePort to ExternalName", func() { | ||||
| 		serviceName := "nodeport-service" | ||||
| 		ns := f.Namespace.Name | ||||
| 		jig := framework.NewServiceTestJig(cs, serviceName) | ||||
|  | ||||
| 		By("creating a service " + serviceName + " with the type=NodePort in namespace " + ns) | ||||
| 		nodePortService := jig.CreateTCPServiceOrFail(ns, func(svc *v1.Service) { | ||||
| 			svc.Spec.Type = v1.ServiceTypeNodePort | ||||
| 		}) | ||||
| 		defer func() { | ||||
| 			framework.Logf("Cleaning up the NodePort to ExternalName test service") | ||||
| 			err := cs.Core().Services(ns).Delete(serviceName, nil) | ||||
| 			Expect(err).NotTo(HaveOccurred()) | ||||
| 		}() | ||||
| 		jig.SanityCheckService(nodePortService, v1.ServiceTypeNodePort) | ||||
| 		By("changing the NodePort service to type=ExternalName") | ||||
| 		externalNameService := jig.UpdateServiceOrFail(ns, nodePortService.Name, func(s *v1.Service) { | ||||
| 			s.Spec.Type = v1.ServiceTypeExternalName | ||||
| 			s.Spec.ExternalName = "foo.example.com" | ||||
| 			s.Spec.ClusterIP = "" | ||||
| 			s.Spec.Ports[0].NodePort = 0 | ||||
| 		}) | ||||
| 		jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) | ||||
| 	}) | ||||
|  | ||||
| 	It("should use same NodePort with same port but different protocols", func() { | ||||
| 		serviceName := "nodeports" | ||||
| 		ns := f.Namespace.Name | ||||
| @@ -866,7 +961,7 @@ var _ = framework.KubeDescribe("Services", func() { | ||||
| 		} | ||||
| 		port := result.Spec.Ports[0] | ||||
| 		if port.NodePort == 0 { | ||||
| 			framework.Failf("got unexpected Spec.Ports[0].nodePort for new service: %v", result) | ||||
| 			framework.Failf("got unexpected Spec.Ports[0].NodePort for new service: %v", result) | ||||
| 		} | ||||
|  | ||||
| 		By("creating service " + serviceName2 + " with conflicting NodePort") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user