2015-01-13 02:11:27 +00:00
/ *
2016-08-17 04:07:17 +00:00
Copyright 2016 The Kubernetes Authors .
2015-01-13 02:11:27 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
2017-07-11 06:44:46 +00:00
package network
2015-01-13 02:11:27 +00:00
import (
2016-08-22 17:48:00 +00:00
"bytes"
2015-01-13 02:11:27 +00:00
"fmt"
2015-05-22 23:01:35 +00:00
"math/rand"
2017-09-19 21:29:29 +00:00
"net"
"strconv"
2015-03-21 00:35:43 +00:00
"strings"
2015-01-13 02:11:27 +00:00
"time"
2018-01-20 02:42:32 +00:00
compute "google.golang.org/api/compute/v1"
2017-06-22 18:24:23 +00:00
"k8s.io/api/core/v1"
2017-01-11 14:09:48 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
2017-01-27 20:42:17 +00:00
"k8s.io/apimachinery/pkg/util/intstr"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/util/wait"
2017-06-23 20:56:37 +00:00
clientset "k8s.io/client-go/kubernetes"
2016-12-14 03:39:50 +00:00
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
2016-12-29 23:35:47 +00:00
"k8s.io/kubernetes/pkg/cloudprovider"
2016-05-06 20:15:49 +00:00
"k8s.io/kubernetes/pkg/controller/endpoint"
2016-04-07 17:21:31 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2017-08-29 08:32:08 +00:00
imageutils "k8s.io/kubernetes/test/utils/image"
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
2016-07-26 12:28:12 +00:00
)
2016-01-30 04:35:32 +00:00
2018-03-14 00:45:34 +00:00
const (
defaultServeHostnameServicePort = 80
defaultServeHostnameServiceName = "svc-hostname"
)
var (
defaultServeHostnameService = v1 . Service {
ObjectMeta : metav1 . ObjectMeta {
Name : defaultServeHostnameServiceName ,
} ,
Spec : v1 . ServiceSpec {
Ports : [ ] v1 . ServicePort { {
Port : int32 ( defaultServeHostnameServicePort ) ,
TargetPort : intstr . FromInt ( 9376 ) ,
Protocol : "TCP" ,
} } ,
Selector : map [ string ] string {
"name" : defaultServeHostnameServiceName ,
} ,
} ,
}
)
func getServeHostnameService ( name string ) * v1 . Service {
svc := defaultServeHostnameService . DeepCopy ( )
svc . ObjectMeta . Name = name
svc . Spec . Selector [ "name" ] = name
return svc
}
2017-07-24 09:43:54 +00:00
var _ = SIGDescribe ( "Services" , func ( ) {
2016-04-07 17:21:31 +00:00
f := framework . NewDefaultFramework ( "services" )
2015-05-28 02:32:27 +00:00
2016-10-19 13:55:39 +00:00
var cs clientset . Interface
2016-11-18 20:55:17 +00:00
var internalClientset internalclientset . Interface
2016-09-07 02:48:04 +00:00
serviceLBNames := [ ] string { }
2015-02-05 13:50:07 +00:00
BeforeEach ( func ( ) {
2016-10-19 13:55:39 +00:00
cs = f . ClientSet
2016-11-18 20:55:17 +00:00
internalClientset = f . InternalClientset
2015-05-08 17:07:32 +00:00
} )
2016-09-07 02:48:04 +00:00
AfterEach ( func ( ) {
if CurrentGinkgoTestDescription ( ) . Failed {
2016-12-29 23:35:47 +00:00
framework . DescribeSvc ( f . Namespace . Name )
2016-09-07 02:48:04 +00:00
}
for _ , lb := range serviceLBNames {
2018-06-06 16:29:12 +00:00
framework . Logf ( "cleaning load balancer resource for %s" , lb )
framework . CleanupServiceResources ( cs , lb , framework . TestContext . CloudConfig . Region , framework . TestContext . CloudConfig . Zone )
2016-09-07 02:48:04 +00:00
}
//reset serviceLBNames
serviceLBNames = [ ] string { }
} )
2015-05-14 01:50:28 +00:00
// TODO: We get coverage of TCP/UDP and multi-port services through the DNS test. We should have a simpler test for multi-port TCP here.
2015-09-29 21:30:45 +00:00
2017-10-20 20:29:25 +00:00
/ *
2018-02-28 02:27:34 +00:00
Release : v1 .9
Testname : Kubernetes Service
Description : By default when a kubernetes cluster is running there MUST be a ‘ kubernetes ’ service running in the cluster .
2017-10-20 20:29:25 +00:00
* /
2017-10-26 17:46:09 +00:00
framework . ConformanceIt ( "should provide secure master service " , func ( ) {
2017-08-13 09:07:29 +00:00
_ , err := cs . CoreV1 ( ) . Services ( metav1 . NamespaceDefault ) . Get ( "kubernetes" , metav1 . GetOptions { } )
2015-05-13 23:13:19 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-02-05 14:05:45 +00:00
} )
2015-02-09 20:37:56 +00:00
2017-10-20 20:29:25 +00:00
/ *
2018-02-28 02:27:34 +00:00
Release : v1 .9
Testname : Service , endpoints
Description : Create a service with a endpoint without any Pods , the service MUST run and show empty endpoints . Add a pod to the service and the service MUST validate to show all the endpoints for the ports exposed by the Pod . Add another Pod then the list of all Ports exposed by both the Pods MUST be valid and have corresponding service endpoint . Once the second Pod is deleted then set of endpoint MUST be validated to show only ports from the first container that are exposed . Once both pods are deleted the endpoints from the service MUST be empty .
2017-10-20 20:29:25 +00:00
* /
2017-10-26 17:46:09 +00:00
framework . ConformanceIt ( "should serve a basic endpoint from pods " , func ( ) {
2015-02-18 19:30:18 +00:00
serviceName := "endpoint-test2"
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2018-02-03 04:06:52 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2015-02-09 20:37:56 +00:00
labels := map [ string ] string {
"foo" : "bar" ,
"baz" : "blah" ,
}
2015-09-29 21:30:45 +00:00
By ( "creating service " + serviceName + " in namespace " + ns )
2015-02-09 20:37:56 +00:00
defer func ( ) {
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2015-02-09 20:37:56 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
2018-02-03 04:06:52 +00:00
ports := [ ] v1 . ServicePort { {
Port : 80 ,
TargetPort : intstr . FromInt ( 80 ) ,
} }
_ , err := jig . CreateServiceWithServicePort ( labels , ns , ports )
2015-02-09 20:37:56 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { } )
2015-02-09 20:37:56 +00:00
2015-09-29 21:30:45 +00:00
names := map [ string ] bool { }
2015-02-09 20:37:56 +00:00
defer func ( ) {
2015-09-29 21:30:45 +00:00
for name := range names {
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Pods ( ns ) . Delete ( name , nil )
2015-02-09 20:37:56 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
} ( )
2015-09-29 21:30:45 +00:00
name1 := "pod1"
name2 := "pod2"
2015-02-23 22:57:08 +00:00
2016-12-29 23:35:47 +00:00
framework . CreatePodOrFail ( cs , ns , name1 , labels , [ ] v1 . ContainerPort { { ContainerPort : 80 } } )
2015-09-29 21:30:45 +00:00
names [ name1 ] = true
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { name1 : { 80 } } )
2015-02-09 20:37:56 +00:00
2016-12-29 23:35:47 +00:00
framework . CreatePodOrFail ( cs , ns , name2 , labels , [ ] v1 . ContainerPort { { ContainerPort : 80 } } )
2015-09-29 21:30:45 +00:00
names [ name2 ] = true
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { name1 : { 80 } , name2 : { 80 } } )
2015-02-09 20:37:56 +00:00
2016-12-29 23:35:47 +00:00
framework . DeletePodOrFail ( cs , ns , name1 )
2015-09-29 21:30:45 +00:00
delete ( names , name1 )
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { name2 : { 80 } } )
2015-02-09 20:37:56 +00:00
2016-12-29 23:35:47 +00:00
framework . DeletePodOrFail ( cs , ns , name2 )
2015-09-29 21:30:45 +00:00
delete ( names , name2 )
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { } )
2015-06-16 01:40:11 +00:00
} )
2015-05-08 17:07:32 +00:00
2017-10-20 20:29:25 +00:00
/ *
2018-02-28 02:27:34 +00:00
Release : v1 .9
Testname : Service , endpoints with multiple ports
Description : Create a service with two ports but no Pods are added to the service yet . The service MUST run and show empty set of endpoints . Add a Pod to the first port , service MUST list one endpoint for the Pod on that port . Add another Pod to the second port , service MUST list both the endpoints . Delete the first Pod and the service MUST list only the endpoint to the second Pod . Delete the second Pod and the service must now have empty set of endpoints .
2017-10-20 20:29:25 +00:00
* /
2017-10-26 17:46:09 +00:00
framework . ConformanceIt ( "should serve multiport endpoints from pods " , func ( ) {
2015-05-08 17:07:32 +00:00
// repacking functionality is intentionally not tested here - it's better to test it in an integration test.
serviceName := "multi-endpoint-test"
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2018-02-03 04:06:52 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2015-05-08 17:07:32 +00:00
defer func ( ) {
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2015-05-08 17:07:32 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
labels := map [ string ] string { "foo" : "bar" }
svc1port := "svc1"
svc2port := "svc2"
2015-09-29 21:30:45 +00:00
By ( "creating service " + serviceName + " in namespace " + ns )
2018-02-03 04:06:52 +00:00
ports := [ ] v1 . ServicePort {
{
Name : "portname1" ,
Port : 80 ,
TargetPort : intstr . FromString ( svc1port ) ,
2015-05-08 17:07:32 +00:00
} ,
2018-02-03 04:06:52 +00:00
{
Name : "portname2" ,
Port : 81 ,
TargetPort : intstr . FromString ( svc2port ) ,
2015-05-08 17:07:32 +00:00
} ,
}
2018-02-03 04:06:52 +00:00
_ , err := jig . CreateServiceWithServicePort ( labels , ns , ports )
2015-05-08 17:07:32 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
port1 := 100
port2 := 101
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { } )
2015-05-08 17:07:32 +00:00
2015-09-29 21:30:45 +00:00
names := map [ string ] bool { }
2015-05-08 17:07:32 +00:00
defer func ( ) {
2015-09-29 21:30:45 +00:00
for name := range names {
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Pods ( ns ) . Delete ( name , nil )
2015-05-08 17:07:32 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
} ( )
2016-11-18 20:55:17 +00:00
containerPorts1 := [ ] v1 . ContainerPort {
2015-05-08 17:07:32 +00:00
{
Name : svc1port ,
2016-04-27 04:35:14 +00:00
ContainerPort : int32 ( port1 ) ,
2015-05-08 17:07:32 +00:00
} ,
}
2016-11-18 20:55:17 +00:00
containerPorts2 := [ ] v1 . ContainerPort {
2015-05-08 17:07:32 +00:00
{
Name : svc2port ,
2016-04-27 04:35:14 +00:00
ContainerPort : int32 ( port2 ) ,
2015-05-08 17:07:32 +00:00
} ,
}
2015-09-29 21:30:45 +00:00
podname1 := "pod1"
podname2 := "pod2"
2016-12-29 23:35:47 +00:00
framework . CreatePodOrFail ( cs , ns , podname1 , labels , containerPorts1 )
2015-09-29 21:30:45 +00:00
names [ podname1 ] = true
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { podname1 : { port1 } } )
2015-05-08 17:07:32 +00:00
2016-12-29 23:35:47 +00:00
framework . CreatePodOrFail ( cs , ns , podname2 , labels , containerPorts2 )
2015-09-29 21:30:45 +00:00
names [ podname2 ] = true
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { podname1 : { port1 } , podname2 : { port2 } } )
2015-05-08 17:07:32 +00:00
2016-12-29 23:35:47 +00:00
framework . DeletePodOrFail ( cs , ns , podname1 )
2015-09-29 21:30:45 +00:00
delete ( names , podname1 )
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { podname2 : { port2 } } )
2015-05-08 17:07:32 +00:00
2016-12-29 23:35:47 +00:00
framework . DeletePodOrFail ( cs , ns , podname2 )
2015-09-29 21:30:45 +00:00
delete ( names , podname2 )
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { } )
2015-06-16 01:40:11 +00:00
} )
2015-03-20 21:04:41 +00:00
2016-08-17 04:07:17 +00:00
It ( "should preserve source pod IP for traffic thru service cluster IP" , func ( ) {
2017-03-31 09:50:54 +00:00
// 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 := framework . ProxyMode ( f ) ; err == nil {
if proxyMode == "userspace" {
framework . 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 )
}
2016-08-17 04:07:17 +00:00
serviceName := "sourceip-test"
ns := f . Namespace . Name
By ( "creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns )
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2016-08-17 04:07:17 +00:00
servicePort := 8080
tcpService := jig . CreateTCPServiceWithPort ( ns , nil , int32 ( servicePort ) )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeClusterIP )
2016-08-17 04:07:17 +00:00
defer func ( ) {
framework . Logf ( "Cleaning up the sourceip test service" )
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2016-08-17 04:07:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
serviceIp := tcpService . Spec . ClusterIP
framework . Logf ( "sourceip-test cluster ip: %s" , serviceIp )
By ( "Picking multiple nodes" )
2016-10-19 13:55:39 +00:00
nodes := framework . GetReadySchedulableNodesOrDie ( f . ClientSet )
2016-08-17 04:07:17 +00:00
if len ( nodes . Items ) == 1 {
framework . Skipf ( "The test requires two Ready nodes on %s, but found just one." , framework . TestContext . Provider )
}
node1 := nodes . Items [ 0 ]
node2 := nodes . Items [ 1 ]
By ( "Creating a webserver pod be part of the TCP service which echoes back source ip" )
serverPodName := "echoserver-sourceip"
2016-12-29 23:35:47 +00:00
jig . LaunchEchoserverPodOnNode ( f , node1 . Name , serverPodName )
2016-08-17 04:07:17 +00:00
defer func ( ) {
framework . Logf ( "Cleaning up the echo server pod" )
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Pods ( ns ) . Delete ( serverPodName , nil )
2016-08-17 04:07:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
2016-10-05 16:13:19 +00:00
// Waiting for service to expose endpoint.
2016-12-29 23:35:47 +00:00
framework . ValidateEndpointsOrFail ( cs , ns , serviceName , framework . PortsByPodName { serverPodName : { servicePort } } )
2016-08-17 04:07:17 +00:00
By ( "Retrieve sourceip from a pod on the same node" )
2016-10-18 13:00:38 +00:00
sourceIp1 , execPodIp1 := execSourceipTest ( f , cs , ns , node1 . Name , serviceIp , servicePort )
2016-08-17 04:07:17 +00:00
By ( "Verifying the preserved source ip" )
Expect ( sourceIp1 ) . To ( Equal ( execPodIp1 ) )
By ( "Retrieve sourceip from a pod on a different node" )
2016-10-18 13:00:38 +00:00
sourceIp2 , execPodIp2 := execSourceipTest ( f , cs , ns , node2 . Name , serviceIp , servicePort )
2016-08-17 04:07:17 +00:00
By ( "Verifying the preserved source ip" )
Expect ( sourceIp2 ) . To ( Equal ( execPodIp2 ) )
} )
2015-07-16 12:38:47 +00:00
It ( "should be able to up and down services" , func ( ) {
2016-01-30 04:35:32 +00:00
// TODO: use the ServiceTestJig here
2016-04-07 17:21:31 +00:00
// this test uses framework.NodeSSHHosts that does not work if a Node only reports LegacyHostIP
framework . SkipUnlessProviderIs ( framework . ProvidersWithSSH ... )
2017-05-01 13:57:50 +00:00
// this test does not work if the Node does not support SSH Key
framework . SkipUnlessSSHKeyPresent ( )
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2018-03-14 00:45:34 +00:00
numPods , servicePort := 3 , defaultServeHostnameServicePort
2015-07-16 12:38:47 +00:00
2016-02-03 19:06:08 +00:00
By ( "creating service1 in namespace " + ns )
2018-03-14 00:45:34 +00:00
podNames1 , svc1IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( "service1" ) , ns , numPods )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-03 19:06:08 +00:00
By ( "creating service2 in namespace " + ns )
2018-03-14 00:45:34 +00:00
podNames2 , svc2IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( "service2" ) , ns , numPods )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-10-18 13:00:38 +00:00
hosts , err := framework . NodeSSHHosts ( cs )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( hosts ) == 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "No ssh-able nodes" )
2015-07-16 12:38:47 +00:00
}
host := hosts [ 0 ]
2016-02-03 19:06:08 +00:00
By ( "verifying service1 is up" )
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
2016-02-03 19:06:08 +00:00
By ( "verifying service2 is up" )
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-07-16 12:38:47 +00:00
// Stop service 1 and make sure it is gone.
2016-02-03 19:06:08 +00:00
By ( "stopping service1" )
2018-05-17 15:27:44 +00:00
framework . ExpectNoError ( framework . StopServeHostnameService ( f . ClientSet , ns , "service1" ) )
2015-07-16 12:38:47 +00:00
2016-02-03 19:06:08 +00:00
By ( "verifying service1 is not up" )
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceDown ( cs , host , svc1IP , servicePort ) )
2016-02-03 19:06:08 +00:00
By ( "verifying service2 is still up" )
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-07-16 12:38:47 +00:00
// Start another service and verify both are up.
2016-02-03 19:06:08 +00:00
By ( "creating service3 in namespace " + ns )
2018-03-14 00:45:34 +00:00
podNames3 , svc3IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( "service3" ) , ns , numPods )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if svc2IP == svc3IP {
2016-04-07 17:21:31 +00:00
framework . Failf ( "service IPs conflict: %v" , svc2IP )
2015-07-16 12:38:47 +00:00
}
2016-02-03 19:06:08 +00:00
By ( "verifying service2 is still up" )
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-07-16 12:38:47 +00:00
2016-02-03 19:06:08 +00:00
By ( "verifying service3 is up" )
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames3 , svc3IP , servicePort ) )
2015-07-16 12:38:47 +00:00
} )
2015-12-18 18:41:33 +00:00
It ( "should work after restarting kube-proxy [Disruptive]" , func ( ) {
2016-01-30 04:35:32 +00:00
// TODO: use the ServiceTestJig here
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" )
2015-07-16 12:38:47 +00:00
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2018-03-14 00:45:34 +00:00
numPods , servicePort := 3 , defaultServeHostnameServicePort
2015-07-16 12:38:47 +00:00
2015-09-29 21:30:45 +00:00
svc1 := "service1"
svc2 := "service2"
2016-12-29 23:35:47 +00:00
defer func ( ) {
2018-05-17 15:27:44 +00:00
framework . ExpectNoError ( framework . StopServeHostnameService ( f . ClientSet , ns , svc1 ) )
2016-12-29 23:35:47 +00:00
} ( )
2018-03-14 00:45:34 +00:00
podNames1 , svc1IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( svc1 ) , ns , numPods )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-09-29 21:30:45 +00:00
2016-12-29 23:35:47 +00:00
defer func ( ) {
2018-05-17 15:27:44 +00:00
framework . ExpectNoError ( framework . StopServeHostnameService ( f . ClientSet , ns , svc2 ) )
2016-12-29 23:35:47 +00:00
} ( )
2018-03-14 00:45:34 +00:00
podNames2 , svc2IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( svc2 ) , ns , numPods )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if svc1IP == svc2IP {
2016-04-07 17:21:31 +00:00
framework . Failf ( "VIPs conflict: %v" , svc1IP )
2015-07-16 12:38:47 +00:00
}
2016-10-18 13:00:38 +00:00
hosts , err := framework . NodeSSHHosts ( cs )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( hosts ) == 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "No ssh-able nodes" )
2015-07-16 12:38:47 +00:00
}
host := hosts [ 0 ]
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-07-16 12:38:47 +00:00
2016-08-31 23:44:30 +00:00
By ( fmt . Sprintf ( "Restarting kube-proxy on %v" , host ) )
2016-04-07 17:21:31 +00:00
if err := framework . RestartKubeProxy ( host ) ; err != nil {
framework . Failf ( "error restarting kube-proxy: %v" , err )
2015-07-16 12:38:47 +00:00
}
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-09-29 21:30:45 +00:00
By ( "Removing iptable rules" )
2016-04-07 17:21:31 +00:00
result , err := framework . SSH ( `
2016-02-06 05:12:33 +00:00
sudo iptables - t nat - F KUBE - SERVICES || true ;
sudo iptables - t nat - F KUBE - PORTALS - HOST || true ;
2016-04-07 17:21:31 +00:00
sudo iptables - t nat - F KUBE - PORTALS - CONTAINER || true ` , host , framework . TestContext . Provider )
2015-11-20 21:54:34 +00:00
if err != nil || result . Code != 0 {
2016-04-07 17:21:31 +00:00
framework . LogSSHResult ( result )
framework . Failf ( "couldn't remove iptable rules: %v" , err )
2015-07-16 12:38:47 +00:00
}
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-07-16 12:38:47 +00:00
} )
2015-12-18 18:41:33 +00:00
It ( "should work after restarting apiserver [Disruptive]" , func ( ) {
2016-01-30 04:35:32 +00:00
// TODO: use the ServiceTestJig here
2016-05-26 16:42:47 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" )
2015-07-16 12:38:47 +00:00
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2015-07-16 12:38:47 +00:00
numPods , servicePort := 3 , 80
2016-11-18 20:55:17 +00:00
defer func ( ) {
2018-05-17 15:27:44 +00:00
framework . ExpectNoError ( framework . StopServeHostnameService ( f . ClientSet , ns , "service1" ) )
2016-11-18 20:55:17 +00:00
} ( )
2018-03-14 00:45:34 +00:00
podNames1 , svc1IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( "service1" ) , ns , numPods )
2015-11-04 19:18:35 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-07-16 12:38:47 +00:00
2016-10-18 13:00:38 +00:00
hosts , err := framework . NodeSSHHosts ( cs )
2015-07-16 12:38:47 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( hosts ) == 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "No ssh-able nodes" )
2015-07-16 12:38:47 +00:00
}
host := hosts [ 0 ]
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
2015-07-16 12:38:47 +00:00
// Restart apiserver
2016-08-31 23:44:30 +00:00
By ( "Restarting apiserver" )
2018-03-09 18:56:46 +00:00
if err := framework . RestartApiserver ( cs ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "error restarting apiserver: %v" , err )
2015-07-16 12:38:47 +00:00
}
2016-08-31 23:44:30 +00:00
By ( "Waiting for apiserver to come up by polling /healthz" )
2016-10-18 13:00:38 +00:00
if err := framework . WaitForApiserverUp ( cs ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "error while waiting for apiserver up: %v" , err )
2015-07-16 12:38:47 +00:00
}
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
2015-07-16 12:38:47 +00:00
// Create a new service and check if it's not reusing IP.
2016-11-18 20:55:17 +00:00
defer func ( ) {
2018-05-17 15:27:44 +00:00
framework . ExpectNoError ( framework . StopServeHostnameService ( f . ClientSet , ns , "service2" ) )
2016-11-18 20:55:17 +00:00
} ( )
2018-03-14 00:45:34 +00:00
podNames2 , svc2IP , err := framework . StartServeHostnameService ( cs , internalClientset , getServeHostnameService ( "service2" ) , ns , numPods )
2015-11-04 19:18:35 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-07-16 12:38:47 +00:00
if svc1IP == svc2IP {
2016-04-07 17:21:31 +00:00
framework . Failf ( "VIPs conflict: %v" , svc1IP )
2015-07-16 12:38:47 +00:00
}
2016-12-29 23:35:47 +00:00
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames1 , svc1IP , servicePort ) )
framework . ExpectNoError ( framework . VerifyServeHostnameServiceUp ( cs , ns , host , podNames2 , svc2IP , servicePort ) )
2015-07-16 12:38:47 +00:00
} )
2015-12-16 22:35:10 +00:00
// TODO: Run this test against the userspace proxy and nodes
// configured with a default deny firewall to validate that the
// proxy whitelists NodePort traffic.
2015-05-20 15:59:34 +00:00
It ( "should be able to create a functioning NodePort service" , func ( ) {
2016-01-30 04:35:32 +00:00
serviceName := "nodeport-test"
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2015-05-20 15:59:34 +00:00
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
nodeIP := framework . PickNodeIP ( jig . Client ) // for later
2015-05-22 23:01:35 +00:00
By ( "creating service " + serviceName + " with type=NodePort in namespace " + ns )
2016-11-18 20:55:17 +00:00
service := jig . CreateTCPServiceOrFail ( ns , func ( svc * v1 . Service ) {
svc . Spec . Type = v1 . ServiceTypeNodePort
2016-01-30 04:35:32 +00:00
} )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( service , v1 . ServiceTypeNodePort )
2016-04-27 04:35:14 +00:00
nodePort := int ( service . Spec . Ports [ 0 ] . NodePort )
2015-05-22 23:01:35 +00:00
By ( "creating pod to be part of service " + serviceName )
2016-01-30 04:35:32 +00:00
jig . RunOrFail ( ns , nil )
2015-05-22 23:01:35 +00:00
By ( "hitting the pod through the service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableHTTP ( nodeIP , nodePort , framework . KubeProxyLagTimeout )
2015-06-17 22:26:14 +00:00
2015-12-05 00:35:02 +00:00
By ( "verifying the node port is locked" )
2016-10-18 13:00:38 +00:00
hostExec := framework . LaunchHostExecPod ( f . ClientSet , f . Namespace . Name , "hostexec" )
2016-01-27 21:42:00 +00:00
// Even if the node-ip:node-port check above passed, this hostexec pod
// might fall on a node with a laggy kube-proxy.
cmd := fmt . Sprintf ( ` for i in $(seq 1 300); do if ss -ant46 'sport = :%d' | grep ^LISTEN; then exit 0; fi; sleep 1; done; exit 1 ` , nodePort )
2016-04-07 17:21:31 +00:00
stdout , err := framework . RunHostCmd ( hostExec . Namespace , hostExec . Name , cmd )
2015-11-12 23:30:21 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "expected node port %d to be in use, stdout: %v. err: %v" , nodePort , stdout , err )
2015-06-17 22:26:14 +00:00
}
2015-05-22 23:01:35 +00:00
} )
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
2017-11-15 13:35:44 +00:00
It ( "should be able to change the type and ports of a service [Slow] [DisabledForLargeClusters]" , func ( ) {
2015-09-29 21:30:45 +00:00
// requires cloud load-balancer support
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" , "aws" )
2015-07-09 16:47:12 +00:00
2016-04-07 17:21:31 +00:00
loadBalancerSupportsUDP := ! framework . ProviderIs ( "aws" )
2016-02-10 02:59:35 +00:00
2016-12-29 23:35:47 +00:00
loadBalancerLagTimeout := framework . LoadBalancerLagTimeoutDefault
2016-04-07 17:21:31 +00:00
if framework . ProviderIs ( "aws" ) {
2016-12-29 23:35:47 +00:00
loadBalancerLagTimeout = framework . LoadBalancerLagTimeoutAWS
2016-02-10 14:31:52 +00:00
}
2016-12-29 23:35:47 +00:00
loadBalancerCreateTimeout := framework . LoadBalancerCreateTimeoutDefault
if nodes := framework . GetReadySchedulableNodesOrDie ( cs ) ; len ( nodes . Items ) > framework . LargeClusterMinNodesNumber {
loadBalancerCreateTimeout = framework . LoadBalancerCreateTimeoutLarge
2016-08-02 10:30:14 +00:00
}
2016-02-10 14:31:52 +00:00
2016-01-30 04:35:32 +00:00
// This test is more monolithic than we'd like because LB turnup can be
// very slow, so we lumped all the tests into one LB lifecycle.
2015-05-22 23:01:35 +00:00
2016-01-30 04:35:32 +00:00
serviceName := "mutability-test"
ns1 := f . Namespace . Name // LB1 in ns1 on TCP
2016-04-07 17:21:31 +00:00
framework . Logf ( "namespace for TCP test: %s" , ns1 )
2015-05-22 23:01:35 +00:00
2016-01-30 04:35:32 +00:00
By ( "creating a second namespace" )
2016-02-06 05:38:52 +00:00
namespacePtr , err := f . CreateNamespace ( "services" , nil )
2015-05-20 15:59:34 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-30 04:35:32 +00:00
ns2 := namespacePtr . Name // LB2 in ns2 on UDP
2016-04-07 17:21:31 +00:00
framework . Logf ( "namespace for UDP test: %s" , ns2 )
2015-05-22 23:01:35 +00:00
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
nodeIP := framework . PickNodeIP ( jig . Client ) // for later
2016-01-30 04:35:32 +00:00
// Test TCP and UDP Services. Services with the same name in different
// namespaces should get different node ports and load balancers.
By ( "creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns1 )
tcpService := jig . CreateTCPServiceOrFail ( ns1 , nil )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeClusterIP )
2016-01-30 04:35:32 +00:00
By ( "creating a UDP service " + serviceName + " with type=ClusterIP in namespace " + ns2 )
udpService := jig . CreateUDPServiceOrFail ( ns2 , nil )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeClusterIP )
2016-01-30 04:35:32 +00:00
By ( "verifying that TCP and UDP use the same port" )
if tcpService . Spec . Ports [ 0 ] . Port != udpService . Spec . Ports [ 0 ] . Port {
2016-04-07 17:21:31 +00:00
framework . Failf ( "expected to use the same port for TCP and UDP" )
2015-05-20 15:59:34 +00:00
}
2016-04-27 04:35:14 +00:00
svcPort := int ( tcpService . Spec . Ports [ 0 ] . Port )
2016-04-07 17:21:31 +00:00
framework . Logf ( "service port (TCP and UDP): %d" , svcPort )
2016-01-30 04:35:32 +00:00
By ( "creating a pod to be part of the TCP service " + serviceName )
jig . RunOrFail ( ns1 , nil )
2015-05-20 15:59:34 +00:00
2016-01-30 04:35:32 +00:00
By ( "creating a pod to be part of the UDP service " + serviceName )
jig . RunOrFail ( ns2 , nil )
2015-05-22 23:01:35 +00:00
2016-01-30 04:35:32 +00:00
// Change the services to NodePort.
2016-02-04 17:28:48 +00:00
By ( "changing the TCP service to type=NodePort" )
2016-11-18 20:55:17 +00:00
tcpService = jig . UpdateServiceOrFail ( ns1 , tcpService . Name , func ( s * v1 . Service ) {
s . Spec . Type = v1 . ServiceTypeNodePort
2015-07-10 20:38:37 +00:00
} )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeNodePort )
2016-04-27 04:35:14 +00:00
tcpNodePort := int ( tcpService . Spec . Ports [ 0 ] . NodePort )
2016-04-07 17:21:31 +00:00
framework . Logf ( "TCP node port: %d" , tcpNodePort )
2015-05-22 23:01:35 +00:00
2016-02-04 17:28:48 +00:00
By ( "changing the UDP service to type=NodePort" )
2016-11-18 20:55:17 +00:00
udpService = jig . UpdateServiceOrFail ( ns2 , udpService . Name , func ( s * v1 . Service ) {
s . Spec . Type = v1 . ServiceTypeNodePort
2016-01-30 04:35:32 +00:00
} )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeNodePort )
2016-04-27 04:35:14 +00:00
udpNodePort := int ( udpService . Spec . Ports [ 0 ] . NodePort )
2016-04-07 17:21:31 +00:00
framework . Logf ( "UDP node port: %d" , udpNodePort )
2015-09-29 21:30:45 +00:00
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableHTTP ( nodeIP , tcpNodePort , framework . KubeProxyLagTimeout )
2016-01-27 21:42:00 +00:00
2016-01-30 04:35:32 +00:00
By ( "hitting the UDP service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableUDP ( nodeIP , udpNodePort , framework . KubeProxyLagTimeout )
2016-01-30 04:35:32 +00:00
// Change the services to LoadBalancer.
2016-04-06 22:12:31 +00:00
// Here we test that LoadBalancers can receive static IP addresses. This isn't
// necessary, but is an additional feature this monolithic test checks.
2016-01-30 04:35:32 +00:00
requestedIP := ""
2016-02-04 18:51:41 +00:00
staticIPName := ""
2016-04-07 17:21:31 +00:00
if framework . ProviderIs ( "gce" , "gke" ) {
2016-01-30 04:35:32 +00:00
By ( "creating a static load balancer IP" )
2016-04-07 17:21:31 +00:00
staticIPName = fmt . Sprintf ( "e2e-external-lb-test-%s" , framework . RunId )
2018-01-20 02:42:32 +00:00
gceCloud , err := framework . GetGCECloud ( )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = gceCloud . ReserveRegionAddress ( & compute . Address { Name : staticIPName } , gceCloud . Region ( ) )
2016-01-30 04:35:32 +00:00
defer func ( ) {
2016-02-04 18:51:41 +00:00
if staticIPName != "" {
// Release GCE static IP - this is not kube-managed and will not be automatically released.
2018-01-20 02:42:32 +00:00
if err := gceCloud . DeleteRegionAddress ( staticIPName , gceCloud . Region ( ) ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "failed to release static IP %s: %v" , staticIPName , err )
2016-02-04 18:51:41 +00:00
}
}
2016-01-30 04:35:32 +00:00
} ( )
2017-06-05 21:24:29 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2018-01-20 02:42:32 +00:00
reservedAddr , err := gceCloud . GetRegionAddress ( staticIPName , gceCloud . Region ( ) )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
requestedIP = reservedAddr . Address
2016-04-07 17:21:31 +00:00
framework . Logf ( "Allocated static load balancer IP: %s" , requestedIP )
2016-01-27 21:42:00 +00:00
}
2015-05-22 23:01:35 +00:00
2016-02-04 17:28:48 +00:00
By ( "changing the TCP service to type=LoadBalancer" )
2016-11-18 20:55:17 +00:00
tcpService = jig . UpdateServiceOrFail ( ns1 , tcpService . Name , func ( s * v1 . Service ) {
2016-01-30 04:35:32 +00:00
s . Spec . LoadBalancerIP = requestedIP // will be "" if not applicable
2016-11-18 20:55:17 +00:00
s . Spec . Type = v1 . ServiceTypeLoadBalancer
2015-07-10 20:38:37 +00:00
} )
2015-05-22 23:01:35 +00:00
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
By ( "changing the UDP service to type=LoadBalancer" )
2016-11-18 20:55:17 +00:00
udpService = jig . UpdateServiceOrFail ( ns2 , udpService . Name , func ( s * v1 . Service ) {
s . Spec . Type = v1 . ServiceTypeLoadBalancer
2016-02-10 02:59:35 +00:00
} )
}
2018-08-04 04:36:48 +00:00
serviceLBNames = append ( serviceLBNames , cloudprovider . DefaultLoadBalancerName ( tcpService ) )
2016-09-07 02:48:04 +00:00
if loadBalancerSupportsUDP {
2018-08-04 04:36:48 +00:00
serviceLBNames = append ( serviceLBNames , cloudprovider . DefaultLoadBalancerName ( udpService ) )
2016-09-07 02:48:04 +00:00
}
2015-05-22 23:01:35 +00:00
2016-02-04 17:28:48 +00:00
By ( "waiting for the TCP service to have a load balancer" )
2016-01-30 04:35:32 +00:00
// Wait for the load balancer to be created asynchronously
2016-08-02 10:30:14 +00:00
tcpService = jig . WaitForLoadBalancerOrFail ( ns1 , tcpService . Name , loadBalancerCreateTimeout )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeLoadBalancer )
2016-04-27 04:35:14 +00:00
if int ( tcpService . Spec . Ports [ 0 ] . NodePort ) != tcpNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "TCP Spec.Ports[0].NodePort changed (%d -> %d) when not expected" , tcpNodePort , tcpService . Spec . Ports [ 0 ] . NodePort )
2015-05-22 23:01:35 +00:00
}
2016-12-29 23:35:47 +00:00
if requestedIP != "" && framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) != requestedIP {
framework . Failf ( "unexpected TCP Status.LoadBalancer.Ingress (expected %s, got %s)" , requestedIP , framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) )
2015-05-22 23:01:35 +00:00
}
2016-12-29 23:35:47 +00:00
tcpIngressIP := framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] )
2016-04-07 17:21:31 +00:00
framework . Logf ( "TCP load balancer: %s" , tcpIngressIP )
2016-01-30 04:35:32 +00:00
2016-04-07 17:21:31 +00:00
if framework . ProviderIs ( "gce" , "gke" ) {
2016-02-04 18:51:41 +00:00
// Do this as early as possible, which overrides the `defer` above.
// This is mostly out of fear of leaking the IP in a timeout case
// (as of this writing we're not 100% sure where the leaks are
// coming from, so this is first-aid rather than surgery).
By ( "demoting the static IP to ephemeral" )
if staticIPName != "" {
2018-01-20 02:42:32 +00:00
gceCloud , err := framework . GetGCECloud ( )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-04 18:51:41 +00:00
// Deleting it after it is attached "demotes" it to an
// ephemeral IP, which can be auto-released.
2018-01-20 02:42:32 +00:00
if err := gceCloud . DeleteRegionAddress ( staticIPName , gceCloud . Region ( ) ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "failed to release static IP %s: %v" , staticIPName , err )
2016-02-04 18:51:41 +00:00
}
staticIPName = ""
}
}
2016-02-10 02:59:35 +00:00
var udpIngressIP string
if loadBalancerSupportsUDP {
By ( "waiting for the UDP service to have a load balancer" )
// 2nd one should be faster since they ran in parallel.
2016-08-02 10:30:14 +00:00
udpService = jig . WaitForLoadBalancerOrFail ( ns2 , udpService . Name , loadBalancerCreateTimeout )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeLoadBalancer )
2016-04-27 04:35:14 +00:00
if int ( udpService . Spec . Ports [ 0 ] . NodePort ) != udpNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "UDP Spec.Ports[0].NodePort changed (%d -> %d) when not expected" , udpNodePort , udpService . Spec . Ports [ 0 ] . NodePort )
2016-02-10 02:59:35 +00:00
}
2016-12-29 23:35:47 +00:00
udpIngressIP = framework . GetIngressPoint ( & udpService . Status . LoadBalancer . Ingress [ 0 ] )
2016-04-07 17:21:31 +00:00
framework . Logf ( "UDP load balancer: %s" , udpIngressIP )
2015-09-29 21:30:45 +00:00
2016-02-10 02:59:35 +00:00
By ( "verifying that TCP and UDP use different load balancers" )
if tcpIngressIP == udpIngressIP {
2016-12-29 23:35:47 +00:00
framework . Failf ( "Load balancers are not different: %s" , framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) )
2016-02-10 02:59:35 +00:00
}
2015-05-22 23:01:35 +00:00
}
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableHTTP ( nodeIP , tcpNodePort , framework . KubeProxyLagTimeout )
2016-01-30 04:35:32 +00:00
By ( "hitting the UDP service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableUDP ( nodeIP , udpNodePort , framework . KubeProxyLagTimeout )
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's LoadBalancer" )
jig . TestReachableHTTP ( tcpIngressIP , svcPort , loadBalancerLagTimeout )
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
By ( "hitting the UDP service's LoadBalancer" )
jig . TestReachableUDP ( udpIngressIP , svcPort , loadBalancerLagTimeout )
}
2016-01-30 04:35:32 +00:00
// Change the services' node ports.
2016-02-04 17:28:48 +00:00
By ( "changing the TCP service's NodePort" )
2016-01-30 04:35:32 +00:00
tcpService = jig . ChangeServiceNodePortOrFail ( ns1 , tcpService . Name , tcpNodePort )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeLoadBalancer )
2016-01-30 04:35:32 +00:00
tcpNodePortOld := tcpNodePort
2016-04-27 04:35:14 +00:00
tcpNodePort = int ( tcpService . Spec . Ports [ 0 ] . NodePort )
2016-01-30 04:35:32 +00:00
if tcpNodePort == tcpNodePortOld {
2016-04-07 17:21:31 +00:00
framework . Failf ( "TCP Spec.Ports[0].NodePort (%d) did not change" , tcpNodePort )
2015-05-22 23:01:35 +00:00
}
2016-12-29 23:35:47 +00:00
if framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) != tcpIngressIP {
framework . Failf ( "TCP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected" , tcpIngressIP , framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) )
2015-05-22 23:01:35 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "TCP node port: %d" , tcpNodePort )
2016-01-30 04:35:32 +00:00
2016-02-04 17:28:48 +00:00
By ( "changing the UDP service's NodePort" )
2016-01-30 04:35:32 +00:00
udpService = jig . ChangeServiceNodePortOrFail ( ns2 , udpService . Name , udpNodePort )
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeLoadBalancer )
2016-02-10 02:59:35 +00:00
} else {
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeNodePort )
2016-02-10 02:59:35 +00:00
}
2016-01-30 04:35:32 +00:00
udpNodePortOld := udpNodePort
2016-04-27 04:35:14 +00:00
udpNodePort = int ( udpService . Spec . Ports [ 0 ] . NodePort )
2016-01-30 04:35:32 +00:00
if udpNodePort == udpNodePortOld {
2016-04-07 17:21:31 +00:00
framework . Failf ( "UDP Spec.Ports[0].NodePort (%d) did not change" , udpNodePort )
2015-05-22 23:01:35 +00:00
}
2016-12-29 23:35:47 +00:00
if loadBalancerSupportsUDP && framework . GetIngressPoint ( & udpService . Status . LoadBalancer . Ingress [ 0 ] ) != udpIngressIP {
framework . Failf ( "UDP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected" , udpIngressIP , framework . GetIngressPoint ( & udpService . Status . LoadBalancer . Ingress [ 0 ] ) )
2015-05-22 23:01:35 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "UDP node port: %d" , udpNodePort )
2015-07-09 17:31:30 +00:00
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's new NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableHTTP ( nodeIP , tcpNodePort , framework . KubeProxyLagTimeout )
2016-01-27 21:42:00 +00:00
2016-01-30 04:35:32 +00:00
By ( "hitting the UDP service's new NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableUDP ( nodeIP , udpNodePort , framework . KubeProxyLagTimeout )
2016-01-27 21:42:00 +00:00
2016-01-30 04:35:32 +00:00
By ( "checking the old TCP NodePort is closed" )
2016-12-29 23:35:47 +00:00
jig . TestNotReachableHTTP ( nodeIP , tcpNodePortOld , framework . KubeProxyLagTimeout )
2015-05-22 23:01:35 +00:00
2016-01-30 04:35:32 +00:00
By ( "checking the old UDP NodePort is closed" )
2016-12-29 23:35:47 +00:00
jig . TestNotReachableUDP ( nodeIP , udpNodePortOld , framework . KubeProxyLagTimeout )
2015-09-29 21:30:45 +00:00
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's LoadBalancer" )
jig . TestReachableHTTP ( tcpIngressIP , svcPort , loadBalancerLagTimeout )
2015-09-29 21:30:45 +00:00
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
By ( "hitting the UDP service's LoadBalancer" )
jig . TestReachableUDP ( udpIngressIP , svcPort , loadBalancerLagTimeout )
}
2016-01-30 04:35:32 +00:00
// Change the services' main ports.
By ( "changing the TCP service's port" )
2016-11-18 20:55:17 +00:00
tcpService = jig . UpdateServiceOrFail ( ns1 , tcpService . Name , func ( s * v1 . Service ) {
2016-01-30 04:35:32 +00:00
s . Spec . Ports [ 0 ] . Port ++
} )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeLoadBalancer )
2016-01-30 04:35:32 +00:00
svcPortOld := svcPort
2016-04-27 04:35:14 +00:00
svcPort = int ( tcpService . Spec . Ports [ 0 ] . Port )
2016-01-30 04:35:32 +00:00
if svcPort == svcPortOld {
2016-04-07 17:21:31 +00:00
framework . Failf ( "TCP Spec.Ports[0].Port (%d) did not change" , svcPort )
2016-01-30 04:35:32 +00:00
}
2016-04-27 04:35:14 +00:00
if int ( tcpService . Spec . Ports [ 0 ] . NodePort ) != tcpNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "TCP Spec.Ports[0].NodePort (%d) changed" , tcpService . Spec . Ports [ 0 ] . NodePort )
2015-09-29 21:30:45 +00:00
}
2016-12-29 23:35:47 +00:00
if framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) != tcpIngressIP {
framework . Failf ( "TCP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected" , tcpIngressIP , framework . GetIngressPoint ( & tcpService . Status . LoadBalancer . Ingress [ 0 ] ) )
2016-01-30 04:35:32 +00:00
}
2015-09-29 21:30:45 +00:00
2016-01-30 04:35:32 +00:00
By ( "changing the UDP service's port" )
2016-11-18 20:55:17 +00:00
udpService = jig . UpdateServiceOrFail ( ns2 , udpService . Name , func ( s * v1 . Service ) {
2016-01-30 04:35:32 +00:00
s . Spec . Ports [ 0 ] . Port ++
2015-10-13 18:28:36 +00:00
} )
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeLoadBalancer )
2016-02-10 02:59:35 +00:00
} else {
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeNodePort )
2016-02-10 02:59:35 +00:00
}
2016-04-27 04:35:14 +00:00
if int ( udpService . Spec . Ports [ 0 ] . Port ) != svcPort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "UDP Spec.Ports[0].Port (%d) did not change" , udpService . Spec . Ports [ 0 ] . Port )
2015-10-13 18:28:36 +00:00
}
2016-04-27 04:35:14 +00:00
if int ( udpService . Spec . Ports [ 0 ] . NodePort ) != udpNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "UDP Spec.Ports[0].NodePort (%d) changed" , udpService . Spec . Ports [ 0 ] . NodePort )
2016-01-30 04:35:32 +00:00
}
2016-12-29 23:35:47 +00:00
if loadBalancerSupportsUDP && framework . GetIngressPoint ( & udpService . Status . LoadBalancer . Ingress [ 0 ] ) != udpIngressIP {
framework . Failf ( "UDP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected" , udpIngressIP , framework . GetIngressPoint ( & udpService . Status . LoadBalancer . Ingress [ 0 ] ) )
2016-01-30 04:35:32 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "service port (TCP and UDP): %d" , svcPort )
2016-02-04 18:51:41 +00:00
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableHTTP ( nodeIP , tcpNodePort , framework . KubeProxyLagTimeout )
2016-01-30 04:35:32 +00:00
By ( "hitting the UDP service's NodePort" )
2016-12-29 23:35:47 +00:00
jig . TestReachableUDP ( nodeIP , udpNodePort , framework . KubeProxyLagTimeout )
2016-01-30 04:35:32 +00:00
By ( "hitting the TCP service's LoadBalancer" )
jig . TestReachableHTTP ( tcpIngressIP , svcPort , loadBalancerCreateTimeout ) // this may actually recreate the LB
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
By ( "hitting the UDP service's LoadBalancer" )
jig . TestReachableUDP ( udpIngressIP , svcPort , loadBalancerCreateTimeout ) // this may actually recreate the LB)
}
2016-01-30 04:35:32 +00:00
// Change the services back to ClusterIP.
2016-02-04 17:28:48 +00:00
By ( "changing TCP service back to type=ClusterIP" )
2016-11-18 20:55:17 +00:00
tcpService = jig . UpdateServiceOrFail ( ns1 , tcpService . Name , func ( s * v1 . Service ) {
s . Spec . Type = v1 . ServiceTypeClusterIP
2016-01-30 04:35:32 +00:00
s . Spec . Ports [ 0 ] . NodePort = 0
} )
// Wait for the load balancer to be destroyed asynchronously
2016-08-02 10:30:14 +00:00
tcpService = jig . WaitForLoadBalancerDestroyOrFail ( ns1 , tcpService . Name , tcpIngressIP , svcPort , loadBalancerCreateTimeout )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( tcpService , v1 . ServiceTypeClusterIP )
2016-01-30 04:35:32 +00:00
2016-02-04 17:28:48 +00:00
By ( "changing UDP service back to type=ClusterIP" )
2016-11-18 20:55:17 +00:00
udpService = jig . UpdateServiceOrFail ( ns2 , udpService . Name , func ( s * v1 . Service ) {
s . Spec . Type = v1 . ServiceTypeClusterIP
2016-01-30 04:35:32 +00:00
s . Spec . Ports [ 0 ] . NodePort = 0
} )
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
// Wait for the load balancer to be destroyed asynchronously
2016-08-02 10:30:14 +00:00
udpService = jig . WaitForLoadBalancerDestroyOrFail ( ns2 , udpService . Name , udpIngressIP , svcPort , loadBalancerCreateTimeout )
2016-11-18 20:55:17 +00:00
jig . SanityCheckService ( udpService , v1 . ServiceTypeClusterIP )
2016-02-10 02:59:35 +00:00
}
2015-10-13 18:28:36 +00:00
2016-01-30 04:35:32 +00:00
By ( "checking the TCP NodePort is closed" )
2016-12-29 23:35:47 +00:00
jig . TestNotReachableHTTP ( nodeIP , tcpNodePort , framework . KubeProxyLagTimeout )
2015-05-22 23:01:35 +00:00
2016-01-30 04:35:32 +00:00
By ( "checking the UDP NodePort is closed" )
2016-12-29 23:35:47 +00:00
jig . TestNotReachableUDP ( nodeIP , udpNodePort , framework . KubeProxyLagTimeout )
2016-01-30 04:35:32 +00:00
By ( "checking the TCP LoadBalancer is closed" )
jig . TestNotReachableHTTP ( tcpIngressIP , svcPort , loadBalancerLagTimeout )
2016-02-10 02:59:35 +00:00
if loadBalancerSupportsUDP {
By ( "checking the UDP LoadBalancer is closed" )
jig . TestNotReachableUDP ( udpIngressIP , svcPort , loadBalancerLagTimeout )
}
2015-05-22 23:01:35 +00:00
} )
2017-11-02 03:26:52 +00:00
It ( "should be able to update NodePorts with two same port numbers but different protocols" , func ( ) {
serviceName := "nodeport-update-service"
ns := f . Namespace . Name
jig := framework . NewServiceTestJig ( cs , serviceName )
By ( "creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns )
tcpService := jig . CreateTCPServiceOrFail ( ns , nil )
defer func ( ) {
framework . Logf ( "Cleaning up the updating NodePorts test service" )
2017-11-12 11:00:21 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2017-11-02 03:26:52 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
jig . SanityCheckService ( tcpService , v1 . ServiceTypeClusterIP )
svcPort := int ( tcpService . Spec . Ports [ 0 ] . Port )
framework . Logf ( "service port TCP: %d" , svcPort )
// Change the services to NodePort and add a UDP port.
By ( "changing the TCP service to type=NodePort and add a UDP port" )
newService := jig . UpdateServiceOrFail ( ns , tcpService . Name , func ( s * v1 . Service ) {
s . Spec . Type = v1 . ServiceTypeNodePort
s . Spec . Ports = [ ] v1 . ServicePort {
{
Name : "tcp-port" ,
Port : 80 ,
Protocol : v1 . ProtocolTCP ,
} ,
{
Name : "udp-port" ,
Port : 80 ,
Protocol : v1 . ProtocolUDP ,
} ,
}
} )
jig . SanityCheckService ( newService , v1 . ServiceTypeNodePort )
if len ( newService . Spec . Ports ) != 2 {
framework . Failf ( "new service should have two Ports" )
}
for _ , port := range newService . Spec . Ports {
if port . NodePort == 0 {
framework . Failf ( "new service failed to allocate NodePort for Port %s" , port . Name )
}
framework . Logf ( "new service allocates NodePort %d for Port %s" , port . NodePort , port . Name )
}
} )
2017-05-22 06:23:23 +00:00
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 )
2017-06-15 03:48:26 +00:00
defer func ( ) {
framework . Logf ( "Cleaning up the ExternalName to ClusterIP test service" )
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2017-06-15 03:48:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
2017-05-22 06:23:23 +00:00
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 )
2017-06-15 03:48:26 +00:00
defer func ( ) {
framework . Logf ( "Cleaning up the ExternalName to NodePort test service" )
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2017-06-15 03:48:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
2017-05-22 06:23:23 +00:00
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 )
} )
2017-06-15 03:48:26 +00:00
It ( "should be able to change the type from ClusterIP to ExternalName" , func ( ) {
serviceName := "clusterip-service"
2017-05-22 06:23:23 +00:00
ns := f . Namespace . Name
jig := framework . NewServiceTestJig ( cs , serviceName )
2017-06-15 03:48:26 +00:00
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" )
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2017-06-15 03:48:26 +00:00
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 = ""
} )
2017-05-22 06:23:23 +00:00
jig . SanityCheckService ( externalNameService , v1 . ServiceTypeExternalName )
2017-06-15 03:48:26 +00:00
} )
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
2017-05-22 06:23:23 +00:00
} )
2017-06-15 03:48:26 +00:00
defer func ( ) {
framework . Logf ( "Cleaning up the NodePort to ExternalName test service" )
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Services ( ns ) . Delete ( serviceName , nil )
2017-06-15 03:48:26 +00:00
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 )
2017-05-22 06:23:23 +00:00
} )
2016-08-20 00:45:09 +00:00
It ( "should use same NodePort with same port but different protocols" , func ( ) {
serviceName := "nodeports"
ns := f . Namespace . Name
2016-12-29 23:35:47 +00:00
t := framework . NewServerTest ( cs , ns , serviceName )
2016-08-20 00:45:09 +00:00
defer func ( ) {
defer GinkgoRecover ( )
errs := t . Cleanup ( )
if len ( errs ) != 0 {
framework . Failf ( "errors in cleanup: %v" , errs )
}
} ( )
By ( "creating service " + serviceName + " with same NodePort but different protocols in namespace " + ns )
2016-11-18 20:55:17 +00:00
service := & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-08-20 00:45:09 +00:00
Name : t . ServiceName ,
Namespace : t . Namespace ,
} ,
2016-11-18 20:55:17 +00:00
Spec : v1 . ServiceSpec {
2016-08-20 00:45:09 +00:00
Selector : t . Labels ,
2016-11-18 20:55:17 +00:00
Type : v1 . ServiceTypeNodePort ,
Ports : [ ] v1 . ServicePort {
2016-08-20 00:45:09 +00:00
{
Name : "tcp-port" ,
Port : 53 ,
2016-11-18 20:55:17 +00:00
Protocol : v1 . ProtocolTCP ,
2016-08-20 00:45:09 +00:00
} ,
{
Name : "udp-port" ,
Port : 53 ,
2016-11-18 20:55:17 +00:00
Protocol : v1 . ProtocolUDP ,
2016-08-20 00:45:09 +00:00
} ,
} ,
} ,
}
result , err := t . CreateService ( service )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( result . Spec . Ports ) != 2 {
framework . Failf ( "got unexpected len(Spec.Ports) for new service: %v" , result )
}
if result . Spec . Ports [ 0 ] . NodePort != result . Spec . Ports [ 1 ] . NodePort {
framework . Failf ( "should use same NodePort for new service: %v" , result )
}
} )
2015-05-22 23:01:35 +00:00
It ( "should prevent NodePort collisions" , func ( ) {
2016-01-30 04:35:32 +00:00
// TODO: use the ServiceTestJig here
2015-09-29 21:30:45 +00:00
baseName := "nodeport-collision-"
serviceName1 := baseName + "1"
serviceName2 := baseName + "2"
ns := f . Namespace . Name
2015-05-22 23:01:35 +00:00
2016-12-29 23:35:47 +00:00
t := framework . NewServerTest ( cs , ns , serviceName1 )
2015-05-22 23:01:35 +00:00
defer func ( ) {
defer GinkgoRecover ( )
errs := t . Cleanup ( )
if len ( errs ) != 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "errors in cleanup: %v" , errs )
2015-05-22 23:01:35 +00:00
}
} ( )
2015-09-29 21:30:45 +00:00
By ( "creating service " + serviceName1 + " with type NodePort in namespace " + ns )
2015-05-22 23:01:35 +00:00
service := t . BuildServiceSpec ( )
2016-11-18 20:55:17 +00:00
service . Spec . Type = v1 . ServiceTypeNodePort
2015-05-22 23:01:35 +00:00
result , err := t . CreateService ( service )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
if result . Spec . Type != v1 . ServiceTypeNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected Spec.Type for new service: %v" , result )
2015-05-22 23:01:35 +00:00
}
if len ( result . Spec . Ports ) != 1 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected len(Spec.Ports) for new service: %v" , result )
2015-05-22 23:01:35 +00:00
}
port := result . Spec . Ports [ 0 ]
if port . NodePort == 0 {
2017-05-22 06:23:23 +00:00
framework . Failf ( "got unexpected Spec.Ports[0].NodePort for new service: %v" , result )
2015-05-22 23:01:35 +00:00
}
2015-09-29 21:30:45 +00:00
By ( "creating service " + serviceName2 + " with conflicting NodePort" )
2015-05-22 23:01:35 +00:00
service2 := t . BuildServiceSpec ( )
service2 . Name = serviceName2
2016-11-18 20:55:17 +00:00
service2 . Spec . Type = v1 . ServiceTypeNodePort
2015-05-22 23:01:35 +00:00
service2 . Spec . Ports [ 0 ] . NodePort = port . NodePort
result2 , err := t . CreateService ( service2 )
if err == nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Created service with conflicting NodePort: %v" , result2 )
2015-05-22 23:01:35 +00:00
}
2016-01-20 05:13:39 +00:00
expectedErr := fmt . Sprintf ( "%d.*port is already allocated" , port . NodePort )
Expect ( fmt . Sprintf ( "%v" , err ) ) . To ( MatchRegexp ( expectedErr ) )
2015-05-22 23:01:35 +00:00
2015-09-29 21:30:45 +00:00
By ( "deleting service " + serviceName1 + " to release NodePort" )
err = t . DeleteService ( serviceName1 )
2015-05-22 23:01:35 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
By ( "creating service " + serviceName2 + " with no-longer-conflicting NodePort" )
_ , err = t . CreateService ( service2 )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} )
It ( "should check NodePort out-of-range" , func ( ) {
2016-01-30 04:35:32 +00:00
// TODO: use the ServiceTestJig here
2015-05-22 23:01:35 +00:00
serviceName := "nodeport-range-test"
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2015-05-22 23:01:35 +00:00
2016-12-29 23:35:47 +00:00
t := framework . NewServerTest ( cs , ns , serviceName )
2015-05-20 15:59:34 +00:00
defer func ( ) {
defer GinkgoRecover ( )
2015-05-22 23:01:35 +00:00
errs := t . Cleanup ( )
if len ( errs ) != 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "errors in cleanup: %v" , errs )
2015-05-22 23:01:35 +00:00
}
2015-05-20 15:59:34 +00:00
} ( )
2015-05-22 23:01:35 +00:00
service := t . BuildServiceSpec ( )
2016-11-18 20:55:17 +00:00
service . Spec . Type = v1 . ServiceTypeNodePort
2015-05-22 23:01:35 +00:00
By ( "creating service " + serviceName + " with type NodePort in namespace " + ns )
service , err := t . CreateService ( service )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
if service . Spec . Type != v1 . ServiceTypeNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected Spec.Type for new service: %v" , service )
2015-05-22 23:01:35 +00:00
}
if len ( service . Spec . Ports ) != 1 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected len(Spec.Ports) for new service: %v" , service )
2015-05-22 23:01:35 +00:00
}
port := service . Spec . Ports [ 0 ]
if port . NodePort == 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected Spec.Ports[0].nodePort for new service: %v" , service )
2015-05-22 23:01:35 +00:00
}
2016-12-29 23:35:47 +00:00
if ! framework . ServiceNodePortRange . Contains ( int ( port . NodePort ) ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected (out-of-range) port for new service: %v" , service )
2015-05-20 15:59:34 +00:00
}
2015-05-22 23:01:35 +00:00
outOfRangeNodePort := 0
2016-02-11 03:42:17 +00:00
rand . Seed ( time . Now ( ) . UTC ( ) . UnixNano ( ) )
2015-05-22 23:01:35 +00:00
for {
outOfRangeNodePort = 1 + rand . Intn ( 65535 )
2016-12-29 23:35:47 +00:00
if ! framework . ServiceNodePortRange . Contains ( outOfRangeNodePort ) {
2015-05-20 15:59:34 +00:00
break
}
}
2015-05-22 23:01:35 +00:00
By ( fmt . Sprintf ( "changing service " + serviceName + " to out-of-range NodePort %d" , outOfRangeNodePort ) )
2016-12-29 23:35:47 +00:00
result , err := framework . UpdateService ( cs , ns , serviceName , func ( s * v1 . Service ) {
2016-04-27 04:35:14 +00:00
s . Spec . Ports [ 0 ] . NodePort = int32 ( outOfRangeNodePort )
2015-07-10 20:38:37 +00:00
} )
2015-05-22 23:01:35 +00:00
if err == nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "failed to prevent update of service with out-of-range NodePort: %v" , result )
2015-05-22 23:01:35 +00:00
}
2016-01-20 05:13:39 +00:00
expectedErr := fmt . Sprintf ( "%d.*port is not in the valid range" , outOfRangeNodePort )
Expect ( fmt . Sprintf ( "%v" , err ) ) . To ( MatchRegexp ( expectedErr ) )
2015-05-22 23:01:35 +00:00
By ( "deleting original service " + serviceName )
err = t . DeleteService ( serviceName )
2015-05-20 15:59:34 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-05-22 23:01:35 +00:00
By ( fmt . Sprintf ( "creating service " + serviceName + " with out-of-range NodePort %d" , outOfRangeNodePort ) )
service = t . BuildServiceSpec ( )
2016-11-18 20:55:17 +00:00
service . Spec . Type = v1 . ServiceTypeNodePort
2016-04-27 04:35:14 +00:00
service . Spec . Ports [ 0 ] . NodePort = int32 ( outOfRangeNodePort )
2015-05-22 23:01:35 +00:00
service , err = t . CreateService ( service )
if err == nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "failed to prevent create of service with out-of-range NodePort (%d): %v" , outOfRangeNodePort , service )
2015-05-22 23:01:35 +00:00
}
2016-01-20 05:13:39 +00:00
Expect ( fmt . Sprintf ( "%v" , err ) ) . To ( MatchRegexp ( expectedErr ) )
2015-05-22 23:01:35 +00:00
} )
It ( "should release NodePorts on delete" , func ( ) {
2016-01-30 04:35:32 +00:00
// TODO: use the ServiceTestJig here
2015-05-22 23:01:35 +00:00
serviceName := "nodeport-reuse"
2015-09-29 21:30:45 +00:00
ns := f . Namespace . Name
2015-05-22 23:01:35 +00:00
2016-12-29 23:35:47 +00:00
t := framework . NewServerTest ( cs , ns , serviceName )
2015-05-22 23:01:35 +00:00
defer func ( ) {
defer GinkgoRecover ( )
errs := t . Cleanup ( )
if len ( errs ) != 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "errors in cleanup: %v" , errs )
2015-05-22 23:01:35 +00:00
}
} ( )
service := t . BuildServiceSpec ( )
2016-11-18 20:55:17 +00:00
service . Spec . Type = v1 . ServiceTypeNodePort
2015-05-22 23:01:35 +00:00
By ( "creating service " + serviceName + " with type NodePort in namespace " + ns )
service , err := t . CreateService ( service )
2015-05-20 15:59:34 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-05-22 23:01:35 +00:00
2016-11-18 20:55:17 +00:00
if service . Spec . Type != v1 . ServiceTypeNodePort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected Spec.Type for new service: %v" , service )
2015-05-22 23:01:35 +00:00
}
if len ( service . Spec . Ports ) != 1 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected len(Spec.Ports) for new service: %v" , service )
2015-05-20 15:59:34 +00:00
}
2015-05-22 23:01:35 +00:00
port := service . Spec . Ports [ 0 ]
if port . NodePort == 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected Spec.Ports[0].nodePort for new service: %v" , service )
2015-05-20 15:59:34 +00:00
}
2016-12-29 23:35:47 +00:00
if ! framework . ServiceNodePortRange . Contains ( int ( port . NodePort ) ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "got unexpected (out-of-range) port for new service: %v" , service )
2015-05-22 23:01:35 +00:00
}
2015-06-17 22:26:14 +00:00
nodePort := port . NodePort
2015-05-22 23:01:35 +00:00
By ( "deleting original service " + serviceName )
err = t . DeleteService ( serviceName )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-10-18 13:00:38 +00:00
hostExec := framework . LaunchHostExecPod ( f . ClientSet , f . Namespace . Name , "hostexec" )
2015-11-12 23:30:21 +00:00
cmd := fmt . Sprintf ( ` ! ss -ant46 'sport = :%d' | tail -n +2 | grep LISTEN ` , nodePort )
2016-02-02 19:34:36 +00:00
var stdout string
2016-12-29 23:35:47 +00:00
if pollErr := wait . PollImmediate ( framework . Poll , framework . KubeProxyLagTimeout , func ( ) ( bool , error ) {
2016-02-02 19:34:36 +00:00
var err error
2016-04-07 17:21:31 +00:00
stdout , err = framework . RunHostCmd ( hostExec . Namespace , hostExec . Name , cmd )
2016-02-02 19:34:36 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "expected node port (%d) to not be in use, stdout: %v" , nodePort , stdout )
2016-02-02 19:34:36 +00:00
return false , nil
}
return true , nil
} ) ; pollErr != nil {
2016-12-29 23:35:47 +00:00
framework . Failf ( "expected node port (%d) to not be in use in %v, stdout: %v" , nodePort , framework . KubeProxyLagTimeout , stdout )
2015-06-17 22:26:14 +00:00
}
By ( fmt . Sprintf ( "creating service " + serviceName + " with same NodePort %d" , nodePort ) )
2015-05-22 23:01:35 +00:00
service = t . BuildServiceSpec ( )
2016-11-18 20:55:17 +00:00
service . Spec . Type = v1 . ServiceTypeNodePort
2015-06-17 22:26:14 +00:00
service . Spec . Ports [ 0 ] . NodePort = nodePort
2015-05-22 23:01:35 +00:00
service , err = t . CreateService ( service )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-05-20 15:59:34 +00:00
} )
2016-05-06 20:15:49 +00:00
It ( "should create endpoints for unready pods" , func ( ) {
2017-01-03 13:00:15 +00:00
serviceName := "tolerate-unready"
2016-05-06 20:15:49 +00:00
ns := f . Namespace . Name
2016-12-29 23:35:47 +00:00
t := framework . NewServerTest ( cs , ns , serviceName )
2016-05-06 20:15:49 +00:00
defer func ( ) {
defer GinkgoRecover ( )
errs := t . Cleanup ( )
if len ( errs ) != 0 {
framework . Failf ( "errors in cleanup: %v" , errs )
}
} ( )
2016-12-29 23:35:47 +00:00
t . Name = "slow-terminating-unready-pod"
2017-08-29 08:32:08 +00:00
t . Image = imageutils . GetE2EImage ( imageutils . Netexec )
2017-01-03 13:00:15 +00:00
port := 80
terminateSeconds := int64 ( 600 )
service := & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2017-01-03 13:00:15 +00:00
Name : t . ServiceName ,
Namespace : t . Namespace ,
Annotations : map [ string ] string { endpoint . TolerateUnreadyEndpointsAnnotation : "true" } ,
} ,
Spec : v1 . ServiceSpec {
Selector : t . Labels ,
Ports : [ ] v1 . ServicePort { {
Name : "http" ,
Port : int32 ( port ) ,
TargetPort : intstr . FromInt ( port ) ,
} } ,
} ,
}
2016-12-29 23:35:47 +00:00
rcSpec := framework . RcByNameContainer ( t . Name , 1 , t . Image , t . Labels , v1 . Container {
2017-01-03 13:00:15 +00:00
Args : [ ] string { fmt . Sprintf ( "--http-port=%d" , port ) } ,
2016-12-29 23:35:47 +00:00
Name : t . Name ,
Image : t . Image ,
2017-01-03 13:00:15 +00:00
Ports : [ ] v1 . ContainerPort { { ContainerPort : int32 ( port ) , Protocol : v1 . ProtocolTCP } } ,
2016-11-18 20:55:17 +00:00
ReadinessProbe : & v1 . Probe {
Handler : v1 . Handler {
Exec : & v1 . ExecAction {
2016-05-06 20:15:49 +00:00
Command : [ ] string { "/bin/false" } ,
} ,
} ,
} ,
2017-01-03 13:00:15 +00:00
Lifecycle : & v1 . Lifecycle {
PreStop : & v1 . Handler {
Exec : & v1 . ExecAction {
Command : [ ] string { "/bin/sleep" , fmt . Sprintf ( "%d" , terminateSeconds ) } ,
} ,
} ,
} ,
2016-11-01 00:26:04 +00:00
} , nil )
2017-01-03 13:00:15 +00:00
rcSpec . Spec . Template . Spec . TerminationGracePeriodSeconds = & terminateSeconds
2016-05-06 20:15:49 +00:00
2017-01-03 13:00:15 +00:00
By ( fmt . Sprintf ( "creating RC %v with selectors %v" , rcSpec . Name , rcSpec . Spec . Selector ) )
2016-12-29 23:35:47 +00:00
_ , err := t . CreateRC ( rcSpec )
2016-12-08 01:51:35 +00:00
framework . ExpectNoError ( err )
2016-05-06 20:15:49 +00:00
By ( fmt . Sprintf ( "creating Service %v with selectors %v" , service . Name , service . Spec . Selector ) )
_ , err = t . CreateService ( service )
2016-12-08 01:51:35 +00:00
framework . ExpectNoError ( err )
2016-05-06 20:15:49 +00:00
2016-12-29 23:35:47 +00:00
By ( "Verifying pods for RC " + t . Name )
framework . ExpectNoError ( framework . VerifyPods ( t . Client , t . Namespace , t . Name , false , 1 ) )
2016-05-06 20:15:49 +00:00
2017-05-02 01:47:59 +00:00
svcName := fmt . Sprintf ( "%v.%v.svc.cluster.local" , serviceName , f . Namespace . Name )
2017-01-03 13:00:15 +00:00
By ( "Waiting for endpoints of Service with DNS name " + svcName )
2016-05-06 20:15:49 +00:00
2016-12-29 23:35:47 +00:00
execPodName := framework . CreateExecPodOrFail ( f . ClientSet , f . Namespace . Name , "execpod-" , nil )
2017-01-03 13:00:15 +00:00
cmd := fmt . Sprintf ( "wget -qO- http://%s:%d/" , svcName , port )
2016-05-06 20:15:49 +00:00
var stdout string
2016-12-29 23:35:47 +00:00
if pollErr := wait . PollImmediate ( framework . Poll , framework . KubeProxyLagTimeout , func ( ) ( bool , error ) {
2016-05-06 20:15:49 +00:00
var err error
2016-06-15 11:14:05 +00:00
stdout , err = framework . RunHostCmd ( f . Namespace . Name , execPodName , cmd )
2016-05-06 20:15:49 +00:00
if err != nil {
2016-12-29 23:35:47 +00:00
framework . Logf ( "expected un-ready endpoint for Service %v, stdout: %v, err %v" , t . Name , stdout , err )
2016-05-06 20:15:49 +00:00
return false , nil
}
return true , nil
} ) ; pollErr != nil {
2016-12-29 23:35:47 +00:00
framework . Failf ( "expected un-ready endpoint for Service %v within %v, stdout: %v" , t . Name , framework . KubeProxyLagTimeout , stdout )
2016-05-06 20:15:49 +00:00
}
2017-01-03 13:00:15 +00:00
2017-05-02 01:47:59 +00:00
By ( "Scaling down replication controller to zero" )
2018-03-29 20:16:03 +00:00
framework . ScaleRC ( f . ClientSet , f . ScalesGetter , t . Namespace , rcSpec . Name , 0 , false )
2017-01-03 13:00:15 +00:00
By ( "Update service to not tolerate unready services" )
2016-12-29 23:35:47 +00:00
_ , err = framework . UpdateService ( f . ClientSet , t . Namespace , t . ServiceName , func ( s * v1 . Service ) {
2017-01-03 13:00:15 +00:00
s . ObjectMeta . Annotations [ endpoint . TolerateUnreadyEndpointsAnnotation ] = "false"
} )
framework . ExpectNoError ( err )
By ( "Check if pod is unreachable" )
cmd = fmt . Sprintf ( "wget -qO- -T 2 http://%s:%d/; test \"$?\" -eq \"1\"" , svcName , port )
2016-12-29 23:35:47 +00:00
if pollErr := wait . PollImmediate ( framework . Poll , framework . KubeProxyLagTimeout , func ( ) ( bool , error ) {
2017-01-03 13:00:15 +00:00
var err error
stdout , err = framework . RunHostCmd ( f . Namespace . Name , execPodName , cmd )
if err != nil {
2016-12-29 23:35:47 +00:00
framework . Logf ( "expected un-ready endpoint for Service %v, stdout: %v, err %v" , t . Name , stdout , err )
2017-01-03 13:00:15 +00:00
return false , nil
}
return true , nil
} ) ; pollErr != nil {
2016-12-29 23:35:47 +00:00
framework . Failf ( "expected un-ready endpoint for Service %v within %v, stdout: %v" , t . Name , framework . KubeProxyLagTimeout , stdout )
2017-01-03 13:00:15 +00:00
}
By ( "Update service to tolerate unready services again" )
2016-12-29 23:35:47 +00:00
_ , err = framework . UpdateService ( f . ClientSet , t . Namespace , t . ServiceName , func ( s * v1 . Service ) {
2017-01-03 13:00:15 +00:00
s . ObjectMeta . Annotations [ endpoint . TolerateUnreadyEndpointsAnnotation ] = "true"
} )
framework . ExpectNoError ( err )
By ( "Check if terminating pod is available through service" )
cmd = fmt . Sprintf ( "wget -qO- http://%s:%d/" , svcName , port )
2016-12-29 23:35:47 +00:00
if pollErr := wait . PollImmediate ( framework . Poll , framework . KubeProxyLagTimeout , func ( ) ( bool , error ) {
2017-01-03 13:00:15 +00:00
var err error
stdout , err = framework . RunHostCmd ( f . Namespace . Name , execPodName , cmd )
if err != nil {
2016-12-29 23:35:47 +00:00
framework . Logf ( "expected un-ready endpoint for Service %v, stdout: %v, err %v" , t . Name , stdout , err )
2017-01-03 13:00:15 +00:00
return false , nil
}
return true , nil
} ) ; pollErr != nil {
2016-12-29 23:35:47 +00:00
framework . Failf ( "expected un-ready endpoint for Service %v within %v, stdout: %v" , t . Name , framework . KubeProxyLagTimeout , stdout )
2017-01-03 13:00:15 +00:00
}
By ( "Remove pods immediately" )
label := labels . SelectorFromSet ( labels . Set ( t . Labels ) )
2017-01-22 03:36:02 +00:00
options := metav1 . ListOptions { LabelSelector : label . String ( ) }
2017-10-25 15:54:32 +00:00
podClient := t . Client . CoreV1 ( ) . Pods ( f . Namespace . Name )
2017-01-03 13:00:15 +00:00
pods , err := podClient . List ( options )
if err != nil {
framework . Logf ( "warning: error retrieving pods: %s" , err )
} else {
for _ , pod := range pods . Items {
var gracePeriodSeconds int64 = 0
2017-01-24 15:38:21 +00:00
err := podClient . Delete ( pod . Name , & metav1 . DeleteOptions { GracePeriodSeconds : & gracePeriodSeconds } )
2017-01-03 13:00:15 +00:00
if err != nil {
framework . Logf ( "warning: error force deleting pod '%s': %s" , pod . Name , err )
}
}
}
2016-05-06 20:15:49 +00:00
} )
2016-09-15 00:00:00 +00:00
It ( "should only allow access from service loadbalancer source ranges [Slow]" , func ( ) {
// this feature currently supported only on GCE/GKE/AWS
framework . SkipUnlessProviderIs ( "gce" , "gke" , "aws" )
2017-04-20 02:10:15 +00:00
loadBalancerLagTimeout := framework . LoadBalancerLagTimeoutDefault
if framework . ProviderIs ( "aws" ) {
loadBalancerLagTimeout = framework . LoadBalancerLagTimeoutAWS
}
2016-12-29 23:35:47 +00:00
loadBalancerCreateTimeout := framework . LoadBalancerCreateTimeoutDefault
if nodes := framework . GetReadySchedulableNodesOrDie ( cs ) ; len ( nodes . Items ) > framework . LargeClusterMinNodesNumber {
loadBalancerCreateTimeout = framework . LoadBalancerCreateTimeoutLarge
2016-09-15 00:00:00 +00:00
}
namespace := f . Namespace . Name
serviceName := "lb-sourcerange"
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2016-09-15 00:00:00 +00:00
By ( "Prepare allow source ips" )
// prepare the exec pods
// acceptPod are allowed to access the loadbalancer
2016-12-29 23:35:47 +00:00
acceptPodName := framework . CreateExecPodOrFail ( cs , namespace , "execpod-accept" , nil )
dropPodName := framework . CreateExecPodOrFail ( cs , namespace , "execpod-drop" , nil )
2016-09-15 00:00:00 +00:00
2017-08-13 09:07:29 +00:00
acceptPod , err := cs . CoreV1 ( ) . Pods ( namespace ) . Get ( acceptPodName , metav1 . GetOptions { } )
2016-09-15 00:00:00 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-08-13 09:07:29 +00:00
dropPod , err := cs . CoreV1 ( ) . Pods ( namespace ) . Get ( dropPodName , metav1 . GetOptions { } )
2016-09-15 00:00:00 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
By ( "creating a pod to be part of the service " + serviceName )
// This container is an nginx container listening on port 80
// See kubernetes/contrib/ingress/echoheaders/nginx.conf for content of response
jig . RunOrFail ( namespace , nil )
// Create loadbalancer service with source range from node[0] and podAccept
svc := jig . CreateTCPServiceOrFail ( namespace , func ( svc * v1 . Service ) {
svc . Spec . Type = v1 . ServiceTypeLoadBalancer
2017-04-20 02:10:15 +00:00
svc . Spec . LoadBalancerSourceRanges = [ ] string { acceptPod . Status . PodIP + "/32" }
2016-09-15 00:00:00 +00:00
} )
// Clean up loadbalancer service
defer func ( ) {
jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
svc . Spec . Type = v1 . ServiceTypeNodePort
svc . Spec . LoadBalancerSourceRanges = nil
} )
2017-08-13 09:07:29 +00:00
Expect ( cs . CoreV1 ( ) . Services ( svc . Namespace ) . Delete ( svc . Name , nil ) ) . NotTo ( HaveOccurred ( ) )
2016-09-15 00:00:00 +00:00
} ( )
svc = jig . WaitForLoadBalancerOrFail ( namespace , serviceName , loadBalancerCreateTimeout )
jig . SanityCheckService ( svc , v1 . ServiceTypeLoadBalancer )
2017-04-20 02:10:15 +00:00
// timeout when we haven't just created the load balancer
normalReachabilityTimeout := 2 * time . Minute
2016-09-15 00:00:00 +00:00
By ( "check reachability from different sources" )
2016-12-29 23:35:47 +00:00
svcIP := framework . GetIngressPoint ( & svc . Status . LoadBalancer . Ingress [ 0 ] )
2017-04-20 02:10:15 +00:00
// Wait longer as this is our first request after creation. We can't check using a separate method,
// because the LB should only be reachable from the "accept" pod
framework . CheckReachabilityFromPod ( true , loadBalancerLagTimeout , namespace , acceptPodName , svcIP )
framework . CheckReachabilityFromPod ( false , normalReachabilityTimeout , namespace , dropPodName , svcIP )
2016-09-15 00:00:00 +00:00
By ( "Update service LoadBalancerSourceRange and check reachability" )
jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
// only allow access from dropPod
svc . Spec . LoadBalancerSourceRanges = [ ] string { dropPod . Status . PodIP + "/32" }
} )
2017-04-20 02:10:15 +00:00
framework . CheckReachabilityFromPod ( false , normalReachabilityTimeout , namespace , acceptPodName , svcIP )
framework . CheckReachabilityFromPod ( true , normalReachabilityTimeout , namespace , dropPodName , svcIP )
2016-09-15 00:00:00 +00:00
By ( "Delete LoadBalancerSourceRange field and check reachability" )
jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
svc . Spec . LoadBalancerSourceRanges = nil
} )
2017-04-20 02:10:15 +00:00
framework . CheckReachabilityFromPod ( true , normalReachabilityTimeout , namespace , acceptPodName , svcIP )
framework . CheckReachabilityFromPod ( true , normalReachabilityTimeout , namespace , dropPodName , svcIP )
2016-09-15 00:00:00 +00:00
} )
2017-05-08 03:42:40 +00:00
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
2017-11-15 13:35:44 +00:00
It ( "should be able to create an internal type load balancer [Slow] [DisabledForLargeClusters]" , func ( ) {
2017-07-24 21:13:41 +00:00
framework . SkipUnlessProviderIs ( "azure" , "gke" , "gce" )
2017-05-08 03:42:40 +00:00
createTimeout := framework . LoadBalancerCreateTimeoutDefault
2017-10-19 18:42:16 +00:00
if nodes := framework . GetReadySchedulableNodesOrDie ( cs ) ; len ( nodes . Items ) > framework . LargeClusterMinNodesNumber {
createTimeout = framework . LoadBalancerCreateTimeoutLarge
}
2017-05-08 03:42:40 +00:00
pollInterval := framework . Poll * 10
namespace := f . Namespace . Name
serviceName := "lb-internal"
jig := framework . NewServiceTestJig ( cs , serviceName )
2017-07-24 21:13:41 +00:00
By ( "creating pod to be part of service " + serviceName )
jig . RunOrFail ( namespace , nil )
enableILB , disableILB := framework . EnableAndDisableInternalLB ( )
2017-05-08 03:42:40 +00:00
isInternalEndpoint := func ( lbIngress * v1 . LoadBalancerIngress ) bool {
ingressEndpoint := framework . GetIngressPoint ( lbIngress )
// Needs update for providers using hostname as endpoint.
return strings . HasPrefix ( ingressEndpoint , "10." )
}
2017-07-24 21:13:41 +00:00
By ( "creating a service with type LoadBalancer and cloud specific Internal-LB annotation enabled" )
2017-05-08 03:42:40 +00:00
svc := jig . CreateTCPServiceOrFail ( namespace , func ( svc * v1 . Service ) {
svc . Spec . Type = v1 . ServiceTypeLoadBalancer
2017-07-24 21:13:41 +00:00
enableILB ( svc )
2017-05-08 03:42:40 +00:00
} )
svc = jig . WaitForLoadBalancerOrFail ( namespace , serviceName , createTimeout )
jig . SanityCheckService ( svc , v1 . ServiceTypeLoadBalancer )
lbIngress := & svc . Status . LoadBalancer . Ingress [ 0 ]
2017-12-01 22:51:56 +00:00
svcPort := int ( svc . Spec . Ports [ 0 ] . Port )
2017-05-08 03:42:40 +00:00
// should have an internal IP.
Expect ( isInternalEndpoint ( lbIngress ) ) . To ( BeTrue ( ) )
2017-12-01 22:51:56 +00:00
// ILBs are not accessible from the test orchestrator, so it's necessary to use
// a pod to test the service.
By ( "hitting the internal load balancer from pod" )
framework . Logf ( "creating pod with host network" )
hostExec := framework . LaunchHostExecPod ( f . ClientSet , f . Namespace . Name , "ilb-host-exec" )
framework . Logf ( "Waiting up to %v for service %q's internal LB to respond to requests" , createTimeout , serviceName )
tcpIngressIP := framework . GetIngressPoint ( lbIngress )
if pollErr := wait . PollImmediate ( pollInterval , createTimeout , func ( ) ( bool , error ) {
cmd := fmt . Sprintf ( ` curl -m 5 'http://%v:%v/echo?msg=hello' ` , tcpIngressIP , svcPort )
stdout , err := framework . RunHostCmd ( hostExec . Namespace , hostExec . Name , cmd )
if err != nil {
framework . Logf ( "error curling; stdout: %v. err: %v" , stdout , err )
return false , nil
}
if ! strings . Contains ( stdout , "hello" ) {
framework . Logf ( "Expected output to contain 'hello', got %q; retrying..." , stdout )
return false , nil
}
framework . Logf ( "Successful curl; stdout: %v" , stdout )
return true , nil
} ) ; pollErr != nil {
framework . Failf ( "Failed to hit ILB IP, err: %v" , pollErr )
}
2017-07-24 21:13:41 +00:00
By ( "switching to external type LoadBalancer" )
2017-05-08 03:42:40 +00:00
svc = jig . UpdateServiceOrFail ( namespace , serviceName , func ( svc * v1 . Service ) {
2017-07-24 21:13:41 +00:00
disableILB ( svc )
2017-05-08 03:42:40 +00:00
} )
framework . Logf ( "Waiting up to %v for service %q to have an external LoadBalancer" , createTimeout , serviceName )
if pollErr := wait . PollImmediate ( pollInterval , createTimeout , func ( ) ( bool , error ) {
2017-10-25 15:54:32 +00:00
svc , err := jig . Client . CoreV1 ( ) . Services ( namespace ) . Get ( serviceName , metav1 . GetOptions { } )
2017-05-08 03:42:40 +00:00
if err != nil {
return false , err
}
lbIngress = & svc . Status . LoadBalancer . Ingress [ 0 ]
return ! isInternalEndpoint ( lbIngress ) , nil
} ) ; pollErr != nil {
framework . Failf ( "Loadbalancer IP not changed to external." )
}
// should have an external IP.
jig . SanityCheckService ( svc , v1 . ServiceTypeLoadBalancer )
Expect ( isInternalEndpoint ( lbIngress ) ) . To ( BeFalse ( ) )
2017-12-01 22:51:56 +00:00
By ( "hitting the external load balancer" )
framework . Logf ( "Waiting up to %v for service %q's external LB to respond to requests" , createTimeout , serviceName )
tcpIngressIP = framework . GetIngressPoint ( lbIngress )
jig . TestReachableHTTP ( tcpIngressIP , svcPort , framework . LoadBalancerLagTimeoutDefault )
2017-07-24 21:13:41 +00:00
// GCE cannot test a specific IP because the test may not own it. This cloud specific condition
// will be removed when GCP supports similar functionality.
if framework . ProviderIs ( "azure" ) {
By ( "switching back to interal type LoadBalancer, with static IP specified." )
internalStaticIP := "10.240.11.11"
svc = jig . UpdateServiceOrFail ( namespace , serviceName , func ( svc * v1 . Service ) {
svc . Spec . LoadBalancerIP = internalStaticIP
enableILB ( svc )
} )
framework . Logf ( "Waiting up to %v for service %q to have an internal LoadBalancer" , createTimeout , serviceName )
if pollErr := wait . PollImmediate ( pollInterval , createTimeout , func ( ) ( bool , error ) {
2017-10-25 15:54:32 +00:00
svc , err := jig . Client . CoreV1 ( ) . Services ( namespace ) . Get ( serviceName , metav1 . GetOptions { } )
2017-07-24 21:13:41 +00:00
if err != nil {
return false , err
}
lbIngress = & svc . Status . LoadBalancer . Ingress [ 0 ]
return isInternalEndpoint ( lbIngress ) , nil
} ) ; pollErr != nil {
framework . Failf ( "Loadbalancer IP not changed to internal." )
2017-05-08 03:42:40 +00:00
}
2017-07-24 21:13:41 +00:00
// should have the given static internal IP.
jig . SanityCheckService ( svc , v1 . ServiceTypeLoadBalancer )
Expect ( framework . GetIngressPoint ( lbIngress ) ) . To ( Equal ( internalStaticIP ) )
2017-05-08 03:42:40 +00:00
}
2017-07-24 21:13:41 +00:00
By ( "switching to ClusterIP type to destroy loadbalancer" )
jig . ChangeServiceType ( svc . Namespace , svc . Name , v1 . ServiceTypeClusterIP , createTimeout )
2017-05-08 03:42:40 +00:00
} )
2018-03-14 00:45:34 +00:00
It ( "should have session affinity work for service with type clusterIP" , func ( ) {
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeClusterIP
execAffinityTestForNonLBService ( f , cs , svc , false )
} )
It ( "should be able to switch session affinity for service with type clusterIP" , func ( ) {
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeClusterIP
execAffinityTestForNonLBService ( f , cs , svc , true )
} )
It ( "should have session affinity work for NodePort service" , func ( ) {
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeNodePort
execAffinityTestForNonLBService ( f , cs , svc , false )
} )
It ( "should be able to switch session affinity for NodePort service" , func ( ) {
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeNodePort
execAffinityTestForNonLBService ( f , cs , svc , true )
} )
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
It ( "should have session affinity work for LoadBalancer service with ESIPP on [Slow] [DisabledForLargeClusters]" , func ( ) {
2018-03-14 00:45:34 +00:00
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeLoadBalancer
svc . Spec . ExternalTrafficPolicy = v1 . ServiceExternalTrafficPolicyTypeLocal
execAffinityTestForLBService ( f , cs , svc , false )
} )
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
It ( "should be able to switch session affinity for LoadBalancer service with ESIPP on [Slow] [DisabledForLargeClusters]" , func ( ) {
2018-03-14 00:45:34 +00:00
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeLoadBalancer
svc . Spec . ExternalTrafficPolicy = v1 . ServiceExternalTrafficPolicyTypeLocal
execAffinityTestForLBService ( f , cs , svc , true )
} )
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
It ( "should have session affinity work for LoadBalancer service with ESIPP off [Slow] [DisabledForLargeClusters]" , func ( ) {
2018-03-14 00:45:34 +00:00
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeLoadBalancer
svc . Spec . ExternalTrafficPolicy = v1 . ServiceExternalTrafficPolicyTypeCluster
execAffinityTestForLBService ( f , cs , svc , false )
} )
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
It ( "should be able to switch session affinity for LoadBalancer service with ESIPP off [Slow] [DisabledForLargeClusters]" , func ( ) {
2018-03-14 00:45:34 +00:00
svc := getServeHostnameService ( "service" )
svc . Spec . Type = v1 . ServiceTypeLoadBalancer
svc . Spec . ExternalTrafficPolicy = v1 . ServiceExternalTrafficPolicyTypeCluster
execAffinityTestForLBService ( f , cs , svc , true )
} )
2016-10-03 18:53:28 +00:00
} )
2018-04-11 11:28:56 +00:00
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
2017-11-15 13:35:44 +00:00
var _ = SIGDescribe ( "ESIPP [Slow] [DisabledForLargeClusters]" , func ( ) {
2016-10-03 18:53:28 +00:00
f := framework . NewDefaultFramework ( "esipp" )
2016-12-29 23:35:47 +00:00
loadBalancerCreateTimeout := framework . LoadBalancerCreateTimeoutDefault
2016-10-03 18:53:28 +00:00
var cs clientset . Interface
2016-09-07 02:48:04 +00:00
serviceLBNames := [ ] string { }
2016-08-22 17:48:00 +00:00
2016-10-03 18:53:28 +00:00
BeforeEach ( func ( ) {
2016-08-22 17:48:00 +00:00
// requires cloud load-balancer support - this feature currently supported only on GCE/GKE
framework . SkipUnlessProviderIs ( "gce" , "gke" )
2016-10-03 18:53:28 +00:00
cs = f . ClientSet
2016-12-29 23:35:47 +00:00
if nodes := framework . GetReadySchedulableNodesOrDie ( cs ) ; len ( nodes . Items ) > framework . LargeClusterMinNodesNumber {
loadBalancerCreateTimeout = framework . LoadBalancerCreateTimeoutLarge
2016-08-22 17:48:00 +00:00
}
2016-10-03 18:53:28 +00:00
} )
2016-09-07 02:48:04 +00:00
AfterEach ( func ( ) {
if CurrentGinkgoTestDescription ( ) . Failed {
2016-12-29 23:35:47 +00:00
framework . DescribeSvc ( f . Namespace . Name )
2016-09-07 02:48:04 +00:00
}
for _ , lb := range serviceLBNames {
2018-06-06 16:29:12 +00:00
framework . Logf ( "cleaning load balancer resource for %s" , lb )
framework . CleanupServiceResources ( cs , lb , framework . TestContext . CloudConfig . Region , framework . TestContext . CloudConfig . Zone )
2016-09-07 02:48:04 +00:00
}
//reset serviceLBNames
serviceLBNames = [ ] string { }
} )
2016-12-05 23:35:55 +00:00
It ( "should work for type=LoadBalancer" , func ( ) {
2016-08-22 17:48:00 +00:00
namespace := f . Namespace . Name
serviceName := "external-local"
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
svc := jig . CreateOnlyLocalLoadBalancerService ( namespace , serviceName , loadBalancerCreateTimeout , true , nil )
2018-08-04 04:36:48 +00:00
serviceLBNames = append ( serviceLBNames , cloudprovider . DefaultLoadBalancerName ( svc ) )
2017-08-09 05:50:00 +00:00
healthCheckNodePort := int ( svc . Spec . HealthCheckNodePort )
2016-08-22 17:48:00 +00:00
if healthCheckNodePort == 0 {
framework . Failf ( "Service HealthCheck NodePort was not allocated" )
}
2016-10-03 18:53:28 +00:00
defer func ( ) {
2016-11-18 20:55:17 +00:00
jig . ChangeServiceType ( svc . Namespace , svc . Name , v1 . ServiceTypeClusterIP , loadBalancerCreateTimeout )
2016-10-03 18:53:28 +00:00
// Make sure we didn't leak the health check node port.
2017-05-27 01:14:20 +00:00
threshold := 2
for _ , ips := range jig . GetEndpointNodes ( svc ) {
Expect ( jig . TestHTTPHealthCheckNodePort ( ips [ 0 ] , healthCheckNodePort , "/healthz" , framework . KubeProxyEndpointLagTimeout , false , threshold ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
}
2017-08-13 09:07:29 +00:00
Expect ( cs . CoreV1 ( ) . Services ( svc . Namespace ) . Delete ( svc . Name , nil ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
} ( )
svcTCPPort := int ( svc . Spec . Ports [ 0 ] . Port )
2016-12-29 23:35:47 +00:00
ingressIP := framework . GetIngressPoint ( & svc . Status . LoadBalancer . Ingress [ 0 ] )
2016-10-03 18:53:28 +00:00
2016-08-22 17:48:00 +00:00
By ( "reading clientIP using the TCP service's service port via its external VIP" )
2016-12-29 23:35:47 +00:00
content := jig . GetHTTPContent ( ingressIP , svcTCPPort , framework . KubeProxyLagTimeout , "/clientip" )
2016-10-07 20:56:38 +00:00
clientIP := content . String ( )
2016-08-22 17:48:00 +00:00
framework . Logf ( "ClientIP detected by target pod using VIP:SvcPort is %s" , clientIP )
2016-10-03 18:53:28 +00:00
2016-08-22 17:48:00 +00:00
By ( "checking if Source IP is preserved" )
if strings . HasPrefix ( clientIP , "10." ) {
framework . Failf ( "Source IP was NOT preserved" )
}
2016-10-03 18:53:28 +00:00
} )
2016-12-05 23:35:55 +00:00
It ( "should work for type=NodePort" , func ( ) {
2016-10-03 18:53:28 +00:00
namespace := f . Namespace . Name
serviceName := "external-local"
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
svc := jig . CreateOnlyLocalNodePortService ( namespace , serviceName , true )
2016-10-03 18:53:28 +00:00
defer func ( ) {
2017-08-13 09:07:29 +00:00
Expect ( cs . CoreV1 ( ) . Services ( svc . Namespace ) . Delete ( svc . Name , nil ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
} ( )
tcpNodePort := int ( svc . Spec . Ports [ 0 ] . NodePort )
2016-12-29 23:35:47 +00:00
endpointsNodeMap := jig . GetEndpointNodes ( svc )
2016-10-03 18:53:28 +00:00
path := "/clientip"
for nodeName , nodeIPs := range endpointsNodeMap {
nodeIP := nodeIPs [ 0 ]
By ( fmt . Sprintf ( "reading clientIP using the TCP service's NodePort, on node %v: %v%v%v" , nodeName , nodeIP , tcpNodePort , path ) )
2016-12-29 23:35:47 +00:00
content := jig . GetHTTPContent ( nodeIP , tcpNodePort , framework . KubeProxyLagTimeout , path )
2016-10-03 18:53:28 +00:00
clientIP := content . String ( )
framework . Logf ( "ClientIP detected by target pod using NodePort is %s" , clientIP )
if strings . HasPrefix ( clientIP , "10." ) {
framework . Failf ( "Source IP was NOT preserved" )
}
2016-08-22 17:48:00 +00:00
}
2016-10-03 18:53:28 +00:00
} )
2017-04-17 21:52:23 +00:00
It ( "should only target nodes with endpoints" , func ( ) {
2016-10-03 18:53:28 +00:00
namespace := f . Namespace . Name
serviceName := "external-local"
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
nodes := jig . GetNodes ( framework . MaxNodesForEndpointsTests )
2016-10-03 18:53:28 +00:00
2017-06-23 18:30:58 +00:00
svc := jig . CreateOnlyLocalLoadBalancerService ( namespace , serviceName , loadBalancerCreateTimeout , false ,
func ( svc * v1 . Service ) {
// Change service port to avoid collision with opened hostPorts
// in other tests that run in parallel.
if len ( svc . Spec . Ports ) != 0 {
svc . Spec . Ports [ 0 ] . TargetPort = intstr . FromInt ( int ( svc . Spec . Ports [ 0 ] . Port ) )
svc . Spec . Ports [ 0 ] . Port = 8081
}
} )
2018-08-04 04:36:48 +00:00
serviceLBNames = append ( serviceLBNames , cloudprovider . DefaultLoadBalancerName ( svc ) )
2016-10-03 18:53:28 +00:00
defer func ( ) {
2016-11-18 20:55:17 +00:00
jig . ChangeServiceType ( svc . Namespace , svc . Name , v1 . ServiceTypeClusterIP , loadBalancerCreateTimeout )
2017-08-13 09:07:29 +00:00
Expect ( cs . CoreV1 ( ) . Services ( svc . Namespace ) . Delete ( svc . Name , nil ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
} ( )
2017-08-09 05:50:00 +00:00
healthCheckNodePort := int ( svc . Spec . HealthCheckNodePort )
2016-10-03 18:53:28 +00:00
if healthCheckNodePort == 0 {
framework . Failf ( "Service HealthCheck NodePort was not allocated" )
2016-08-22 17:48:00 +00:00
}
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
ips := framework . CollectAddresses ( nodes , v1 . NodeExternalIP )
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
ingressIP := framework . GetIngressPoint ( & svc . Status . LoadBalancer . Ingress [ 0 ] )
2016-10-03 18:53:28 +00:00
svcTCPPort := int ( svc . Spec . Ports [ 0 ] . Port )
threshold := 2
path := "/healthz"
for i := 0 ; i < len ( nodes . Items ) ; i ++ {
endpointNodeName := nodes . Items [ i ] . Name
By ( "creating a pod to be part of the service " + serviceName + " on node " + endpointNodeName )
2016-11-18 20:55:17 +00:00
jig . RunOrFail ( namespace , func ( rc * v1 . ReplicationController ) {
2016-10-03 18:53:28 +00:00
rc . Name = serviceName
if endpointNodeName != "" {
rc . Spec . Template . Spec . NodeName = endpointNodeName
}
} )
By ( fmt . Sprintf ( "waiting for service endpoint on node %v" , endpointNodeName ) )
2016-12-29 23:35:47 +00:00
jig . WaitForEndpointOnNode ( namespace , serviceName , endpointNodeName )
2016-10-03 18:53:28 +00:00
2016-08-22 17:48:00 +00:00
// HealthCheck should pass only on the node where num(endpoints) > 0
// All other nodes should fail the healthcheck on the service healthCheckNodePort
2016-10-03 18:53:28 +00:00
for n , publicIP := range ips {
2017-05-27 01:14:20 +00:00
// Make sure the loadbalancer picked up the health check change.
// Confirm traffic can reach backend through LB before checking healthcheck nodeport.
jig . TestReachableHTTP ( ingressIP , svcTCPPort , framework . KubeProxyLagTimeout )
2016-10-03 18:53:28 +00:00
expectedSuccess := nodes . Items [ n ] . Name == endpointNodeName
2017-09-19 21:29:29 +00:00
port := strconv . Itoa ( healthCheckNodePort )
ipPort := net . JoinHostPort ( publicIP , port )
framework . Logf ( "Health checking %s, http://%s%s, expectedSuccess %v" , nodes . Items [ n ] . Name , ipPort , path , expectedSuccess )
2017-05-27 01:14:20 +00:00
Expect ( jig . TestHTTPHealthCheckNodePort ( publicIP , healthCheckNodePort , path , framework . KubeProxyEndpointLagTimeout , expectedSuccess , threshold ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
}
2018-05-17 15:27:44 +00:00
framework . ExpectNoError ( framework . DeleteRCAndWaitForGC ( f . ClientSet , namespace , serviceName ) )
2016-10-03 18:53:28 +00:00
}
} )
2017-04-17 21:52:23 +00:00
It ( "should work from pods" , func ( ) {
2016-10-03 18:53:28 +00:00
namespace := f . Namespace . Name
serviceName := "external-local"
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
nodes := jig . GetNodes ( framework . MaxNodesForEndpointsTests )
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
svc := jig . CreateOnlyLocalLoadBalancerService ( namespace , serviceName , loadBalancerCreateTimeout , true , nil )
2018-08-04 04:36:48 +00:00
serviceLBNames = append ( serviceLBNames , cloudprovider . DefaultLoadBalancerName ( svc ) )
2016-10-03 18:53:28 +00:00
defer func ( ) {
2016-11-18 20:55:17 +00:00
jig . ChangeServiceType ( svc . Namespace , svc . Name , v1 . ServiceTypeClusterIP , loadBalancerCreateTimeout )
2017-08-13 09:07:29 +00:00
Expect ( cs . CoreV1 ( ) . Services ( svc . Namespace ) . Delete ( svc . Name , nil ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
} ( )
2016-12-29 23:35:47 +00:00
ingressIP := framework . GetIngressPoint ( & svc . Status . LoadBalancer . Ingress [ 0 ] )
2017-09-19 21:29:29 +00:00
port := strconv . Itoa ( int ( svc . Spec . Ports [ 0 ] . Port ) )
ipPort := net . JoinHostPort ( ingressIP , port )
path := fmt . Sprintf ( "%s/clientip" , ipPort )
2016-10-03 18:53:28 +00:00
nodeName := nodes . Items [ 0 ] . Name
podName := "execpod-sourceip"
By ( fmt . Sprintf ( "Creating %v on node %v" , podName , nodeName ) )
2016-12-29 23:35:47 +00:00
execPodName := framework . CreateExecPodOrFail ( f . ClientSet , namespace , podName , func ( pod * v1 . Pod ) {
pod . Spec . NodeName = nodeName
} )
2016-10-03 18:53:28 +00:00
defer func ( ) {
2017-08-13 09:07:29 +00:00
err := cs . CoreV1 ( ) . Pods ( namespace ) . Delete ( execPodName , nil )
2016-10-03 18:53:28 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
2017-10-25 15:54:32 +00:00
execPod , err := f . ClientSet . CoreV1 ( ) . Pods ( namespace ) . Get ( execPodName , metav1 . GetOptions { } )
2016-12-08 01:51:35 +00:00
framework . ExpectNoError ( err )
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
framework . Logf ( "Waiting up to %v wget %v" , framework . KubeProxyLagTimeout , path )
2016-10-03 18:53:28 +00:00
cmd := fmt . Sprintf ( ` wget -T 30 -qO- %v ` , path )
var srcIP string
By ( fmt . Sprintf ( "Hitting external lb %v from pod %v on node %v" , ingressIP , podName , nodeName ) )
2016-12-29 23:35:47 +00:00
if pollErr := wait . PollImmediate ( framework . Poll , framework . LoadBalancerCreateTimeoutDefault , func ( ) ( bool , error ) {
2016-10-03 18:53:28 +00:00
stdout , err := framework . RunHostCmd ( execPod . Namespace , execPod . Name , cmd )
if err != nil {
framework . Logf ( "got err: %v, retry until timeout" , err )
return false , nil
}
srcIP = strings . TrimSpace ( strings . Split ( stdout , ":" ) [ 0 ] )
return srcIP == execPod . Status . PodIP , nil
} ) ; pollErr != nil {
framework . Failf ( "Source IP not preserved from %v, expected '%v' got '%v'" , podName , execPod . Status . PodIP , srcIP )
}
} )
2017-05-07 16:30:40 +00:00
It ( "should handle updates to ExternalTrafficPolicy field" , func ( ) {
2016-10-03 18:53:28 +00:00
namespace := f . Namespace . Name
serviceName := "external-local"
2016-12-29 23:35:47 +00:00
jig := framework . NewServiceTestJig ( cs , serviceName )
2016-10-03 18:53:28 +00:00
2016-12-29 23:35:47 +00:00
nodes := jig . GetNodes ( framework . MaxNodesForEndpointsTests )
2016-10-03 18:53:28 +00:00
if len ( nodes . Items ) < 2 {
framework . Failf ( "Need at least 2 nodes to verify source ip from a node without endpoint" )
}
2016-12-29 23:35:47 +00:00
svc := jig . CreateOnlyLocalLoadBalancerService ( namespace , serviceName , loadBalancerCreateTimeout , true , nil )
2018-08-04 04:36:48 +00:00
serviceLBNames = append ( serviceLBNames , cloudprovider . DefaultLoadBalancerName ( svc ) )
2016-10-03 18:53:28 +00:00
defer func ( ) {
2016-11-18 20:55:17 +00:00
jig . ChangeServiceType ( svc . Namespace , svc . Name , v1 . ServiceTypeClusterIP , loadBalancerCreateTimeout )
2017-08-13 09:07:29 +00:00
Expect ( cs . CoreV1 ( ) . Services ( svc . Namespace ) . Delete ( svc . Name , nil ) ) . NotTo ( HaveOccurred ( ) )
2016-10-03 18:53:28 +00:00
} ( )
2017-05-07 16:30:40 +00:00
// save the health check node port because it disappears when ESIPP is turned off.
2017-08-09 05:50:00 +00:00
healthCheckNodePort := int ( svc . Spec . HealthCheckNodePort )
2016-10-03 18:53:28 +00:00
By ( "turning ESIPP off" )
2016-11-18 20:55:17 +00:00
svc = jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
2017-05-31 18:35:24 +00:00
svc . Spec . ExternalTrafficPolicy = v1 . ServiceExternalTrafficPolicyTypeCluster
2016-10-03 18:53:28 +00:00
} )
2017-08-09 05:50:00 +00:00
if svc . Spec . HealthCheckNodePort > 0 {
2017-05-07 16:30:40 +00:00
framework . Failf ( "Service HealthCheck NodePort still present" )
2016-10-03 18:53:28 +00:00
}
2016-12-29 23:35:47 +00:00
endpointNodeMap := jig . GetEndpointNodes ( svc )
2016-10-03 18:53:28 +00:00
noEndpointNodeMap := map [ string ] [ ] string { }
for _ , n := range nodes . Items {
if _ , ok := endpointNodeMap [ n . Name ] ; ok {
continue
}
2016-12-29 23:35:47 +00:00
noEndpointNodeMap [ n . Name ] = framework . GetNodeAddresses ( & n , v1 . NodeExternalIP )
2016-10-03 18:53:28 +00:00
}
svcTCPPort := int ( svc . Spec . Ports [ 0 ] . Port )
svcNodePort := int ( svc . Spec . Ports [ 0 ] . NodePort )
2016-12-29 23:35:47 +00:00
ingressIP := framework . GetIngressPoint ( & svc . Status . LoadBalancer . Ingress [ 0 ] )
2016-10-03 18:53:28 +00:00
path := "/clientip"
By ( fmt . Sprintf ( "endpoints present on nodes %v, absent on nodes %v" , endpointNodeMap , noEndpointNodeMap ) )
for nodeName , nodeIPs := range noEndpointNodeMap {
2016-10-21 00:09:48 +00:00
By ( fmt . Sprintf ( "Checking %v (%v:%v%v) proxies to endpoints on another node" , nodeName , nodeIPs [ 0 ] , svcNodePort , path ) )
2016-12-29 23:35:47 +00:00
jig . GetHTTPContent ( nodeIPs [ 0 ] , svcNodePort , framework . KubeProxyLagTimeout , path )
2016-10-03 18:53:28 +00:00
}
for nodeName , nodeIPs := range endpointNodeMap {
By ( fmt . Sprintf ( "checking kube-proxy health check fails on node with endpoint (%s), public IP %s" , nodeName , nodeIPs [ 0 ] ) )
var body bytes . Buffer
var result bool
var err error
2016-12-29 23:35:47 +00:00
if pollErr := wait . PollImmediate ( framework . Poll , framework . ServiceTestTimeout , func ( ) ( bool , error ) {
result , err = framework . TestReachableHTTPWithContent ( nodeIPs [ 0 ] , healthCheckNodePort , "/healthz" , "" , & body )
2016-10-03 18:53:28 +00:00
return ! result , nil
} ) ; pollErr != nil {
framework . Failf ( "Kube-proxy still exposing health check on node %v:%v, after ESIPP was turned off. Last err %v, last body %v" ,
nodeName , healthCheckNodePort , err , body . String ( ) )
}
}
// Poll till kube-proxy re-adds the MASQUERADE rule on the node.
By ( fmt . Sprintf ( "checking source ip is NOT preserved through loadbalancer %v" , ingressIP ) )
2016-10-21 00:09:48 +00:00
var clientIP string
2016-12-29 23:35:47 +00:00
pollErr := wait . PollImmediate ( framework . Poll , framework . KubeProxyLagTimeout , func ( ) ( bool , error ) {
content := jig . GetHTTPContent ( ingressIP , svcTCPPort , framework . KubeProxyLagTimeout , "/clientip" )
2016-10-21 00:09:48 +00:00
clientIP = content . String ( )
2016-10-03 18:53:28 +00:00
if strings . HasPrefix ( clientIP , "10." ) {
return true , nil
}
2016-10-21 00:09:48 +00:00
return false , nil
2016-10-03 18:53:28 +00:00
} )
if pollErr != nil {
2016-10-21 00:09:48 +00:00
framework . Failf ( "Source IP WAS preserved even after ESIPP turned off. Got %v, expected a ten-dot cluster ip." , clientIP )
2016-10-03 18:53:28 +00:00
}
// TODO: We need to attempt to create another service with the previously
// allocated healthcheck nodePort. If the health check nodePort has been
// freed, the new service creation will succeed, upon which we cleanup.
// If the health check nodePort has NOT been freed, the new service
// creation will fail.
2017-05-07 16:30:40 +00:00
By ( "setting ExternalTraffic field back to OnlyLocal" )
2016-11-18 20:55:17 +00:00
svc = jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
2017-05-07 16:30:40 +00:00
svc . Spec . ExternalTrafficPolicy = v1 . ServiceExternalTrafficPolicyTypeLocal
2016-10-03 18:53:28 +00:00
// Request the same healthCheckNodePort as before, to test the user-requested allocation path
2017-05-07 16:30:40 +00:00
svc . Spec . HealthCheckNodePort = int32 ( healthCheckNodePort )
2016-10-03 18:53:28 +00:00
} )
2016-12-29 23:35:47 +00:00
pollErr = wait . PollImmediate ( framework . Poll , framework . KubeProxyLagTimeout , func ( ) ( bool , error ) {
content := jig . GetHTTPContent ( ingressIP , svcTCPPort , framework . KubeProxyLagTimeout , path )
2016-10-21 00:09:48 +00:00
clientIP = content . String ( )
By ( fmt . Sprintf ( "Endpoint %v:%v%v returned client ip %v" , ingressIP , svcTCPPort , path , clientIP ) )
2016-10-03 18:53:28 +00:00
if ! strings . HasPrefix ( clientIP , "10." ) {
return true , nil
}
2016-10-21 00:09:48 +00:00
return false , nil
2016-10-03 18:53:28 +00:00
} )
if pollErr != nil {
2016-10-21 00:09:48 +00:00
framework . Failf ( "Source IP (%v) is not the client IP even after ESIPP turned on, expected a public IP." , clientIP )
2016-08-22 17:48:00 +00:00
}
} )
2015-01-28 00:38:48 +00:00
} )
2015-02-09 20:37:56 +00:00
2016-10-18 13:00:38 +00:00
func execSourceipTest ( f * framework . Framework , c clientset . Interface , ns , nodeName , serviceIP string , servicePort int ) ( string , string ) {
2016-10-03 18:53:28 +00:00
framework . Logf ( "Creating an exec pod on node %v" , nodeName )
2016-12-29 23:35:47 +00:00
execPodName := framework . CreateExecPodOrFail ( f . ClientSet , ns , fmt . Sprintf ( "execpod-sourceip-%s" , nodeName ) , func ( pod * v1 . Pod ) {
pod . Spec . NodeName = nodeName
} )
2016-08-17 04:07:17 +00:00
defer func ( ) {
framework . Logf ( "Cleaning up the exec pod" )
2017-10-25 15:54:32 +00:00
err := c . CoreV1 ( ) . Pods ( ns ) . Delete ( execPodName , nil )
2016-08-17 04:07:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
2017-10-25 15:54:32 +00:00
execPod , err := f . ClientSet . CoreV1 ( ) . Pods ( ns ) . Get ( execPodName , metav1 . GetOptions { } )
2016-12-08 01:51:35 +00:00
framework . ExpectNoError ( err )
2016-08-17 04:07:17 +00:00
var stdout string
2017-09-19 21:29:29 +00:00
serviceIPPort := net . JoinHostPort ( serviceIP , strconv . Itoa ( servicePort ) )
2016-08-17 04:07:17 +00:00
timeout := 2 * time . Minute
2017-09-19 21:29:29 +00:00
framework . Logf ( "Waiting up to %v wget %s" , timeout , serviceIPPort )
cmd := fmt . Sprintf ( ` wget -T 30 -qO- %s | grep client_address ` , serviceIPPort )
2018-03-06 01:24:48 +00:00
for start := time . Now ( ) ; time . Since ( start ) < timeout ; time . Sleep ( 2 * time . Second ) {
2016-08-17 04:07:17 +00:00
stdout , err = framework . RunHostCmd ( execPod . Namespace , execPod . Name , cmd )
if err != nil {
framework . Logf ( "got err: %v, retry until timeout" , err )
continue
}
2016-10-05 16:13:19 +00:00
// Need to check output because wget -q might omit the error.
if strings . TrimSpace ( stdout ) == "" {
framework . Logf ( "got empty stdout, retry until timeout" )
continue
}
2016-08-17 04:07:17 +00:00
break
}
2016-12-08 01:51:35 +00:00
framework . ExpectNoError ( err )
2016-08-17 04:07:17 +00:00
2016-10-05 16:13:19 +00:00
// The stdout return from RunHostCmd seems to come with "\n", so TrimSpace is needed.
// Desired stdout in this format: client_address=x.x.x.x
2016-08-17 04:07:17 +00:00
outputs := strings . Split ( strings . TrimSpace ( stdout ) , "=" )
2016-10-04 17:23:53 +00:00
if len ( outputs ) != 2 {
2016-10-05 16:13:19 +00:00
// Fail the test if output format is unexpected.
2016-10-04 17:23:53 +00:00
framework . Failf ( "exec pod returned unexpected stdout format: [%v]\n" , stdout )
}
2016-10-03 18:53:28 +00:00
return execPod . Status . PodIP , outputs [ 1 ]
2016-08-17 04:07:17 +00:00
}
2018-03-14 00:45:34 +00:00
// execAffinityTestForNonLBService is a helper function that wrap the logic of
// affinity test for non-load-balancer services. Session afinity will be
// enabled when the service is created. If parameter isTransitionTest is true,
// session affinity will be switched off/on and test if the service converges
// to a stable affinity state.
func execAffinityTestForNonLBService ( f * framework . Framework , cs clientset . Interface , svc * v1 . Service , isTransitionTest bool ) {
ns := f . Namespace . Name
numPods , servicePort , serviceName := 3 , defaultServeHostnameServicePort , svc . ObjectMeta . Name
By ( "creating service in namespace " + ns )
serviceType := svc . Spec . Type
svc . Spec . SessionAffinity = v1 . ServiceAffinityClientIP
_ , _ , err := framework . StartServeHostnameService ( cs , f . InternalClientset , svc , ns , numPods )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
defer func ( ) {
2018-05-17 15:27:44 +00:00
framework . StopServeHostnameService ( cs , ns , serviceName )
2018-03-14 00:45:34 +00:00
} ( )
jig := framework . NewServiceTestJig ( cs , serviceName )
svc , err = jig . Client . CoreV1 ( ) . Services ( ns ) . Get ( serviceName , metav1 . GetOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
var svcIp string
if serviceType == v1 . ServiceTypeNodePort {
nodes := framework . GetReadySchedulableNodesOrDie ( cs )
addrs := framework . CollectAddresses ( nodes , v1 . NodeInternalIP )
Expect ( len ( addrs ) ) . To ( BeNumerically ( ">" , 0 ) , "Failed to get Node internal IP" )
svcIp = addrs [ 0 ]
servicePort = int ( svc . Spec . Ports [ 0 ] . NodePort )
} else {
svcIp = svc . Spec . ClusterIP
}
execPodName := framework . CreateExecPodOrFail ( cs , ns , "execpod-affinity" , nil )
defer func ( ) {
framework . Logf ( "Cleaning up the exec pod" )
err := cs . CoreV1 ( ) . Pods ( ns ) . Delete ( execPodName , nil )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} ( )
execPod , err := cs . CoreV1 ( ) . Pods ( ns ) . Get ( execPodName , metav1 . GetOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if ! isTransitionTest {
Expect ( framework . CheckAffinity ( jig , execPod , svcIp , servicePort , true , false ) ) . To ( BeTrue ( ) )
}
if isTransitionTest {
svc = jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
svc . Spec . SessionAffinity = v1 . ServiceAffinityNone
} )
Expect ( framework . CheckAffinity ( jig , execPod , svcIp , servicePort , false , true ) ) . To ( BeTrue ( ) )
svc = jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
svc . Spec . SessionAffinity = v1 . ServiceAffinityClientIP
} )
Expect ( framework . CheckAffinity ( jig , execPod , svcIp , servicePort , true , true ) ) . To ( BeTrue ( ) )
}
}
// execAffinityTestForLBService is a helper function that wrap the logic of
// affinity test for load balancer services, similar to
// execAffinityTestForNonLBService.
func execAffinityTestForLBService ( f * framework . Framework , cs clientset . Interface , svc * v1 . Service , isTransitionTest bool ) {
numPods , ns , serviceName := 3 , f . Namespace . Name , svc . ObjectMeta . Name
By ( "creating service in namespace " + ns )
svc . Spec . SessionAffinity = v1 . ServiceAffinityClientIP
_ , _ , err := framework . StartServeHostnameService ( cs , f . InternalClientset , svc , ns , numPods )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
jig := framework . NewServiceTestJig ( cs , serviceName )
By ( "waiting for loadbalancer for service " + ns + "/" + serviceName )
svc = jig . WaitForLoadBalancerOrFail ( ns , serviceName , framework . LoadBalancerCreateTimeoutDefault )
jig . SanityCheckService ( svc , v1 . ServiceTypeLoadBalancer )
defer func ( ) {
2018-05-17 15:27:44 +00:00
framework . StopServeHostnameService ( cs , ns , serviceName )
2018-08-04 04:36:48 +00:00
lb := cloudprovider . DefaultLoadBalancerName ( svc )
2018-06-06 16:29:12 +00:00
framework . Logf ( "cleaning load balancer resource for %s" , lb )
framework . CleanupServiceResources ( cs , lb , framework . TestContext . CloudConfig . Region , framework . TestContext . CloudConfig . Zone )
2018-03-14 00:45:34 +00:00
} ( )
ingressIP := framework . GetIngressPoint ( & svc . Status . LoadBalancer . Ingress [ 0 ] )
port := int ( svc . Spec . Ports [ 0 ] . Port )
if ! isTransitionTest {
Expect ( framework . CheckAffinity ( jig , nil , ingressIP , port , true , false ) ) . To ( BeTrue ( ) )
}
if isTransitionTest {
svc = jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
svc . Spec . SessionAffinity = v1 . ServiceAffinityNone
} )
Expect ( framework . CheckAffinity ( jig , nil , ingressIP , port , false , true ) ) . To ( BeTrue ( ) )
svc = jig . UpdateServiceOrFail ( svc . Namespace , svc . Name , func ( svc * v1 . Service ) {
svc . Spec . SessionAffinity = v1 . ServiceAffinityClientIP
} )
Expect ( framework . CheckAffinity ( jig , nil , ingressIP , port , true , true ) ) . To ( BeTrue ( ) )
}
}