service.go 137 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package network
  14. import (
  15. "bytes"
  16. "context"
  17. "errors"
  18. "fmt"
  19. "math/rand"
  20. "net"
  21. "net/http"
  22. "sort"
  23. "strconv"
  24. "strings"
  25. "time"
  26. utilnet "k8s.io/apimachinery/pkg/util/net"
  27. compute "google.golang.org/api/compute/v1"
  28. appsv1 "k8s.io/api/apps/v1"
  29. v1 "k8s.io/api/core/v1"
  30. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  31. "k8s.io/apimachinery/pkg/labels"
  32. "k8s.io/apimachinery/pkg/util/intstr"
  33. "k8s.io/apimachinery/pkg/util/sets"
  34. "k8s.io/apimachinery/pkg/util/wait"
  35. clientset "k8s.io/client-go/kubernetes"
  36. cloudprovider "k8s.io/cloud-provider"
  37. "k8s.io/kubernetes/test/e2e/framework"
  38. e2edeploy "k8s.io/kubernetes/test/e2e/framework/deployment"
  39. e2eendpoints "k8s.io/kubernetes/test/e2e/framework/endpoints"
  40. e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
  41. e2enode "k8s.io/kubernetes/test/e2e/framework/node"
  42. e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
  43. "k8s.io/kubernetes/test/e2e/framework/providers/gce"
  44. e2erc "k8s.io/kubernetes/test/e2e/framework/rc"
  45. e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
  46. e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
  47. e2essh "k8s.io/kubernetes/test/e2e/framework/ssh"
  48. testutils "k8s.io/kubernetes/test/utils"
  49. imageutils "k8s.io/kubernetes/test/utils/image"
  50. gcecloud "k8s.io/legacy-cloud-providers/gce"
  51. "github.com/onsi/ginkgo"
  52. "github.com/onsi/gomega"
  53. )
  54. const (
  55. defaultServeHostnameServicePort = 80
  56. defaultServeHostnameServiceName = "svc-hostname"
  57. // KubeProxyLagTimeout is the maximum time a kube-proxy daemon on a node is allowed
  58. // to not notice a Service update, such as type=NodePort.
  59. // TODO: This timeout should be O(10s), observed values are O(1m), 5m is very
  60. // liberal. Fix tracked in #20567.
  61. KubeProxyLagTimeout = 5 * time.Minute
  62. // LoadBalancerPollTimeout is the time required by the loadbalancer to poll.
  63. // On average it takes ~6 minutes for a single backend to come online in GCE.
  64. LoadBalancerPollTimeout = 22 * time.Minute
  65. // AffinityTimeout is the maximum time that CheckAffinity is allowed to take; this
  66. // needs to be more than long enough for AffinityConfirmCount HTTP requests to
  67. // complete in a busy CI cluster, but shouldn't be too long since we will end up
  68. // waiting the entire time in the tests where affinity is not expected.
  69. AffinityTimeout = 2 * time.Minute
  70. // AffinityConfirmCount is the number of needed continuous requests to confirm that
  71. // affinity is enabled.
  72. AffinityConfirmCount = 15
  73. )
  74. var (
  75. defaultServeHostnameService = v1.Service{
  76. ObjectMeta: metav1.ObjectMeta{
  77. Name: defaultServeHostnameServiceName,
  78. },
  79. Spec: v1.ServiceSpec{
  80. Ports: []v1.ServicePort{{
  81. Port: int32(defaultServeHostnameServicePort),
  82. TargetPort: intstr.FromInt(9376),
  83. Protocol: v1.ProtocolTCP,
  84. }},
  85. Selector: map[string]string{
  86. "name": defaultServeHostnameServiceName,
  87. },
  88. },
  89. }
  90. )
  91. // portsByPodName is a map that maps pod name to container ports.
  92. type portsByPodName map[string][]int
  93. // CheckAffinity function tests whether the service affinity works as expected.
  94. // If affinity is expected, the test will return true once affinityConfirmCount
  95. // number of same response observed in a row. If affinity is not expected, the
  96. // test will keep observe until different responses observed. The function will
  97. // return false only in case of unexpected errors.
  98. func checkAffinity(execPod *v1.Pod, serviceIP string, servicePort int, shouldHold bool) bool {
  99. serviceIPPort := net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))
  100. cmd := fmt.Sprintf(`curl -q -s --connect-timeout 2 http://%s/`, serviceIPPort)
  101. timeout := AffinityTimeout
  102. if execPod == nil {
  103. timeout = LoadBalancerPollTimeout
  104. }
  105. var tracker affinityTracker
  106. if pollErr := wait.PollImmediate(framework.Poll, timeout, func() (bool, error) {
  107. if execPod != nil {
  108. stdout, err := framework.RunHostCmd(execPod.Namespace, execPod.Name, cmd)
  109. if err != nil {
  110. framework.Logf("Failed to get response from %s. Retry until timeout", serviceIPPort)
  111. return false, nil
  112. }
  113. tracker.recordHost(stdout)
  114. } else {
  115. rawResponse := GetHTTPContent(serviceIP, servicePort, timeout, "")
  116. tracker.recordHost(rawResponse.String())
  117. }
  118. trackerFulfilled, affinityHolds := tracker.checkHostTrace(AffinityConfirmCount)
  119. if !shouldHold && !affinityHolds {
  120. return true, nil
  121. }
  122. if shouldHold && trackerFulfilled && affinityHolds {
  123. return true, nil
  124. }
  125. return false, nil
  126. }); pollErr != nil {
  127. trackerFulfilled, _ := tracker.checkHostTrace(AffinityConfirmCount)
  128. if pollErr != wait.ErrWaitTimeout {
  129. checkAffinityFailed(tracker, pollErr.Error())
  130. return false
  131. }
  132. if !trackerFulfilled {
  133. checkAffinityFailed(tracker, fmt.Sprintf("Connection to %s timed out or not enough responses.", serviceIPPort))
  134. }
  135. if shouldHold {
  136. checkAffinityFailed(tracker, "Affinity should hold but didn't.")
  137. } else {
  138. checkAffinityFailed(tracker, "Affinity shouldn't hold but did.")
  139. }
  140. return true
  141. }
  142. return true
  143. }
  144. // affinityTracker tracks the destination of a request for the affinity tests.
  145. type affinityTracker struct {
  146. hostTrace []string
  147. }
  148. // Record the response going to a given host.
  149. func (at *affinityTracker) recordHost(host string) {
  150. at.hostTrace = append(at.hostTrace, host)
  151. framework.Logf("Received response from host: %s", host)
  152. }
  153. // Check that we got a constant count requests going to the same host.
  154. func (at *affinityTracker) checkHostTrace(count int) (fulfilled, affinityHolds bool) {
  155. fulfilled = (len(at.hostTrace) >= count)
  156. if len(at.hostTrace) == 0 {
  157. return fulfilled, true
  158. }
  159. last := at.hostTrace[0:]
  160. if len(at.hostTrace)-count >= 0 {
  161. last = at.hostTrace[len(at.hostTrace)-count:]
  162. }
  163. host := at.hostTrace[len(at.hostTrace)-1]
  164. for _, h := range last {
  165. if h != host {
  166. return fulfilled, false
  167. }
  168. }
  169. return fulfilled, true
  170. }
  171. func checkAffinityFailed(tracker affinityTracker, err string) {
  172. framework.Logf("%v", tracker.hostTrace)
  173. framework.Failf(err)
  174. }
  175. // StartServeHostnameService creates a replication controller that serves its
  176. // hostname and a service on top of it.
  177. func StartServeHostnameService(c clientset.Interface, svc *v1.Service, ns string, replicas int) ([]string, string, error) {
  178. podNames := make([]string, replicas)
  179. name := svc.ObjectMeta.Name
  180. ginkgo.By("creating service " + name + " in namespace " + ns)
  181. _, err := c.CoreV1().Services(ns).Create(context.TODO(), svc, metav1.CreateOptions{})
  182. if err != nil {
  183. return podNames, "", err
  184. }
  185. var createdPods []*v1.Pod
  186. maxContainerFailures := 0
  187. config := testutils.RCConfig{
  188. Client: c,
  189. Image: framework.ServeHostnameImage,
  190. Command: []string{"/agnhost", "serve-hostname"},
  191. Name: name,
  192. Namespace: ns,
  193. PollInterval: 3 * time.Second,
  194. Timeout: framework.PodReadyBeforeTimeout,
  195. Replicas: replicas,
  196. CreatedPods: &createdPods,
  197. MaxContainerFailures: &maxContainerFailures,
  198. }
  199. err = e2erc.RunRC(config)
  200. if err != nil {
  201. return podNames, "", err
  202. }
  203. if len(createdPods) != replicas {
  204. return podNames, "", fmt.Errorf("incorrect number of running pods: %v", len(createdPods))
  205. }
  206. for i := range createdPods {
  207. podNames[i] = createdPods[i].ObjectMeta.Name
  208. }
  209. sort.StringSlice(podNames).Sort()
  210. service, err := c.CoreV1().Services(ns).Get(context.TODO(), name, metav1.GetOptions{})
  211. if err != nil {
  212. return podNames, "", err
  213. }
  214. if service.Spec.ClusterIP == "" {
  215. return podNames, "", fmt.Errorf("service IP is blank for %v", name)
  216. }
  217. serviceIP := service.Spec.ClusterIP
  218. return podNames, serviceIP, nil
  219. }
  220. // StopServeHostnameService stops the given service.
  221. func StopServeHostnameService(clientset clientset.Interface, ns, name string) error {
  222. if err := e2erc.DeleteRCAndWaitForGC(clientset, ns, name); err != nil {
  223. return err
  224. }
  225. if err := clientset.CoreV1().Services(ns).Delete(context.TODO(), name, nil); err != nil {
  226. return err
  227. }
  228. return nil
  229. }
  230. // verifyServeHostnameServiceUp wgets the given serviceIP:servicePort from the
  231. // given host and from within a pod. The host is expected to be an SSH-able node
  232. // in the cluster. Each pod in the service is expected to echo its name. These
  233. // names are compared with the given expectedPods list after a sort | uniq.
  234. func verifyServeHostnameServiceUp(c clientset.Interface, ns, host string, expectedPods []string, serviceIP string, servicePort int) error {
  235. execPod := e2epod.CreateExecPodOrFail(c, ns, "execpod-", nil)
  236. defer func() {
  237. e2epod.DeletePodOrFail(c, ns, execPod.Name)
  238. }()
  239. // Loop a bunch of times - the proxy is randomized, so we want a good
  240. // chance of hitting each backend at least once.
  241. buildCommand := func(wget string) string {
  242. serviceIPPort := net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))
  243. return fmt.Sprintf("for i in $(seq 1 %d); do %s http://%s 2>&1 || true; echo; done",
  244. 50*len(expectedPods), wget, serviceIPPort)
  245. }
  246. commands := []func() string{
  247. // verify service from node
  248. func() string {
  249. cmd := "set -e; " + buildCommand("wget -q --timeout=0.2 --tries=1 -O -")
  250. framework.Logf("Executing cmd %q on host %v", cmd, host)
  251. result, err := e2essh.SSH(cmd, host, framework.TestContext.Provider)
  252. if err != nil || result.Code != 0 {
  253. e2essh.LogResult(result)
  254. framework.Logf("error while SSH-ing to node: %v", err)
  255. }
  256. return result.Stdout
  257. },
  258. // verify service from pod
  259. func() string {
  260. cmd := buildCommand("wget -q -T 1 -O -")
  261. framework.Logf("Executing cmd %q in pod %v/%v", cmd, ns, execPod.Name)
  262. // TODO: Use exec-over-http via the netexec pod instead of kubectl exec.
  263. output, err := framework.RunHostCmd(ns, execPod.Name, cmd)
  264. if err != nil {
  265. framework.Logf("error while kubectl execing %q in pod %v/%v: %v\nOutput: %v", cmd, ns, execPod.Name, err, output)
  266. }
  267. return output
  268. },
  269. }
  270. expectedEndpoints := sets.NewString(expectedPods...)
  271. ginkgo.By(fmt.Sprintf("verifying service has %d reachable backends", len(expectedPods)))
  272. for _, cmdFunc := range commands {
  273. passed := false
  274. gotEndpoints := sets.NewString()
  275. // Retry cmdFunc for a while
  276. for start := time.Now(); time.Since(start) < KubeProxyLagTimeout; time.Sleep(5 * time.Second) {
  277. for _, endpoint := range strings.Split(cmdFunc(), "\n") {
  278. trimmedEp := strings.TrimSpace(endpoint)
  279. if trimmedEp != "" {
  280. gotEndpoints.Insert(trimmedEp)
  281. }
  282. }
  283. // TODO: simply checking that the retrieved endpoints is a superset
  284. // of the expected allows us to ignore intermitten network flakes that
  285. // result in output like "wget timed out", but these should be rare
  286. // and we need a better way to track how often it occurs.
  287. if gotEndpoints.IsSuperset(expectedEndpoints) {
  288. if !gotEndpoints.Equal(expectedEndpoints) {
  289. framework.Logf("Ignoring unexpected output wgetting endpoints of service %s: %v", serviceIP, gotEndpoints.Difference(expectedEndpoints))
  290. }
  291. passed = true
  292. break
  293. }
  294. framework.Logf("Unable to reach the following endpoints of service %s: %v", serviceIP, expectedEndpoints.Difference(gotEndpoints))
  295. }
  296. if !passed {
  297. // Sort the lists so they're easier to visually diff.
  298. exp := expectedEndpoints.List()
  299. got := gotEndpoints.List()
  300. sort.StringSlice(exp).Sort()
  301. sort.StringSlice(got).Sort()
  302. return fmt.Errorf("service verification failed for: %s\nexpected %v\nreceived %v", serviceIP, exp, got)
  303. }
  304. }
  305. return nil
  306. }
  307. // verifyServeHostnameServiceDown verifies that the given service isn't served.
  308. func verifyServeHostnameServiceDown(c clientset.Interface, host string, serviceIP string, servicePort int) error {
  309. ipPort := net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))
  310. // The current versions of curl included in CentOS and RHEL distros
  311. // misinterpret square brackets around IPv6 as globbing, so use the -g
  312. // argument to disable globbing to handle the IPv6 case.
  313. command := fmt.Sprintf(
  314. "curl -g -s --connect-timeout 2 http://%s && exit 99", ipPort)
  315. for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
  316. result, err := e2essh.SSH(command, host, framework.TestContext.Provider)
  317. if err != nil {
  318. e2essh.LogResult(result)
  319. framework.Logf("error while SSH-ing to node: %v", err)
  320. }
  321. if result.Code != 99 {
  322. return nil
  323. }
  324. framework.Logf("service still alive - still waiting")
  325. }
  326. return fmt.Errorf("waiting for service to be down timed out")
  327. }
  328. // testNotReachableHTTP tests that a HTTP request doesn't connect to the given host and port.
  329. func testNotReachableHTTP(host string, port int, timeout time.Duration) {
  330. pollfn := func() (bool, error) {
  331. result := e2enetwork.PokeHTTP(host, port, "/", nil)
  332. if result.Code == 0 {
  333. return true, nil
  334. }
  335. return false, nil // caller can retry
  336. }
  337. if err := wait.PollImmediate(framework.Poll, timeout, pollfn); err != nil {
  338. framework.Failf("HTTP service %v:%v reachable after %v: %v", host, port, timeout, err)
  339. }
  340. }
  341. // testRejectedHTTP tests that the given host rejects a HTTP request on the given port.
  342. func testRejectedHTTP(host string, port int, timeout time.Duration) {
  343. pollfn := func() (bool, error) {
  344. result := e2enetwork.PokeHTTP(host, port, "/", nil)
  345. if result.Status == e2enetwork.HTTPRefused {
  346. return true, nil
  347. }
  348. return false, nil // caller can retry
  349. }
  350. if err := wait.PollImmediate(framework.Poll, timeout, pollfn); err != nil {
  351. framework.Failf("HTTP service %v:%v not rejected: %v", host, port, err)
  352. }
  353. }
  354. // UDPPokeParams is a struct for UDP poke parameters.
  355. type UDPPokeParams struct {
  356. Timeout time.Duration
  357. Response string
  358. }
  359. // UDPPokeResult is a struct for UDP poke result.
  360. type UDPPokeResult struct {
  361. Status UDPPokeStatus
  362. Error error // if there was any error
  363. Response []byte // if code != 0
  364. }
  365. // UDPPokeStatus is string for representing UDP poke status.
  366. type UDPPokeStatus string
  367. const (
  368. // UDPSuccess is UDP poke status which is success.
  369. UDPSuccess UDPPokeStatus = "Success"
  370. // UDPError is UDP poke status which is error.
  371. UDPError UDPPokeStatus = "UnknownError"
  372. // UDPTimeout is UDP poke status which is timeout.
  373. UDPTimeout UDPPokeStatus = "TimedOut"
  374. // UDPRefused is UDP poke status which is connection refused.
  375. UDPRefused UDPPokeStatus = "ConnectionRefused"
  376. // UDPBadResponse is UDP poke status which is bad response.
  377. UDPBadResponse UDPPokeStatus = "BadResponse"
  378. // Any time we add new errors, we should audit all callers of this.
  379. )
  380. // pokeUDP tries to connect to a host on a port and send the given request. Callers
  381. // can specify additional success parameters, if desired.
  382. //
  383. // The result status will be characterized as precisely as possible, given the
  384. // known users of this.
  385. //
  386. // The result error will be populated for any status other than Success.
  387. //
  388. // The result response will be populated if the UDP transaction was completed, even
  389. // if the other test params make this a failure).
  390. func pokeUDP(host string, port int, request string, params *UDPPokeParams) UDPPokeResult {
  391. hostPort := net.JoinHostPort(host, strconv.Itoa(port))
  392. url := fmt.Sprintf("udp://%s", hostPort)
  393. ret := UDPPokeResult{}
  394. // Sanity check inputs, because it has happened. These are the only things
  395. // that should hard fail the test - they are basically ASSERT()s.
  396. if host == "" {
  397. framework.Failf("Got empty host for UDP poke (%s)", url)
  398. return ret
  399. }
  400. if port == 0 {
  401. framework.Failf("Got port==0 for UDP poke (%s)", url)
  402. return ret
  403. }
  404. // Set default params.
  405. if params == nil {
  406. params = &UDPPokeParams{}
  407. }
  408. framework.Logf("Poking %v", url)
  409. con, err := net.Dial("udp", hostPort)
  410. if err != nil {
  411. ret.Status = UDPError
  412. ret.Error = err
  413. framework.Logf("Poke(%q): %v", url, err)
  414. return ret
  415. }
  416. _, err = con.Write([]byte(fmt.Sprintf("%s\n", request)))
  417. if err != nil {
  418. ret.Error = err
  419. neterr, ok := err.(net.Error)
  420. if ok && neterr.Timeout() {
  421. ret.Status = UDPTimeout
  422. } else if strings.Contains(err.Error(), "connection refused") {
  423. ret.Status = UDPRefused
  424. } else {
  425. ret.Status = UDPError
  426. }
  427. framework.Logf("Poke(%q): %v", url, err)
  428. return ret
  429. }
  430. if params.Timeout != 0 {
  431. err = con.SetDeadline(time.Now().Add(params.Timeout))
  432. if err != nil {
  433. ret.Status = UDPError
  434. ret.Error = err
  435. framework.Logf("Poke(%q): %v", url, err)
  436. return ret
  437. }
  438. }
  439. bufsize := len(params.Response) + 1
  440. if bufsize == 0 {
  441. bufsize = 4096
  442. }
  443. var buf = make([]byte, bufsize)
  444. n, err := con.Read(buf)
  445. if err != nil {
  446. ret.Error = err
  447. neterr, ok := err.(net.Error)
  448. if ok && neterr.Timeout() {
  449. ret.Status = UDPTimeout
  450. } else if strings.Contains(err.Error(), "connection refused") {
  451. ret.Status = UDPRefused
  452. } else {
  453. ret.Status = UDPError
  454. }
  455. framework.Logf("Poke(%q): %v", url, err)
  456. return ret
  457. }
  458. ret.Response = buf[0:n]
  459. if params.Response != "" && string(ret.Response) != params.Response {
  460. ret.Status = UDPBadResponse
  461. ret.Error = fmt.Errorf("response does not match expected string: %q", string(ret.Response))
  462. framework.Logf("Poke(%q): %v", url, ret.Error)
  463. return ret
  464. }
  465. ret.Status = UDPSuccess
  466. framework.Logf("Poke(%q): success", url)
  467. return ret
  468. }
  469. // testReachableUDP tests that the given host serves UDP on the given port.
  470. func testReachableUDP(host string, port int, timeout time.Duration) {
  471. pollfn := func() (bool, error) {
  472. result := pokeUDP(host, port, "echo hello", &UDPPokeParams{
  473. Timeout: 3 * time.Second,
  474. Response: "hello",
  475. })
  476. if result.Status == UDPSuccess {
  477. return true, nil
  478. }
  479. return false, nil // caller can retry
  480. }
  481. if err := wait.PollImmediate(framework.Poll, timeout, pollfn); err != nil {
  482. framework.Failf("Could not reach UDP service through %v:%v after %v: %v", host, port, timeout, err)
  483. }
  484. }
  485. // testNotReachableUDP tests that the given host doesn't serve UDP on the given port.
  486. func testNotReachableUDP(host string, port int, timeout time.Duration) {
  487. pollfn := func() (bool, error) {
  488. result := pokeUDP(host, port, "echo hello", &UDPPokeParams{Timeout: 3 * time.Second})
  489. if result.Status != UDPSuccess && result.Status != UDPError {
  490. return true, nil
  491. }
  492. return false, nil // caller can retry
  493. }
  494. if err := wait.PollImmediate(framework.Poll, timeout, pollfn); err != nil {
  495. framework.Failf("UDP service %v:%v reachable after %v: %v", host, port, timeout, err)
  496. }
  497. }
  498. // testRejectedUDP tests that the given host rejects a UDP request on the given port.
  499. func testRejectedUDP(host string, port int, timeout time.Duration) {
  500. pollfn := func() (bool, error) {
  501. result := pokeUDP(host, port, "echo hello", &UDPPokeParams{Timeout: 3 * time.Second})
  502. if result.Status == UDPRefused {
  503. return true, nil
  504. }
  505. return false, nil // caller can retry
  506. }
  507. if err := wait.PollImmediate(framework.Poll, timeout, pollfn); err != nil {
  508. framework.Failf("UDP service %v:%v not rejected: %v", host, port, err)
  509. }
  510. }
  511. // TestHTTPHealthCheckNodePort tests a HTTP connection by the given request to the given host and port.
  512. func TestHTTPHealthCheckNodePort(host string, port int, request string, timeout time.Duration, expectSucceed bool, threshold int) error {
  513. count := 0
  514. condition := func() (bool, error) {
  515. success, _ := testHTTPHealthCheckNodePort(host, port, request)
  516. if success && expectSucceed ||
  517. !success && !expectSucceed {
  518. count++
  519. }
  520. if count >= threshold {
  521. return true, nil
  522. }
  523. return false, nil
  524. }
  525. if err := wait.PollImmediate(time.Second, timeout, condition); err != nil {
  526. return fmt.Errorf("error waiting for healthCheckNodePort: expected at least %d succeed=%v on %v%v, got %d", threshold, expectSucceed, host, port, count)
  527. }
  528. return nil
  529. }
  530. func testHTTPHealthCheckNodePort(ip string, port int, request string) (bool, error) {
  531. ipPort := net.JoinHostPort(ip, strconv.Itoa(port))
  532. url := fmt.Sprintf("http://%s%s", ipPort, request)
  533. if ip == "" || port == 0 {
  534. framework.Failf("Got empty IP for reachability check (%s)", url)
  535. return false, fmt.Errorf("invalid input ip or port")
  536. }
  537. framework.Logf("Testing HTTP health check on %v", url)
  538. resp, err := httpGetNoConnectionPoolTimeout(url, 5*time.Second)
  539. if err != nil {
  540. framework.Logf("Got error testing for reachability of %s: %v", url, err)
  541. return false, err
  542. }
  543. defer resp.Body.Close()
  544. if err != nil {
  545. framework.Logf("Got error reading response from %s: %v", url, err)
  546. return false, err
  547. }
  548. // HealthCheck responder returns 503 for no local endpoints
  549. if resp.StatusCode == 503 {
  550. return false, nil
  551. }
  552. // HealthCheck responder returns 200 for non-zero local endpoints
  553. if resp.StatusCode == 200 {
  554. return true, nil
  555. }
  556. return false, fmt.Errorf("unexpected HTTP response code %s from health check responder at %s", resp.Status, url)
  557. }
  558. // Does an HTTP GET, but does not reuse TCP connections
  559. // This masks problems where the iptables rule has changed, but we don't see it
  560. func httpGetNoConnectionPoolTimeout(url string, timeout time.Duration) (*http.Response, error) {
  561. tr := utilnet.SetTransportDefaults(&http.Transport{
  562. DisableKeepAlives: true,
  563. })
  564. client := &http.Client{
  565. Transport: tr,
  566. Timeout: timeout,
  567. }
  568. return client.Get(url)
  569. }
  570. func getServeHostnameService(name string) *v1.Service {
  571. svc := defaultServeHostnameService.DeepCopy()
  572. svc.ObjectMeta.Name = name
  573. svc.Spec.Selector["name"] = name
  574. return svc
  575. }
  576. // restartKubeProxy restarts kube-proxy on the given host.
  577. func restartKubeProxy(host string) error {
  578. // TODO: Make it work for all providers.
  579. if !framework.ProviderIs("gce", "gke", "aws") {
  580. return fmt.Errorf("unsupported provider for restartKubeProxy: %s", framework.TestContext.Provider)
  581. }
  582. // kubelet will restart the kube-proxy since it's running in a static pod
  583. framework.Logf("Killing kube-proxy on node %v", host)
  584. result, err := e2essh.SSH("sudo pkill kube-proxy", host, framework.TestContext.Provider)
  585. if err != nil || result.Code != 0 {
  586. e2essh.LogResult(result)
  587. return fmt.Errorf("couldn't restart kube-proxy: %v", err)
  588. }
  589. // wait for kube-proxy to come back up
  590. sshCmd := "sudo /bin/sh -c 'pgrep kube-proxy | wc -l'"
  591. err = wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) {
  592. framework.Logf("Waiting for kubeproxy to come back up with %v on %v", sshCmd, host)
  593. result, err := e2essh.SSH(sshCmd, host, framework.TestContext.Provider)
  594. if err != nil {
  595. return false, err
  596. }
  597. if result.Code != 0 {
  598. e2essh.LogResult(result)
  599. return false, fmt.Errorf("failed to run command, exited %d", result.Code)
  600. }
  601. if result.Stdout == "0\n" {
  602. return false, nil
  603. }
  604. framework.Logf("kube-proxy is back up.")
  605. return true, nil
  606. })
  607. if err != nil {
  608. return fmt.Errorf("kube-proxy didn't recover: %v", err)
  609. }
  610. return nil
  611. }
  612. // waitForApiserverUp waits for the kube-apiserver to be up.
  613. func waitForApiserverUp(c clientset.Interface) error {
  614. for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
  615. body, err := c.CoreV1().RESTClient().Get().AbsPath("/healthz").Do(context.TODO()).Raw()
  616. if err == nil && string(body) == "ok" {
  617. return nil
  618. }
  619. }
  620. return fmt.Errorf("waiting for apiserver timed out")
  621. }
  622. var _ = SIGDescribe("Services", func() {
  623. f := framework.NewDefaultFramework("services")
  624. var cs clientset.Interface
  625. serviceLBNames := []string{}
  626. ginkgo.BeforeEach(func() {
  627. cs = f.ClientSet
  628. })
  629. ginkgo.AfterEach(func() {
  630. if ginkgo.CurrentGinkgoTestDescription().Failed {
  631. DescribeSvc(f.Namespace.Name)
  632. }
  633. for _, lb := range serviceLBNames {
  634. framework.Logf("cleaning load balancer resource for %s", lb)
  635. e2eservice.CleanupServiceResources(cs, lb, framework.TestContext.CloudConfig.Region, framework.TestContext.CloudConfig.Zone)
  636. }
  637. //reset serviceLBNames
  638. serviceLBNames = []string{}
  639. })
  640. // 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.
  641. /*
  642. Release : v1.9
  643. Testname: Kubernetes Service
  644. Description: By default when a kubernetes cluster is running there MUST be a 'kubernetes' service running in the cluster.
  645. */
  646. framework.ConformanceIt("should provide secure master service ", func() {
  647. _, err := cs.CoreV1().Services(metav1.NamespaceDefault).Get(context.TODO(), "kubernetes", metav1.GetOptions{})
  648. framework.ExpectNoError(err, "failed to fetch the service object for the service named kubernetes")
  649. })
  650. /*
  651. Release : v1.9
  652. Testname: Service, endpoints
  653. 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.
  654. */
  655. framework.ConformanceIt("should serve a basic endpoint from pods ", func() {
  656. serviceName := "endpoint-test2"
  657. ns := f.Namespace.Name
  658. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  659. ginkgo.By("creating service " + serviceName + " in namespace " + ns)
  660. defer func() {
  661. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  662. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName, ns)
  663. }()
  664. _, err := jig.CreateTCPServiceWithPort(nil, 80)
  665. framework.ExpectNoError(err)
  666. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{})
  667. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  668. names := map[string]bool{}
  669. defer func() {
  670. for name := range names {
  671. err := cs.CoreV1().Pods(ns).Delete(context.TODO(), name, nil)
  672. framework.ExpectNoError(err, "failed to delete pod: %s in namespace: %s", name, ns)
  673. }
  674. }()
  675. name1 := "pod1"
  676. name2 := "pod2"
  677. createPodOrFail(cs, ns, name1, jig.Labels, []v1.ContainerPort{{ContainerPort: 80}})
  678. names[name1] = true
  679. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{name1: {80}})
  680. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  681. createPodOrFail(cs, ns, name2, jig.Labels, []v1.ContainerPort{{ContainerPort: 80}})
  682. names[name2] = true
  683. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{name1: {80}, name2: {80}})
  684. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  685. e2epod.DeletePodOrFail(cs, ns, name1)
  686. delete(names, name1)
  687. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{name2: {80}})
  688. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  689. e2epod.DeletePodOrFail(cs, ns, name2)
  690. delete(names, name2)
  691. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{})
  692. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  693. })
  694. /*
  695. Release : v1.9
  696. Testname: Service, endpoints with multiple ports
  697. 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.
  698. */
  699. framework.ConformanceIt("should serve multiport endpoints from pods ", func() {
  700. // repacking functionality is intentionally not tested here - it's better to test it in an integration test.
  701. serviceName := "multi-endpoint-test"
  702. ns := f.Namespace.Name
  703. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  704. defer func() {
  705. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  706. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName, ns)
  707. }()
  708. svc1port := "svc1"
  709. svc2port := "svc2"
  710. ginkgo.By("creating service " + serviceName + " in namespace " + ns)
  711. _, err := jig.CreateTCPService(func(service *v1.Service) {
  712. service.Spec.Ports = []v1.ServicePort{
  713. {
  714. Name: "portname1",
  715. Port: 80,
  716. TargetPort: intstr.FromString(svc1port),
  717. },
  718. {
  719. Name: "portname2",
  720. Port: 81,
  721. TargetPort: intstr.FromString(svc2port),
  722. },
  723. }
  724. })
  725. framework.ExpectNoError(err)
  726. port1 := 100
  727. port2 := 101
  728. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{})
  729. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  730. names := map[string]bool{}
  731. defer func() {
  732. for name := range names {
  733. err := cs.CoreV1().Pods(ns).Delete(context.TODO(), name, nil)
  734. framework.ExpectNoError(err, "failed to delete pod: %s in namespace: %s", name, ns)
  735. }
  736. }()
  737. containerPorts1 := []v1.ContainerPort{
  738. {
  739. Name: svc1port,
  740. ContainerPort: int32(port1),
  741. },
  742. }
  743. containerPorts2 := []v1.ContainerPort{
  744. {
  745. Name: svc2port,
  746. ContainerPort: int32(port2),
  747. },
  748. }
  749. podname1 := "pod1"
  750. podname2 := "pod2"
  751. createPodOrFail(cs, ns, podname1, jig.Labels, containerPorts1)
  752. names[podname1] = true
  753. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podname1: {port1}})
  754. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  755. createPodOrFail(cs, ns, podname2, jig.Labels, containerPorts2)
  756. names[podname2] = true
  757. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podname1: {port1}, podname2: {port2}})
  758. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  759. e2epod.DeletePodOrFail(cs, ns, podname1)
  760. delete(names, podname1)
  761. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{podname2: {port2}})
  762. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  763. e2epod.DeletePodOrFail(cs, ns, podname2)
  764. delete(names, podname2)
  765. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{})
  766. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  767. })
  768. ginkgo.It("should preserve source pod IP for traffic thru service cluster IP [LinuxOnly]", func() {
  769. // this test is creating a pod with HostNetwork=true, which is not supported on Windows.
  770. e2eskipper.SkipIfNodeOSDistroIs("windows")
  771. // This behavior is not supported if Kube-proxy is in "userspace" mode.
  772. // So we check the kube-proxy mode and skip this test if that's the case.
  773. if proxyMode, err := proxyMode(f); err == nil {
  774. if proxyMode == "userspace" {
  775. e2eskipper.Skipf("The test doesn't work with kube-proxy in userspace mode")
  776. }
  777. } else {
  778. framework.Logf("Couldn't detect KubeProxy mode - test failure may be expected: %v", err)
  779. }
  780. serviceName := "sourceip-test"
  781. ns := f.Namespace.Name
  782. ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns)
  783. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  784. servicePort := 8080
  785. tcpService, err := jig.CreateTCPServiceWithPort(nil, int32(servicePort))
  786. framework.ExpectNoError(err)
  787. defer func() {
  788. framework.Logf("Cleaning up the sourceip test service")
  789. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  790. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName, ns)
  791. }()
  792. serviceIP := tcpService.Spec.ClusterIP
  793. framework.Logf("sourceip-test cluster ip: %s", serviceIP)
  794. ginkgo.By("Picking 2 Nodes to test whether source IP is preserved or not")
  795. nodes, err := e2enode.GetBoundedReadySchedulableNodes(cs, 2)
  796. framework.ExpectNoError(err)
  797. nodeCounts := len(nodes.Items)
  798. if nodeCounts < 2 {
  799. e2eskipper.Skipf("The test requires at least two ready nodes on %s, but found %v", framework.TestContext.Provider, nodeCounts)
  800. }
  801. ginkgo.By("Creating a webserver pod to be part of the TCP service which echoes back source ip")
  802. serverPodName := "echo-sourceip"
  803. pod := f.NewAgnhostPod(serverPodName, "netexec", "--http-port", strconv.Itoa(servicePort))
  804. pod.Labels = jig.Labels
  805. _, err = cs.CoreV1().Pods(ns).Create(context.TODO(), pod, metav1.CreateOptions{})
  806. framework.ExpectNoError(err)
  807. framework.ExpectNoError(f.WaitForPodReady(pod.Name))
  808. defer func() {
  809. framework.Logf("Cleaning up the echo server pod")
  810. err := cs.CoreV1().Pods(ns).Delete(context.TODO(), serverPodName, nil)
  811. framework.ExpectNoError(err, "failed to delete pod: %s on node", serverPodName)
  812. }()
  813. // Waiting for service to expose endpoint.
  814. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{serverPodName: {servicePort}})
  815. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  816. ginkgo.By("Creating pause pod deployment")
  817. deployment := createPausePodDeployment(cs, "pause-pod", ns, nodeCounts)
  818. defer func() {
  819. framework.Logf("Deleting deployment")
  820. err = cs.AppsV1().Deployments(ns).Delete(context.TODO(), deployment.Name, &metav1.DeleteOptions{})
  821. framework.ExpectNoError(err, "Failed to delete deployment %s", deployment.Name)
  822. }()
  823. framework.ExpectNoError(e2edeploy.WaitForDeploymentComplete(cs, deployment), "Failed to complete pause pod deployment")
  824. deployment, err = cs.AppsV1().Deployments(ns).Get(context.TODO(), deployment.Name, metav1.GetOptions{})
  825. framework.ExpectNoError(err, "Error in retrieving pause pod deployment")
  826. labelSelector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
  827. pausePods, err := cs.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelector.String()})
  828. framework.ExpectNoError(err, "Error in listing pods associated with pause pod deployments")
  829. gomega.Expect(pausePods.Items[0].Spec.NodeName).ToNot(gomega.Equal(pausePods.Items[1].Spec.NodeName))
  830. serviceAddress := net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))
  831. for _, pausePod := range pausePods.Items {
  832. sourceIP, execPodIP := execSourceipTest(pausePod, serviceAddress)
  833. ginkgo.By("Verifying the preserved source ip")
  834. framework.ExpectEqual(sourceIP, execPodIP)
  835. }
  836. })
  837. ginkgo.It("should allow pods to hairpin back to themselves through services", func() {
  838. serviceName := "hairpin-test"
  839. ns := f.Namespace.Name
  840. ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns)
  841. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  842. servicePort := 8080
  843. svc, err := jig.CreateTCPServiceWithPort(nil, int32(servicePort))
  844. framework.ExpectNoError(err)
  845. serviceIP := svc.Spec.ClusterIP
  846. framework.Logf("hairpin-test cluster ip: %s", serviceIP)
  847. ginkgo.By("creating a client/server pod")
  848. serverPodName := "hairpin"
  849. podTemplate := f.NewAgnhostPod(serverPodName, "netexec", "--http-port", strconv.Itoa(servicePort))
  850. podTemplate.Labels = jig.Labels
  851. pod, err := cs.CoreV1().Pods(ns).Create(context.TODO(), podTemplate, metav1.CreateOptions{})
  852. framework.ExpectNoError(err)
  853. framework.ExpectNoError(f.WaitForPodReady(pod.Name))
  854. ginkgo.By("waiting for the service to expose an endpoint")
  855. err = validateEndpointsPorts(cs, ns, serviceName, portsByPodName{serverPodName: {servicePort}})
  856. framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", serviceName, ns)
  857. ginkgo.By("Checking if the pod can reach itself")
  858. err = jig.CheckServiceReachability(svc, pod)
  859. framework.ExpectNoError(err)
  860. })
  861. ginkgo.It("should be able to up and down services", func() {
  862. // TODO: use the ServiceTestJig here
  863. // this test uses e2essh.NodeSSHHosts that does not work if a Node only reports LegacyHostIP
  864. e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
  865. // this test does not work if the Node does not support SSH Key
  866. e2eskipper.SkipUnlessSSHKeyPresent()
  867. ns := f.Namespace.Name
  868. numPods, servicePort := 3, defaultServeHostnameServicePort
  869. svc1 := "up-down-1"
  870. svc2 := "up-down-2"
  871. svc3 := "up-down-3"
  872. ginkgo.By("creating " + svc1 + " in namespace " + ns)
  873. podNames1, svc1IP, err := StartServeHostnameService(cs, getServeHostnameService(svc1), ns, numPods)
  874. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc1, ns)
  875. ginkgo.By("creating " + svc2 + " in namespace " + ns)
  876. podNames2, svc2IP, err := StartServeHostnameService(cs, getServeHostnameService(svc2), ns, numPods)
  877. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc2, ns)
  878. hosts, err := e2essh.NodeSSHHosts(cs)
  879. framework.ExpectNoError(err, "failed to find external/internal IPs for every node")
  880. if len(hosts) == 0 {
  881. framework.Failf("No ssh-able nodes")
  882. }
  883. host := hosts[0]
  884. ginkgo.By("verifying service " + svc1 + " is up")
  885. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames1, svc1IP, servicePort))
  886. ginkgo.By("verifying service " + svc2 + " is up")
  887. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames2, svc2IP, servicePort))
  888. // Stop service 1 and make sure it is gone.
  889. ginkgo.By("stopping service " + svc1)
  890. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, svc1))
  891. ginkgo.By("verifying service " + svc1 + " is not up")
  892. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svc1IP, servicePort))
  893. ginkgo.By("verifying service " + svc2 + " is still up")
  894. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames2, svc2IP, servicePort))
  895. // Start another service and verify both are up.
  896. ginkgo.By("creating service " + svc3 + " in namespace " + ns)
  897. podNames3, svc3IP, err := StartServeHostnameService(cs, getServeHostnameService(svc3), ns, numPods)
  898. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc3, ns)
  899. if svc2IP == svc3IP {
  900. framework.Failf("service IPs conflict: %v", svc2IP)
  901. }
  902. ginkgo.By("verifying service " + svc2 + " is still up")
  903. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames2, svc2IP, servicePort))
  904. ginkgo.By("verifying service " + svc3 + " is up")
  905. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames3, svc3IP, servicePort))
  906. })
  907. ginkgo.It("should work after restarting kube-proxy [Disruptive]", func() {
  908. // TODO: use the ServiceTestJig here
  909. e2eskipper.SkipUnlessProviderIs("gce", "gke")
  910. e2eskipper.SkipUnlessSSHKeyPresent()
  911. ns := f.Namespace.Name
  912. numPods, servicePort := 3, defaultServeHostnameServicePort
  913. svc1 := "restart-proxy-1"
  914. svc2 := "restart-proxy-2"
  915. defer func() {
  916. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, svc1))
  917. }()
  918. podNames1, svc1IP, err := StartServeHostnameService(cs, getServeHostnameService(svc1), ns, numPods)
  919. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc1, ns)
  920. defer func() {
  921. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, svc2))
  922. }()
  923. podNames2, svc2IP, err := StartServeHostnameService(cs, getServeHostnameService(svc2), ns, numPods)
  924. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc2, ns)
  925. if svc1IP == svc2IP {
  926. framework.Failf("VIPs conflict: %v", svc1IP)
  927. }
  928. hosts, err := e2essh.NodeSSHHosts(cs)
  929. framework.ExpectNoError(err, "failed to find external/internal IPs for every node")
  930. if len(hosts) == 0 {
  931. framework.Failf("No ssh-able nodes")
  932. }
  933. host := hosts[0]
  934. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames1, svc1IP, servicePort))
  935. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames2, svc2IP, servicePort))
  936. ginkgo.By(fmt.Sprintf("Restarting kube-proxy on %v", host))
  937. if err := restartKubeProxy(host); err != nil {
  938. framework.Failf("error restarting kube-proxy: %v", err)
  939. }
  940. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames1, svc1IP, servicePort))
  941. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames2, svc2IP, servicePort))
  942. })
  943. ginkgo.It("should work after restarting apiserver [Disruptive]", func() {
  944. // TODO: use the ServiceTestJig here
  945. e2eskipper.SkipUnlessProviderIs("gce", "gke")
  946. e2eskipper.SkipUnlessSSHKeyPresent()
  947. ns := f.Namespace.Name
  948. numPods, servicePort := 3, 80
  949. svc1 := "restart-apiserver-1"
  950. svc2 := "restart-apiserver-2"
  951. defer func() {
  952. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, svc1))
  953. }()
  954. podNames1, svc1IP, err := StartServeHostnameService(cs, getServeHostnameService(svc1), ns, numPods)
  955. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc1, ns)
  956. hosts, err := e2essh.NodeSSHHosts(cs)
  957. framework.ExpectNoError(err, "failed to find external/internal IPs for every node")
  958. if len(hosts) == 0 {
  959. framework.Failf("No ssh-able nodes")
  960. }
  961. host := hosts[0]
  962. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames1, svc1IP, servicePort))
  963. // Restart apiserver
  964. ginkgo.By("Restarting apiserver")
  965. if err := framework.RestartApiserver(ns, cs); err != nil {
  966. framework.Failf("error restarting apiserver: %v", err)
  967. }
  968. ginkgo.By("Waiting for apiserver to come up by polling /healthz")
  969. if err := waitForApiserverUp(cs); err != nil {
  970. framework.Failf("error while waiting for apiserver up: %v", err)
  971. }
  972. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames1, svc1IP, servicePort))
  973. // Create a new service and check if it's not reusing IP.
  974. defer func() {
  975. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, svc2))
  976. }()
  977. podNames2, svc2IP, err := StartServeHostnameService(cs, getServeHostnameService(svc2), ns, numPods)
  978. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc2, ns)
  979. if svc1IP == svc2IP {
  980. framework.Failf("VIPs conflict: %v", svc1IP)
  981. }
  982. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames1, svc1IP, servicePort))
  983. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podNames2, svc2IP, servicePort))
  984. })
  985. /*
  986. Release : v1.16
  987. Testname: Service, NodePort Service
  988. Description: Create a TCP NodePort service, and test reachability from a client Pod.
  989. The client Pod MUST be able to access the NodePort service by service name and cluster
  990. IP on the service port, and on nodes' internal and external IPs on the NodePort.
  991. */
  992. framework.ConformanceIt("should be able to create a functioning NodePort service", func() {
  993. serviceName := "nodeport-test"
  994. ns := f.Namespace.Name
  995. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  996. ginkgo.By("creating service " + serviceName + " with type=NodePort in namespace " + ns)
  997. nodePortService, err := jig.CreateTCPService(func(svc *v1.Service) {
  998. svc.Spec.Type = v1.ServiceTypeNodePort
  999. svc.Spec.Ports = []v1.ServicePort{
  1000. {Port: 80, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(9376)},
  1001. }
  1002. })
  1003. framework.ExpectNoError(err)
  1004. err = jig.CreateServicePods(2)
  1005. framework.ExpectNoError(err)
  1006. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
  1007. err = jig.CheckServiceReachability(nodePortService, execPod)
  1008. framework.ExpectNoError(err)
  1009. })
  1010. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  1011. ginkgo.It("should be able to change the type and ports of a service [Slow] [DisabledForLargeClusters]", func() {
  1012. // requires cloud load-balancer support
  1013. e2eskipper.SkipUnlessProviderIs("gce", "gke", "aws")
  1014. loadBalancerSupportsUDP := !framework.ProviderIs("aws")
  1015. loadBalancerLagTimeout := e2eservice.LoadBalancerLagTimeoutDefault
  1016. if framework.ProviderIs("aws") {
  1017. loadBalancerLagTimeout = e2eservice.LoadBalancerLagTimeoutAWS
  1018. }
  1019. loadBalancerCreateTimeout := e2eservice.GetServiceLoadBalancerCreationTimeout(cs)
  1020. // This test is more monolithic than we'd like because LB turnup can be
  1021. // very slow, so we lumped all the tests into one LB lifecycle.
  1022. serviceName := "mutability-test"
  1023. ns1 := f.Namespace.Name // LB1 in ns1 on TCP
  1024. framework.Logf("namespace for TCP test: %s", ns1)
  1025. ginkgo.By("creating a second namespace")
  1026. namespacePtr, err := f.CreateNamespace("services", nil)
  1027. framework.ExpectNoError(err, "failed to create namespace")
  1028. ns2 := namespacePtr.Name // LB2 in ns2 on UDP
  1029. framework.Logf("namespace for UDP test: %s", ns2)
  1030. nodeIP, err := e2enode.PickIP(cs) // for later
  1031. framework.ExpectNoError(err)
  1032. // Test TCP and UDP Services. Services with the same name in different
  1033. // namespaces should get different node ports and load balancers.
  1034. ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns1)
  1035. tcpJig := e2eservice.NewTestJig(cs, ns1, serviceName)
  1036. tcpService, err := tcpJig.CreateTCPService(nil)
  1037. framework.ExpectNoError(err)
  1038. ginkgo.By("creating a UDP service " + serviceName + " with type=ClusterIP in namespace " + ns2)
  1039. udpJig := e2eservice.NewTestJig(cs, ns2, serviceName)
  1040. udpService, err := udpJig.CreateUDPService(nil)
  1041. framework.ExpectNoError(err)
  1042. ginkgo.By("verifying that TCP and UDP use the same port")
  1043. if tcpService.Spec.Ports[0].Port != udpService.Spec.Ports[0].Port {
  1044. framework.Failf("expected to use the same port for TCP and UDP")
  1045. }
  1046. svcPort := int(tcpService.Spec.Ports[0].Port)
  1047. framework.Logf("service port (TCP and UDP): %d", svcPort)
  1048. ginkgo.By("creating a pod to be part of the TCP service " + serviceName)
  1049. _, err = tcpJig.Run(nil)
  1050. framework.ExpectNoError(err)
  1051. ginkgo.By("creating a pod to be part of the UDP service " + serviceName)
  1052. _, err = udpJig.Run(nil)
  1053. framework.ExpectNoError(err)
  1054. // Change the services to NodePort.
  1055. ginkgo.By("changing the TCP service to type=NodePort")
  1056. tcpService, err = tcpJig.UpdateService(func(s *v1.Service) {
  1057. s.Spec.Type = v1.ServiceTypeNodePort
  1058. })
  1059. framework.ExpectNoError(err)
  1060. tcpNodePort := int(tcpService.Spec.Ports[0].NodePort)
  1061. framework.Logf("TCP node port: %d", tcpNodePort)
  1062. ginkgo.By("changing the UDP service to type=NodePort")
  1063. udpService, err = udpJig.UpdateService(func(s *v1.Service) {
  1064. s.Spec.Type = v1.ServiceTypeNodePort
  1065. })
  1066. framework.ExpectNoError(err)
  1067. udpNodePort := int(udpService.Spec.Ports[0].NodePort)
  1068. framework.Logf("UDP node port: %d", udpNodePort)
  1069. ginkgo.By("hitting the TCP service's NodePort")
  1070. e2eservice.TestReachableHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1071. ginkgo.By("hitting the UDP service's NodePort")
  1072. testReachableUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1073. // Change the services to LoadBalancer.
  1074. // Here we test that LoadBalancers can receive static IP addresses. This isn't
  1075. // necessary, but is an additional feature this monolithic test checks.
  1076. requestedIP := ""
  1077. staticIPName := ""
  1078. if framework.ProviderIs("gce", "gke") {
  1079. ginkgo.By("creating a static load balancer IP")
  1080. staticIPName = fmt.Sprintf("e2e-external-lb-test-%s", framework.RunID)
  1081. gceCloud, err := gce.GetGCECloud()
  1082. framework.ExpectNoError(err, "failed to get GCE cloud provider")
  1083. err = gceCloud.ReserveRegionAddress(&compute.Address{Name: staticIPName}, gceCloud.Region())
  1084. defer func() {
  1085. if staticIPName != "" {
  1086. // Release GCE static IP - this is not kube-managed and will not be automatically released.
  1087. if err := gceCloud.DeleteRegionAddress(staticIPName, gceCloud.Region()); err != nil {
  1088. framework.Logf("failed to release static IP %s: %v", staticIPName, err)
  1089. }
  1090. }
  1091. }()
  1092. framework.ExpectNoError(err, "failed to create region address: %s", staticIPName)
  1093. reservedAddr, err := gceCloud.GetRegionAddress(staticIPName, gceCloud.Region())
  1094. framework.ExpectNoError(err, "failed to get region address: %s", staticIPName)
  1095. requestedIP = reservedAddr.Address
  1096. framework.Logf("Allocated static load balancer IP: %s", requestedIP)
  1097. }
  1098. ginkgo.By("changing the TCP service to type=LoadBalancer")
  1099. tcpService, err = tcpJig.UpdateService(func(s *v1.Service) {
  1100. s.Spec.LoadBalancerIP = requestedIP // will be "" if not applicable
  1101. s.Spec.Type = v1.ServiceTypeLoadBalancer
  1102. })
  1103. framework.ExpectNoError(err)
  1104. if loadBalancerSupportsUDP {
  1105. ginkgo.By("changing the UDP service to type=LoadBalancer")
  1106. udpService, err = udpJig.UpdateService(func(s *v1.Service) {
  1107. s.Spec.Type = v1.ServiceTypeLoadBalancer
  1108. })
  1109. framework.ExpectNoError(err)
  1110. }
  1111. serviceLBNames = append(serviceLBNames, cloudprovider.DefaultLoadBalancerName(tcpService))
  1112. if loadBalancerSupportsUDP {
  1113. serviceLBNames = append(serviceLBNames, cloudprovider.DefaultLoadBalancerName(udpService))
  1114. }
  1115. ginkgo.By("waiting for the TCP service to have a load balancer")
  1116. // Wait for the load balancer to be created asynchronously
  1117. tcpService, err = tcpJig.WaitForLoadBalancer(loadBalancerCreateTimeout)
  1118. framework.ExpectNoError(err)
  1119. if int(tcpService.Spec.Ports[0].NodePort) != tcpNodePort {
  1120. framework.Failf("TCP Spec.Ports[0].NodePort changed (%d -> %d) when not expected", tcpNodePort, tcpService.Spec.Ports[0].NodePort)
  1121. }
  1122. if requestedIP != "" && e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]) != requestedIP {
  1123. framework.Failf("unexpected TCP Status.LoadBalancer.Ingress (expected %s, got %s)", requestedIP, e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]))
  1124. }
  1125. tcpIngressIP := e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0])
  1126. framework.Logf("TCP load balancer: %s", tcpIngressIP)
  1127. if framework.ProviderIs("gce", "gke") {
  1128. // Do this as early as possible, which overrides the `defer` above.
  1129. // This is mostly out of fear of leaking the IP in a timeout case
  1130. // (as of this writing we're not 100% sure where the leaks are
  1131. // coming from, so this is first-aid rather than surgery).
  1132. ginkgo.By("demoting the static IP to ephemeral")
  1133. if staticIPName != "" {
  1134. gceCloud, err := gce.GetGCECloud()
  1135. framework.ExpectNoError(err, "failed to get GCE cloud provider")
  1136. // Deleting it after it is attached "demotes" it to an
  1137. // ephemeral IP, which can be auto-released.
  1138. if err := gceCloud.DeleteRegionAddress(staticIPName, gceCloud.Region()); err != nil {
  1139. framework.Failf("failed to release static IP %s: %v", staticIPName, err)
  1140. }
  1141. staticIPName = ""
  1142. }
  1143. }
  1144. var udpIngressIP string
  1145. if loadBalancerSupportsUDP {
  1146. ginkgo.By("waiting for the UDP service to have a load balancer")
  1147. // 2nd one should be faster since they ran in parallel.
  1148. udpService, err = udpJig.WaitForLoadBalancer(loadBalancerCreateTimeout)
  1149. framework.ExpectNoError(err)
  1150. if int(udpService.Spec.Ports[0].NodePort) != udpNodePort {
  1151. framework.Failf("UDP Spec.Ports[0].NodePort changed (%d -> %d) when not expected", udpNodePort, udpService.Spec.Ports[0].NodePort)
  1152. }
  1153. udpIngressIP = e2eservice.GetIngressPoint(&udpService.Status.LoadBalancer.Ingress[0])
  1154. framework.Logf("UDP load balancer: %s", udpIngressIP)
  1155. ginkgo.By("verifying that TCP and UDP use different load balancers")
  1156. if tcpIngressIP == udpIngressIP {
  1157. framework.Failf("Load balancers are not different: %s", e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]))
  1158. }
  1159. }
  1160. ginkgo.By("hitting the TCP service's NodePort")
  1161. e2eservice.TestReachableHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1162. ginkgo.By("hitting the UDP service's NodePort")
  1163. testReachableUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1164. ginkgo.By("hitting the TCP service's LoadBalancer")
  1165. e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, loadBalancerLagTimeout)
  1166. if loadBalancerSupportsUDP {
  1167. ginkgo.By("hitting the UDP service's LoadBalancer")
  1168. testReachableUDP(udpIngressIP, svcPort, loadBalancerLagTimeout)
  1169. }
  1170. // Change the services' node ports.
  1171. ginkgo.By("changing the TCP service's NodePort")
  1172. tcpService, err = tcpJig.ChangeServiceNodePort(tcpNodePort)
  1173. framework.ExpectNoError(err)
  1174. tcpNodePortOld := tcpNodePort
  1175. tcpNodePort = int(tcpService.Spec.Ports[0].NodePort)
  1176. if tcpNodePort == tcpNodePortOld {
  1177. framework.Failf("TCP Spec.Ports[0].NodePort (%d) did not change", tcpNodePort)
  1178. }
  1179. if e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]) != tcpIngressIP {
  1180. framework.Failf("TCP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected", tcpIngressIP, e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]))
  1181. }
  1182. framework.Logf("TCP node port: %d", tcpNodePort)
  1183. ginkgo.By("changing the UDP service's NodePort")
  1184. udpService, err = udpJig.ChangeServiceNodePort(udpNodePort)
  1185. framework.ExpectNoError(err)
  1186. udpNodePortOld := udpNodePort
  1187. udpNodePort = int(udpService.Spec.Ports[0].NodePort)
  1188. if udpNodePort == udpNodePortOld {
  1189. framework.Failf("UDP Spec.Ports[0].NodePort (%d) did not change", udpNodePort)
  1190. }
  1191. if loadBalancerSupportsUDP && e2eservice.GetIngressPoint(&udpService.Status.LoadBalancer.Ingress[0]) != udpIngressIP {
  1192. framework.Failf("UDP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected", udpIngressIP, e2eservice.GetIngressPoint(&udpService.Status.LoadBalancer.Ingress[0]))
  1193. }
  1194. framework.Logf("UDP node port: %d", udpNodePort)
  1195. ginkgo.By("hitting the TCP service's new NodePort")
  1196. e2eservice.TestReachableHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1197. ginkgo.By("hitting the UDP service's new NodePort")
  1198. testReachableUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1199. ginkgo.By("checking the old TCP NodePort is closed")
  1200. testNotReachableHTTP(nodeIP, tcpNodePortOld, e2eservice.KubeProxyLagTimeout)
  1201. ginkgo.By("checking the old UDP NodePort is closed")
  1202. testNotReachableUDP(nodeIP, udpNodePortOld, e2eservice.KubeProxyLagTimeout)
  1203. ginkgo.By("hitting the TCP service's LoadBalancer")
  1204. e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, loadBalancerLagTimeout)
  1205. if loadBalancerSupportsUDP {
  1206. ginkgo.By("hitting the UDP service's LoadBalancer")
  1207. testReachableUDP(udpIngressIP, svcPort, loadBalancerLagTimeout)
  1208. }
  1209. // Change the services' main ports.
  1210. ginkgo.By("changing the TCP service's port")
  1211. tcpService, err = tcpJig.UpdateService(func(s *v1.Service) {
  1212. s.Spec.Ports[0].Port++
  1213. })
  1214. framework.ExpectNoError(err)
  1215. svcPortOld := svcPort
  1216. svcPort = int(tcpService.Spec.Ports[0].Port)
  1217. if svcPort == svcPortOld {
  1218. framework.Failf("TCP Spec.Ports[0].Port (%d) did not change", svcPort)
  1219. }
  1220. if int(tcpService.Spec.Ports[0].NodePort) != tcpNodePort {
  1221. framework.Failf("TCP Spec.Ports[0].NodePort (%d) changed", tcpService.Spec.Ports[0].NodePort)
  1222. }
  1223. if e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]) != tcpIngressIP {
  1224. framework.Failf("TCP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected", tcpIngressIP, e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0]))
  1225. }
  1226. ginkgo.By("changing the UDP service's port")
  1227. udpService, err = udpJig.UpdateService(func(s *v1.Service) {
  1228. s.Spec.Ports[0].Port++
  1229. })
  1230. framework.ExpectNoError(err)
  1231. if int(udpService.Spec.Ports[0].Port) != svcPort {
  1232. framework.Failf("UDP Spec.Ports[0].Port (%d) did not change", udpService.Spec.Ports[0].Port)
  1233. }
  1234. if int(udpService.Spec.Ports[0].NodePort) != udpNodePort {
  1235. framework.Failf("UDP Spec.Ports[0].NodePort (%d) changed", udpService.Spec.Ports[0].NodePort)
  1236. }
  1237. if loadBalancerSupportsUDP && e2eservice.GetIngressPoint(&udpService.Status.LoadBalancer.Ingress[0]) != udpIngressIP {
  1238. framework.Failf("UDP Status.LoadBalancer.Ingress changed (%s -> %s) when not expected", udpIngressIP, e2eservice.GetIngressPoint(&udpService.Status.LoadBalancer.Ingress[0]))
  1239. }
  1240. framework.Logf("service port (TCP and UDP): %d", svcPort)
  1241. ginkgo.By("hitting the TCP service's NodePort")
  1242. e2eservice.TestReachableHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1243. ginkgo.By("hitting the UDP service's NodePort")
  1244. testReachableUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1245. ginkgo.By("hitting the TCP service's LoadBalancer")
  1246. e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, loadBalancerCreateTimeout)
  1247. if loadBalancerSupportsUDP {
  1248. ginkgo.By("hitting the UDP service's LoadBalancer")
  1249. testReachableUDP(udpIngressIP, svcPort, loadBalancerCreateTimeout)
  1250. }
  1251. ginkgo.By("Scaling the pods to 0")
  1252. err = tcpJig.Scale(0)
  1253. framework.ExpectNoError(err)
  1254. err = udpJig.Scale(0)
  1255. framework.ExpectNoError(err)
  1256. ginkgo.By("looking for ICMP REJECT on the TCP service's NodePort")
  1257. testRejectedHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1258. ginkgo.By("looking for ICMP REJECT on the UDP service's NodePort")
  1259. testRejectedUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1260. ginkgo.By("looking for ICMP REJECT on the TCP service's LoadBalancer")
  1261. testRejectedHTTP(tcpIngressIP, svcPort, loadBalancerCreateTimeout)
  1262. if loadBalancerSupportsUDP {
  1263. ginkgo.By("looking for ICMP REJECT on the UDP service's LoadBalancer")
  1264. testRejectedUDP(udpIngressIP, svcPort, loadBalancerCreateTimeout)
  1265. }
  1266. ginkgo.By("Scaling the pods to 1")
  1267. err = tcpJig.Scale(1)
  1268. framework.ExpectNoError(err)
  1269. err = udpJig.Scale(1)
  1270. framework.ExpectNoError(err)
  1271. ginkgo.By("hitting the TCP service's NodePort")
  1272. e2eservice.TestReachableHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1273. ginkgo.By("hitting the UDP service's NodePort")
  1274. testReachableUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1275. ginkgo.By("hitting the TCP service's LoadBalancer")
  1276. e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, loadBalancerCreateTimeout)
  1277. if loadBalancerSupportsUDP {
  1278. ginkgo.By("hitting the UDP service's LoadBalancer")
  1279. testReachableUDP(udpIngressIP, svcPort, loadBalancerCreateTimeout)
  1280. }
  1281. // Change the services back to ClusterIP.
  1282. ginkgo.By("changing TCP service back to type=ClusterIP")
  1283. _, err = tcpJig.UpdateService(func(s *v1.Service) {
  1284. s.Spec.Type = v1.ServiceTypeClusterIP
  1285. s.Spec.Ports[0].NodePort = 0
  1286. })
  1287. framework.ExpectNoError(err)
  1288. // Wait for the load balancer to be destroyed asynchronously
  1289. _, err = tcpJig.WaitForLoadBalancerDestroy(tcpIngressIP, svcPort, loadBalancerCreateTimeout)
  1290. framework.ExpectNoError(err)
  1291. ginkgo.By("changing UDP service back to type=ClusterIP")
  1292. _, err = udpJig.UpdateService(func(s *v1.Service) {
  1293. s.Spec.Type = v1.ServiceTypeClusterIP
  1294. s.Spec.Ports[0].NodePort = 0
  1295. })
  1296. framework.ExpectNoError(err)
  1297. if loadBalancerSupportsUDP {
  1298. // Wait for the load balancer to be destroyed asynchronously
  1299. _, err = udpJig.WaitForLoadBalancerDestroy(udpIngressIP, svcPort, loadBalancerCreateTimeout)
  1300. framework.ExpectNoError(err)
  1301. }
  1302. ginkgo.By("checking the TCP NodePort is closed")
  1303. testNotReachableHTTP(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout)
  1304. ginkgo.By("checking the UDP NodePort is closed")
  1305. testNotReachableUDP(nodeIP, udpNodePort, e2eservice.KubeProxyLagTimeout)
  1306. ginkgo.By("checking the TCP LoadBalancer is closed")
  1307. testNotReachableHTTP(tcpIngressIP, svcPort, loadBalancerLagTimeout)
  1308. if loadBalancerSupportsUDP {
  1309. ginkgo.By("checking the UDP LoadBalancer is closed")
  1310. testNotReachableUDP(udpIngressIP, svcPort, loadBalancerLagTimeout)
  1311. }
  1312. })
  1313. /*
  1314. Testname: Service, update NodePort, same port different protocol
  1315. Description: Create a service to accept TCP requests. By default, created service MUST be of type ClusterIP and an ClusterIP MUST be assigned to the service.
  1316. When service type is updated to NodePort supporting TCP protocol, it MUST be reachable on nodeIP over allocated NodePort to serve TCP requests.
  1317. When this NodePort service is updated to use two protocols i.e. TCP and UDP for same assigned service port 80, service update MUST be successful by allocating two NodePorts to the service and
  1318. service MUST be able to serve both TCP and UDP requests over same service port 80.
  1319. */
  1320. ginkgo.It("should be able to update service type to NodePort listening on same port number but different protocols", func() {
  1321. serviceName := "nodeport-update-service"
  1322. ns := f.Namespace.Name
  1323. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  1324. ginkgo.By("creating a TCP service " + serviceName + " with type=ClusterIP in namespace " + ns)
  1325. tcpService, err := jig.CreateTCPService(nil)
  1326. framework.ExpectNoError(err)
  1327. defer func() {
  1328. framework.Logf("Cleaning up the updating NodePorts test service")
  1329. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  1330. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName, ns)
  1331. }()
  1332. framework.Logf("Service Port TCP: %v", tcpService.Spec.Ports[0].Port)
  1333. ginkgo.By("changing the TCP service to type=NodePort")
  1334. nodePortService, err := jig.UpdateService(func(s *v1.Service) {
  1335. s.Spec.Type = v1.ServiceTypeNodePort
  1336. s.Spec.Ports = []v1.ServicePort{
  1337. {
  1338. Name: "tcp-port",
  1339. Port: 80,
  1340. Protocol: v1.ProtocolTCP,
  1341. TargetPort: intstr.FromInt(9376),
  1342. },
  1343. }
  1344. })
  1345. framework.ExpectNoError(err)
  1346. err = jig.CreateTCPUDPServicePods(2)
  1347. framework.ExpectNoError(err)
  1348. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
  1349. err = jig.CheckServiceReachability(nodePortService, execPod)
  1350. framework.ExpectNoError(err)
  1351. ginkgo.By("Updating NodePort service to listen TCP and UDP based requests over same Port")
  1352. nodePortService, err = jig.UpdateService(func(s *v1.Service) {
  1353. s.Spec.Type = v1.ServiceTypeNodePort
  1354. s.Spec.Ports = []v1.ServicePort{
  1355. {
  1356. Name: "tcp-port",
  1357. Port: 80,
  1358. Protocol: v1.ProtocolTCP,
  1359. TargetPort: intstr.FromInt(9376),
  1360. },
  1361. {
  1362. Name: "udp-port",
  1363. Port: 80,
  1364. Protocol: v1.ProtocolUDP,
  1365. TargetPort: intstr.FromInt(9376),
  1366. },
  1367. }
  1368. })
  1369. framework.ExpectNoError(err)
  1370. err = jig.CheckServiceReachability(nodePortService, execPod)
  1371. framework.ExpectNoError(err)
  1372. nodePortCounts := len(nodePortService.Spec.Ports)
  1373. framework.ExpectEqual(nodePortCounts, 2, "updated service should have two Ports but found %d Ports", nodePortCounts)
  1374. for _, port := range nodePortService.Spec.Ports {
  1375. framework.ExpectNotEqual(port.NodePort, 0, "NodePort service failed to allocate NodePort for Port %s", port.Name)
  1376. framework.Logf("NodePort service allocates NodePort: %d for Port: %s over Protocol: %s", port.NodePort, port.Name, port.Protocol)
  1377. }
  1378. })
  1379. /*
  1380. Release: v1.16
  1381. Testname: Service, change type, ExternalName to ClusterIP
  1382. Description: Create a service of type ExternalName, pointing to external DNS. ClusterIP MUST not be assigned to the service.
  1383. Update the service from ExternalName to ClusterIP by removing ExternalName entry, assigning port 80 as service port and TCP as protocol.
  1384. Service update MUST be successful by assigning ClusterIP to the service and it MUST be reachable over serviceName and ClusterIP on provided service port.
  1385. */
  1386. framework.ConformanceIt("should be able to change the type from ExternalName to ClusterIP", func() {
  1387. serviceName := "externalname-service"
  1388. ns := f.Namespace.Name
  1389. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  1390. ginkgo.By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns)
  1391. _, err := jig.CreateExternalNameService(nil)
  1392. framework.ExpectNoError(err)
  1393. defer func() {
  1394. framework.Logf("Cleaning up the ExternalName to ClusterIP test service")
  1395. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  1396. framework.ExpectNoError(err, "failed to delete service %s in namespace %s", serviceName, ns)
  1397. }()
  1398. ginkgo.By("changing the ExternalName service to type=ClusterIP")
  1399. clusterIPService, err := jig.UpdateService(func(s *v1.Service) {
  1400. s.Spec.Type = v1.ServiceTypeClusterIP
  1401. s.Spec.ExternalName = ""
  1402. s.Spec.Ports = []v1.ServicePort{
  1403. {Port: 80, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(9376)},
  1404. }
  1405. })
  1406. framework.ExpectNoError(err)
  1407. err = jig.CreateServicePods(2)
  1408. framework.ExpectNoError(err)
  1409. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
  1410. err = jig.CheckServiceReachability(clusterIPService, execPod)
  1411. framework.ExpectNoError(err)
  1412. })
  1413. /*
  1414. Release: v1.16
  1415. Testname: Service, change type, ExternalName to NodePort
  1416. Description: Create a service of type ExternalName, pointing to external DNS. ClusterIP MUST not be assigned to the service.
  1417. Update the service from ExternalName to NodePort, assigning port 80 as service port and, TCP as protocol.
  1418. service update MUST be successful by exposing service on every node's IP on dynamically assigned NodePort and, ClusterIP MUST be assigned to route service requests.
  1419. Service MUST be reachable over serviceName and the ClusterIP on servicePort. Service MUST also be reachable over node's IP on NodePort.
  1420. */
  1421. framework.ConformanceIt("should be able to change the type from ExternalName to NodePort", func() {
  1422. serviceName := "externalname-service"
  1423. ns := f.Namespace.Name
  1424. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  1425. ginkgo.By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns)
  1426. _, err := jig.CreateExternalNameService(nil)
  1427. framework.ExpectNoError(err)
  1428. defer func() {
  1429. framework.Logf("Cleaning up the ExternalName to NodePort test service")
  1430. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  1431. framework.ExpectNoError(err, "failed to delete service %s in namespace %s", serviceName, ns)
  1432. }()
  1433. ginkgo.By("changing the ExternalName service to type=NodePort")
  1434. nodePortService, err := jig.UpdateService(func(s *v1.Service) {
  1435. s.Spec.Type = v1.ServiceTypeNodePort
  1436. s.Spec.ExternalName = ""
  1437. s.Spec.Ports = []v1.ServicePort{
  1438. {Port: 80, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(9376)},
  1439. }
  1440. })
  1441. framework.ExpectNoError(err)
  1442. err = jig.CreateServicePods(2)
  1443. framework.ExpectNoError(err)
  1444. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
  1445. err = jig.CheckServiceReachability(nodePortService, execPod)
  1446. framework.ExpectNoError(err)
  1447. })
  1448. /*
  1449. Release: v1.16
  1450. Testname: Service, change type, ClusterIP to ExternalName
  1451. Description: Create a service of type ClusterIP. Service creation MUST be successful by assigning ClusterIP to the service.
  1452. Update service type from ClusterIP to ExternalName by setting CNAME entry as externalName. Service update MUST be successful and service MUST not has associated ClusterIP.
  1453. Service MUST be able to resolve to IP address by returning A records ensuring service is pointing to provided externalName.
  1454. */
  1455. framework.ConformanceIt("should be able to change the type from ClusterIP to ExternalName", func() {
  1456. serviceName := "clusterip-service"
  1457. ns := f.Namespace.Name
  1458. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  1459. ginkgo.By("creating a service " + serviceName + " with the type=ClusterIP in namespace " + ns)
  1460. _, err := jig.CreateTCPService(nil)
  1461. framework.ExpectNoError(err)
  1462. defer func() {
  1463. framework.Logf("Cleaning up the ClusterIP to ExternalName test service")
  1464. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  1465. framework.ExpectNoError(err, "failed to delete service %s in namespace %s", serviceName, ns)
  1466. }()
  1467. ginkgo.By("Creating active service to test reachability when its FQDN is referred as externalName for another service")
  1468. externalServiceName := "externalsvc"
  1469. externalServiceFQDN := createAndGetExternalServiceFQDN(cs, ns, externalServiceName)
  1470. defer func() {
  1471. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, externalServiceName))
  1472. }()
  1473. ginkgo.By("changing the ClusterIP service to type=ExternalName")
  1474. externalNameService, err := jig.UpdateService(func(s *v1.Service) {
  1475. s.Spec.Type = v1.ServiceTypeExternalName
  1476. s.Spec.ExternalName = externalServiceFQDN
  1477. s.Spec.ClusterIP = ""
  1478. })
  1479. framework.ExpectNoError(err)
  1480. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
  1481. err = jig.CheckServiceReachability(externalNameService, execPod)
  1482. framework.ExpectNoError(err)
  1483. })
  1484. /*
  1485. Release: v1.16
  1486. Testname: Service, change type, NodePort to ExternalName
  1487. Description: Create a service of type NodePort. Service creation MUST be successful by exposing service on every node's IP on dynamically assigned NodePort and, ClusterIP MUST be assigned to route service requests.
  1488. Update the service type from NodePort to ExternalName by setting CNAME entry as externalName. Service update MUST be successful and, MUST not has ClusterIP associated with the service and, allocated NodePort MUST be released.
  1489. Service MUST be able to resolve to IP address by returning A records ensuring service is pointing to provided externalName.
  1490. */
  1491. framework.ConformanceIt("should be able to change the type from NodePort to ExternalName", func() {
  1492. serviceName := "nodeport-service"
  1493. ns := f.Namespace.Name
  1494. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  1495. ginkgo.By("creating a service " + serviceName + " with the type=NodePort in namespace " + ns)
  1496. _, err := jig.CreateTCPService(func(svc *v1.Service) {
  1497. svc.Spec.Type = v1.ServiceTypeNodePort
  1498. })
  1499. framework.ExpectNoError(err)
  1500. defer func() {
  1501. framework.Logf("Cleaning up the NodePort to ExternalName test service")
  1502. err := cs.CoreV1().Services(ns).Delete(context.TODO(), serviceName, nil)
  1503. framework.ExpectNoError(err, "failed to delete service %s in namespace %s", serviceName, ns)
  1504. }()
  1505. ginkgo.By("Creating active service to test reachability when its FQDN is referred as externalName for another service")
  1506. externalServiceName := "externalsvc"
  1507. externalServiceFQDN := createAndGetExternalServiceFQDN(cs, ns, externalServiceName)
  1508. defer func() {
  1509. framework.ExpectNoError(StopServeHostnameService(f.ClientSet, ns, externalServiceName))
  1510. }()
  1511. ginkgo.By("changing the NodePort service to type=ExternalName")
  1512. externalNameService, err := jig.UpdateService(func(s *v1.Service) {
  1513. s.Spec.Type = v1.ServiceTypeExternalName
  1514. s.Spec.ExternalName = externalServiceFQDN
  1515. s.Spec.ClusterIP = ""
  1516. s.Spec.Ports[0].NodePort = 0
  1517. })
  1518. framework.ExpectNoError(err)
  1519. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
  1520. err = jig.CheckServiceReachability(externalNameService, execPod)
  1521. framework.ExpectNoError(err)
  1522. })
  1523. ginkgo.It("should prevent NodePort collisions", func() {
  1524. // TODO: use the ServiceTestJig here
  1525. baseName := "nodeport-collision-"
  1526. serviceName1 := baseName + "1"
  1527. serviceName2 := baseName + "2"
  1528. ns := f.Namespace.Name
  1529. t := NewServerTest(cs, ns, serviceName1)
  1530. defer func() {
  1531. defer ginkgo.GinkgoRecover()
  1532. errs := t.Cleanup()
  1533. if len(errs) != 0 {
  1534. framework.Failf("errors in cleanup: %v", errs)
  1535. }
  1536. }()
  1537. ginkgo.By("creating service " + serviceName1 + " with type NodePort in namespace " + ns)
  1538. service := t.BuildServiceSpec()
  1539. service.Spec.Type = v1.ServiceTypeNodePort
  1540. result, err := t.CreateService(service)
  1541. framework.ExpectNoError(err, "failed to create service: %s in namespace: %s", serviceName1, ns)
  1542. if result.Spec.Type != v1.ServiceTypeNodePort {
  1543. framework.Failf("got unexpected Spec.Type for new service: %v", result)
  1544. }
  1545. if len(result.Spec.Ports) != 1 {
  1546. framework.Failf("got unexpected len(Spec.Ports) for new service: %v", result)
  1547. }
  1548. port := result.Spec.Ports[0]
  1549. if port.NodePort == 0 {
  1550. framework.Failf("got unexpected Spec.Ports[0].NodePort for new service: %v", result)
  1551. }
  1552. ginkgo.By("creating service " + serviceName2 + " with conflicting NodePort")
  1553. service2 := t.BuildServiceSpec()
  1554. service2.Name = serviceName2
  1555. service2.Spec.Type = v1.ServiceTypeNodePort
  1556. service2.Spec.Ports[0].NodePort = port.NodePort
  1557. result2, err := t.CreateService(service2)
  1558. if err == nil {
  1559. framework.Failf("Created service with conflicting NodePort: %v", result2)
  1560. }
  1561. expectedErr := fmt.Sprintf("%d.*port is already allocated", port.NodePort)
  1562. gomega.Expect(fmt.Sprintf("%v", err)).To(gomega.MatchRegexp(expectedErr))
  1563. ginkgo.By("deleting service " + serviceName1 + " to release NodePort")
  1564. err = t.DeleteService(serviceName1)
  1565. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName1, ns)
  1566. ginkgo.By("creating service " + serviceName2 + " with no-longer-conflicting NodePort")
  1567. _, err = t.CreateService(service2)
  1568. framework.ExpectNoError(err, "failed to create service: %s in namespace: %s", serviceName1, ns)
  1569. })
  1570. ginkgo.It("should check NodePort out-of-range", func() {
  1571. // TODO: use the ServiceTestJig here
  1572. serviceName := "nodeport-range-test"
  1573. ns := f.Namespace.Name
  1574. t := NewServerTest(cs, ns, serviceName)
  1575. defer func() {
  1576. defer ginkgo.GinkgoRecover()
  1577. errs := t.Cleanup()
  1578. if len(errs) != 0 {
  1579. framework.Failf("errors in cleanup: %v", errs)
  1580. }
  1581. }()
  1582. service := t.BuildServiceSpec()
  1583. service.Spec.Type = v1.ServiceTypeNodePort
  1584. ginkgo.By("creating service " + serviceName + " with type NodePort in namespace " + ns)
  1585. service, err := t.CreateService(service)
  1586. framework.ExpectNoError(err, "failed to create service: %s in namespace: %s", serviceName, ns)
  1587. if service.Spec.Type != v1.ServiceTypeNodePort {
  1588. framework.Failf("got unexpected Spec.Type for new service: %v", service)
  1589. }
  1590. if len(service.Spec.Ports) != 1 {
  1591. framework.Failf("got unexpected len(Spec.Ports) for new service: %v", service)
  1592. }
  1593. port := service.Spec.Ports[0]
  1594. if port.NodePort == 0 {
  1595. framework.Failf("got unexpected Spec.Ports[0].nodePort for new service: %v", service)
  1596. }
  1597. if !e2eservice.NodePortRange.Contains(int(port.NodePort)) {
  1598. framework.Failf("got unexpected (out-of-range) port for new service: %v", service)
  1599. }
  1600. outOfRangeNodePort := 0
  1601. for {
  1602. outOfRangeNodePort = 1 + rand.Intn(65535)
  1603. if !e2eservice.NodePortRange.Contains(outOfRangeNodePort) {
  1604. break
  1605. }
  1606. }
  1607. ginkgo.By(fmt.Sprintf("changing service "+serviceName+" to out-of-range NodePort %d", outOfRangeNodePort))
  1608. result, err := e2eservice.UpdateService(cs, ns, serviceName, func(s *v1.Service) {
  1609. s.Spec.Ports[0].NodePort = int32(outOfRangeNodePort)
  1610. })
  1611. if err == nil {
  1612. framework.Failf("failed to prevent update of service with out-of-range NodePort: %v", result)
  1613. }
  1614. expectedErr := fmt.Sprintf("%d.*port is not in the valid range", outOfRangeNodePort)
  1615. gomega.Expect(fmt.Sprintf("%v", err)).To(gomega.MatchRegexp(expectedErr))
  1616. ginkgo.By("deleting original service " + serviceName)
  1617. err = t.DeleteService(serviceName)
  1618. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName, ns)
  1619. ginkgo.By(fmt.Sprintf("creating service "+serviceName+" with out-of-range NodePort %d", outOfRangeNodePort))
  1620. service = t.BuildServiceSpec()
  1621. service.Spec.Type = v1.ServiceTypeNodePort
  1622. service.Spec.Ports[0].NodePort = int32(outOfRangeNodePort)
  1623. service, err = t.CreateService(service)
  1624. if err == nil {
  1625. framework.Failf("failed to prevent create of service with out-of-range NodePort (%d): %v", outOfRangeNodePort, service)
  1626. }
  1627. gomega.Expect(fmt.Sprintf("%v", err)).To(gomega.MatchRegexp(expectedErr))
  1628. })
  1629. ginkgo.It("should release NodePorts on delete", func() {
  1630. // TODO: use the ServiceTestJig here
  1631. serviceName := "nodeport-reuse"
  1632. ns := f.Namespace.Name
  1633. t := NewServerTest(cs, ns, serviceName)
  1634. defer func() {
  1635. defer ginkgo.GinkgoRecover()
  1636. errs := t.Cleanup()
  1637. if len(errs) != 0 {
  1638. framework.Failf("errors in cleanup: %v", errs)
  1639. }
  1640. }()
  1641. service := t.BuildServiceSpec()
  1642. service.Spec.Type = v1.ServiceTypeNodePort
  1643. ginkgo.By("creating service " + serviceName + " with type NodePort in namespace " + ns)
  1644. service, err := t.CreateService(service)
  1645. framework.ExpectNoError(err, "failed to create service: %s in namespace: %s", serviceName, ns)
  1646. if service.Spec.Type != v1.ServiceTypeNodePort {
  1647. framework.Failf("got unexpected Spec.Type for new service: %v", service)
  1648. }
  1649. if len(service.Spec.Ports) != 1 {
  1650. framework.Failf("got unexpected len(Spec.Ports) for new service: %v", service)
  1651. }
  1652. port := service.Spec.Ports[0]
  1653. if port.NodePort == 0 {
  1654. framework.Failf("got unexpected Spec.Ports[0].nodePort for new service: %v", service)
  1655. }
  1656. if !e2eservice.NodePortRange.Contains(int(port.NodePort)) {
  1657. framework.Failf("got unexpected (out-of-range) port for new service: %v", service)
  1658. }
  1659. nodePort := port.NodePort
  1660. ginkgo.By("deleting original service " + serviceName)
  1661. err = t.DeleteService(serviceName)
  1662. framework.ExpectNoError(err, "failed to delete service: %s in namespace: %s", serviceName, ns)
  1663. hostExec := launchHostExecPod(f.ClientSet, f.Namespace.Name, "hostexec")
  1664. cmd := fmt.Sprintf(`! ss -ant46 'sport = :%d' | tail -n +2 | grep LISTEN`, nodePort)
  1665. var stdout string
  1666. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.KubeProxyLagTimeout, func() (bool, error) {
  1667. var err error
  1668. stdout, err = framework.RunHostCmd(hostExec.Namespace, hostExec.Name, cmd)
  1669. if err != nil {
  1670. framework.Logf("expected node port (%d) to not be in use, stdout: %v", nodePort, stdout)
  1671. return false, nil
  1672. }
  1673. return true, nil
  1674. }); pollErr != nil {
  1675. framework.Failf("expected node port (%d) to not be in use in %v, stdout: %v", nodePort, e2eservice.KubeProxyLagTimeout, stdout)
  1676. }
  1677. ginkgo.By(fmt.Sprintf("creating service "+serviceName+" with same NodePort %d", nodePort))
  1678. service = t.BuildServiceSpec()
  1679. service.Spec.Type = v1.ServiceTypeNodePort
  1680. service.Spec.Ports[0].NodePort = nodePort
  1681. _, err = t.CreateService(service)
  1682. framework.ExpectNoError(err, "failed to create service: %s in namespace: %s", serviceName, ns)
  1683. })
  1684. ginkgo.It("should create endpoints for unready pods", func() {
  1685. serviceName := "tolerate-unready"
  1686. ns := f.Namespace.Name
  1687. t := NewServerTest(cs, ns, serviceName)
  1688. defer func() {
  1689. defer ginkgo.GinkgoRecover()
  1690. errs := t.Cleanup()
  1691. if len(errs) != 0 {
  1692. framework.Failf("errors in cleanup: %v", errs)
  1693. }
  1694. }()
  1695. t.Name = "slow-terminating-unready-pod"
  1696. t.Image = imageutils.GetE2EImage(imageutils.Agnhost)
  1697. port := 80
  1698. terminateSeconds := int64(600)
  1699. service := &v1.Service{
  1700. ObjectMeta: metav1.ObjectMeta{
  1701. Name: t.ServiceName,
  1702. Namespace: t.Namespace,
  1703. },
  1704. Spec: v1.ServiceSpec{
  1705. Selector: t.Labels,
  1706. Ports: []v1.ServicePort{{
  1707. Name: "http",
  1708. Port: int32(port),
  1709. TargetPort: intstr.FromInt(port),
  1710. }},
  1711. PublishNotReadyAddresses: true,
  1712. },
  1713. }
  1714. rcSpec := e2erc.ByNameContainer(t.Name, 1, t.Labels, v1.Container{
  1715. Args: []string{"netexec", fmt.Sprintf("--http-port=%d", port)},
  1716. Name: t.Name,
  1717. Image: t.Image,
  1718. Ports: []v1.ContainerPort{{ContainerPort: int32(port), Protocol: v1.ProtocolTCP}},
  1719. ReadinessProbe: &v1.Probe{
  1720. Handler: v1.Handler{
  1721. Exec: &v1.ExecAction{
  1722. Command: []string{"/bin/false"},
  1723. },
  1724. },
  1725. },
  1726. Lifecycle: &v1.Lifecycle{
  1727. PreStop: &v1.Handler{
  1728. Exec: &v1.ExecAction{
  1729. Command: []string{"/bin/sleep", fmt.Sprintf("%d", terminateSeconds)},
  1730. },
  1731. },
  1732. },
  1733. }, nil)
  1734. rcSpec.Spec.Template.Spec.TerminationGracePeriodSeconds = &terminateSeconds
  1735. ginkgo.By(fmt.Sprintf("creating RC %v with selectors %v", rcSpec.Name, rcSpec.Spec.Selector))
  1736. _, err := t.CreateRC(rcSpec)
  1737. framework.ExpectNoError(err)
  1738. ginkgo.By(fmt.Sprintf("creating Service %v with selectors %v", service.Name, service.Spec.Selector))
  1739. _, err = t.CreateService(service)
  1740. framework.ExpectNoError(err)
  1741. ginkgo.By("Verifying pods for RC " + t.Name)
  1742. framework.ExpectNoError(e2epod.VerifyPods(t.Client, t.Namespace, t.Name, false, 1))
  1743. svcName := fmt.Sprintf("%v.%v.svc.%v", serviceName, f.Namespace.Name, framework.TestContext.ClusterDNSDomain)
  1744. ginkgo.By("Waiting for endpoints of Service with DNS name " + svcName)
  1745. execPod := e2epod.CreateExecPodOrFail(f.ClientSet, f.Namespace.Name, "execpod-", nil)
  1746. execPodName := execPod.Name
  1747. cmd := fmt.Sprintf("curl -q -s --connect-timeout 2 http://%s:%d/", svcName, port)
  1748. var stdout string
  1749. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.KubeProxyLagTimeout, func() (bool, error) {
  1750. var err error
  1751. stdout, err = framework.RunHostCmd(f.Namespace.Name, execPodName, cmd)
  1752. if err != nil {
  1753. framework.Logf("expected un-ready endpoint for Service %v, stdout: %v, err %v", t.Name, stdout, err)
  1754. return false, nil
  1755. }
  1756. return true, nil
  1757. }); pollErr != nil {
  1758. framework.Failf("expected un-ready endpoint for Service %v within %v, stdout: %v", t.Name, e2eservice.KubeProxyLagTimeout, stdout)
  1759. }
  1760. ginkgo.By("Scaling down replication controller to zero")
  1761. e2erc.ScaleRC(f.ClientSet, f.ScalesGetter, t.Namespace, rcSpec.Name, 0, false)
  1762. ginkgo.By("Update service to not tolerate unready services")
  1763. _, err = e2eservice.UpdateService(f.ClientSet, t.Namespace, t.ServiceName, func(s *v1.Service) {
  1764. s.Spec.PublishNotReadyAddresses = false
  1765. })
  1766. framework.ExpectNoError(err)
  1767. ginkgo.By("Check if pod is unreachable")
  1768. cmd = fmt.Sprintf("curl -q -s --connect-timeout 2 http://%s:%d/; test \"$?\" -ne \"0\"", svcName, port)
  1769. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.KubeProxyLagTimeout, func() (bool, error) {
  1770. var err error
  1771. stdout, err = framework.RunHostCmd(f.Namespace.Name, execPodName, cmd)
  1772. if err != nil {
  1773. framework.Logf("expected un-ready endpoint for Service %v, stdout: %v, err %v", t.Name, stdout, err)
  1774. return false, nil
  1775. }
  1776. return true, nil
  1777. }); pollErr != nil {
  1778. framework.Failf("expected un-ready endpoint for Service %v within %v, stdout: %v", t.Name, e2eservice.KubeProxyLagTimeout, stdout)
  1779. }
  1780. ginkgo.By("Update service to tolerate unready services again")
  1781. _, err = e2eservice.UpdateService(f.ClientSet, t.Namespace, t.ServiceName, func(s *v1.Service) {
  1782. s.Spec.PublishNotReadyAddresses = true
  1783. })
  1784. framework.ExpectNoError(err)
  1785. ginkgo.By("Check if terminating pod is available through service")
  1786. cmd = fmt.Sprintf("curl -q -s --connect-timeout 2 http://%s:%d/", svcName, port)
  1787. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.KubeProxyLagTimeout, func() (bool, error) {
  1788. var err error
  1789. stdout, err = framework.RunHostCmd(f.Namespace.Name, execPodName, cmd)
  1790. if err != nil {
  1791. framework.Logf("expected un-ready endpoint for Service %v, stdout: %v, err %v", t.Name, stdout, err)
  1792. return false, nil
  1793. }
  1794. return true, nil
  1795. }); pollErr != nil {
  1796. framework.Failf("expected un-ready endpoint for Service %v within %v, stdout: %v", t.Name, e2eservice.KubeProxyLagTimeout, stdout)
  1797. }
  1798. ginkgo.By("Remove pods immediately")
  1799. label := labels.SelectorFromSet(labels.Set(t.Labels))
  1800. options := metav1.ListOptions{LabelSelector: label.String()}
  1801. podClient := t.Client.CoreV1().Pods(f.Namespace.Name)
  1802. pods, err := podClient.List(context.TODO(), options)
  1803. if err != nil {
  1804. framework.Logf("warning: error retrieving pods: %s", err)
  1805. } else {
  1806. for _, pod := range pods.Items {
  1807. var gracePeriodSeconds int64 = 0
  1808. err := podClient.Delete(context.TODO(), pod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gracePeriodSeconds})
  1809. if err != nil {
  1810. framework.Logf("warning: error force deleting pod '%s': %s", pod.Name, err)
  1811. }
  1812. }
  1813. }
  1814. })
  1815. ginkgo.It("should only allow access from service loadbalancer source ranges [Slow]", func() {
  1816. // this feature currently supported only on GCE/GKE/AWS
  1817. e2eskipper.SkipUnlessProviderIs("gce", "gke", "aws")
  1818. loadBalancerLagTimeout := e2eservice.LoadBalancerLagTimeoutDefault
  1819. if framework.ProviderIs("aws") {
  1820. loadBalancerLagTimeout = e2eservice.LoadBalancerLagTimeoutAWS
  1821. }
  1822. loadBalancerCreateTimeout := e2eservice.GetServiceLoadBalancerCreationTimeout(cs)
  1823. namespace := f.Namespace.Name
  1824. serviceName := "lb-sourcerange"
  1825. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  1826. ginkgo.By("Prepare allow source ips")
  1827. // prepare the exec pods
  1828. // acceptPod are allowed to access the loadbalancer
  1829. acceptPod := e2epod.CreateExecPodOrFail(cs, namespace, "execpod-accept", nil)
  1830. dropPod := e2epod.CreateExecPodOrFail(cs, namespace, "execpod-drop", nil)
  1831. ginkgo.By("creating a pod to be part of the service " + serviceName)
  1832. // This container is an nginx container listening on port 80
  1833. // See kubernetes/contrib/ingress/echoheaders/nginx.conf for content of response
  1834. _, err := jig.Run(nil)
  1835. framework.ExpectNoError(err)
  1836. // Make sure acceptPod is running. There are certain chances that pod might be teminated due to unexpected reasons.
  1837. acceptPod, err = cs.CoreV1().Pods(namespace).Get(context.TODO(), acceptPod.Name, metav1.GetOptions{})
  1838. framework.ExpectNoError(err, "Unable to get pod %s", acceptPod.Name)
  1839. framework.ExpectEqual(acceptPod.Status.Phase, v1.PodRunning)
  1840. framework.ExpectNotEqual(acceptPod.Status.PodIP, "")
  1841. // Create loadbalancer service with source range from node[0] and podAccept
  1842. svc, err := jig.CreateTCPService(func(svc *v1.Service) {
  1843. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  1844. svc.Spec.LoadBalancerSourceRanges = []string{acceptPod.Status.PodIP + "/32"}
  1845. })
  1846. framework.ExpectNoError(err)
  1847. defer func() {
  1848. ginkgo.By("Clean up loadbalancer service")
  1849. e2eservice.WaitForServiceDeletedWithFinalizer(cs, svc.Namespace, svc.Name)
  1850. }()
  1851. svc, err = jig.WaitForLoadBalancer(loadBalancerCreateTimeout)
  1852. framework.ExpectNoError(err)
  1853. // timeout when we haven't just created the load balancer
  1854. normalReachabilityTimeout := 2 * time.Minute
  1855. ginkgo.By("check reachability from different sources")
  1856. svcIP := e2eservice.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0])
  1857. // Wait longer as this is our first request after creation. We can't check using a separate method,
  1858. // because the LB should only be reachable from the "accept" pod
  1859. checkReachabilityFromPod(true, loadBalancerLagTimeout, namespace, acceptPod.Name, svcIP)
  1860. checkReachabilityFromPod(false, normalReachabilityTimeout, namespace, dropPod.Name, svcIP)
  1861. // Make sure dropPod is running. There are certain chances that the pod might be teminated due to unexpected reasons. dropPod, err = cs.CoreV1().Pods(namespace).Get(dropPod.Name, metav1.GetOptions{})
  1862. dropPod, err = cs.CoreV1().Pods(namespace).Get(context.TODO(), dropPod.Name, metav1.GetOptions{})
  1863. framework.ExpectNoError(err, "Unable to get pod %s", dropPod.Name)
  1864. framework.ExpectEqual(acceptPod.Status.Phase, v1.PodRunning)
  1865. framework.ExpectNotEqual(acceptPod.Status.PodIP, "")
  1866. ginkgo.By("Update service LoadBalancerSourceRange and check reachability")
  1867. _, err = jig.UpdateService(func(svc *v1.Service) {
  1868. // only allow access from dropPod
  1869. svc.Spec.LoadBalancerSourceRanges = []string{dropPod.Status.PodIP + "/32"}
  1870. })
  1871. framework.ExpectNoError(err)
  1872. checkReachabilityFromPod(false, normalReachabilityTimeout, namespace, acceptPod.Name, svcIP)
  1873. checkReachabilityFromPod(true, normalReachabilityTimeout, namespace, dropPod.Name, svcIP)
  1874. ginkgo.By("Delete LoadBalancerSourceRange field and check reachability")
  1875. _, err = jig.UpdateService(func(svc *v1.Service) {
  1876. svc.Spec.LoadBalancerSourceRanges = nil
  1877. })
  1878. framework.ExpectNoError(err)
  1879. checkReachabilityFromPod(true, normalReachabilityTimeout, namespace, acceptPod.Name, svcIP)
  1880. checkReachabilityFromPod(true, normalReachabilityTimeout, namespace, dropPod.Name, svcIP)
  1881. })
  1882. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  1883. ginkgo.It("should be able to create an internal type load balancer [Slow] [DisabledForLargeClusters]", func() {
  1884. e2eskipper.SkipUnlessProviderIs("azure", "gke", "gce")
  1885. createTimeout := e2eservice.GetServiceLoadBalancerCreationTimeout(cs)
  1886. pollInterval := framework.Poll * 10
  1887. namespace := f.Namespace.Name
  1888. serviceName := "lb-internal"
  1889. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  1890. ginkgo.By("creating pod to be part of service " + serviceName)
  1891. _, err := jig.Run(nil)
  1892. framework.ExpectNoError(err)
  1893. enableILB, disableILB := enableAndDisableInternalLB()
  1894. isInternalEndpoint := func(lbIngress *v1.LoadBalancerIngress) bool {
  1895. ingressEndpoint := e2eservice.GetIngressPoint(lbIngress)
  1896. // Needs update for providers using hostname as endpoint.
  1897. return strings.HasPrefix(ingressEndpoint, "10.")
  1898. }
  1899. ginkgo.By("creating a service with type LoadBalancer and cloud specific Internal-LB annotation enabled")
  1900. svc, err := jig.CreateTCPService(func(svc *v1.Service) {
  1901. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  1902. enableILB(svc)
  1903. })
  1904. framework.ExpectNoError(err)
  1905. defer func() {
  1906. ginkgo.By("Clean up loadbalancer service")
  1907. e2eservice.WaitForServiceDeletedWithFinalizer(cs, svc.Namespace, svc.Name)
  1908. }()
  1909. svc, err = jig.WaitForLoadBalancer(createTimeout)
  1910. framework.ExpectNoError(err)
  1911. lbIngress := &svc.Status.LoadBalancer.Ingress[0]
  1912. svcPort := int(svc.Spec.Ports[0].Port)
  1913. // should have an internal IP.
  1914. framework.ExpectEqual(isInternalEndpoint(lbIngress), true)
  1915. // ILBs are not accessible from the test orchestrator, so it's necessary to use
  1916. // a pod to test the service.
  1917. ginkgo.By("hitting the internal load balancer from pod")
  1918. framework.Logf("creating pod with host network")
  1919. hostExec := launchHostExecPod(f.ClientSet, f.Namespace.Name, "ilb-host-exec")
  1920. framework.Logf("Waiting up to %v for service %q's internal LB to respond to requests", createTimeout, serviceName)
  1921. tcpIngressIP := e2eservice.GetIngressPoint(lbIngress)
  1922. if pollErr := wait.PollImmediate(pollInterval, createTimeout, func() (bool, error) {
  1923. cmd := fmt.Sprintf(`curl -m 5 'http://%v:%v/echo?msg=hello'`, tcpIngressIP, svcPort)
  1924. stdout, err := framework.RunHostCmd(hostExec.Namespace, hostExec.Name, cmd)
  1925. if err != nil {
  1926. framework.Logf("error curling; stdout: %v. err: %v", stdout, err)
  1927. return false, nil
  1928. }
  1929. if !strings.Contains(stdout, "hello") {
  1930. framework.Logf("Expected output to contain 'hello', got %q; retrying...", stdout)
  1931. return false, nil
  1932. }
  1933. framework.Logf("Successful curl; stdout: %v", stdout)
  1934. return true, nil
  1935. }); pollErr != nil {
  1936. framework.Failf("ginkgo.Failed to hit ILB IP, err: %v", pollErr)
  1937. }
  1938. ginkgo.By("switching to external type LoadBalancer")
  1939. svc, err = jig.UpdateService(func(svc *v1.Service) {
  1940. disableILB(svc)
  1941. })
  1942. framework.ExpectNoError(err)
  1943. framework.Logf("Waiting up to %v for service %q to have an external LoadBalancer", createTimeout, serviceName)
  1944. if pollErr := wait.PollImmediate(pollInterval, createTimeout, func() (bool, error) {
  1945. svc, err := cs.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
  1946. if err != nil {
  1947. return false, err
  1948. }
  1949. lbIngress = &svc.Status.LoadBalancer.Ingress[0]
  1950. return !isInternalEndpoint(lbIngress), nil
  1951. }); pollErr != nil {
  1952. framework.Failf("Loadbalancer IP not changed to external.")
  1953. }
  1954. // should have an external IP.
  1955. gomega.Expect(isInternalEndpoint(lbIngress)).To(gomega.BeFalse())
  1956. ginkgo.By("hitting the external load balancer")
  1957. framework.Logf("Waiting up to %v for service %q's external LB to respond to requests", createTimeout, serviceName)
  1958. tcpIngressIP = e2eservice.GetIngressPoint(lbIngress)
  1959. e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
  1960. // GCE cannot test a specific IP because the test may not own it. This cloud specific condition
  1961. // will be removed when GCP supports similar functionality.
  1962. if framework.ProviderIs("azure") {
  1963. ginkgo.By("switching back to interal type LoadBalancer, with static IP specified.")
  1964. internalStaticIP := "10.240.11.11"
  1965. svc, err = jig.UpdateService(func(svc *v1.Service) {
  1966. svc.Spec.LoadBalancerIP = internalStaticIP
  1967. enableILB(svc)
  1968. })
  1969. framework.ExpectNoError(err)
  1970. framework.Logf("Waiting up to %v for service %q to have an internal LoadBalancer", createTimeout, serviceName)
  1971. if pollErr := wait.PollImmediate(pollInterval, createTimeout, func() (bool, error) {
  1972. svc, err := cs.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
  1973. if err != nil {
  1974. return false, err
  1975. }
  1976. lbIngress = &svc.Status.LoadBalancer.Ingress[0]
  1977. return isInternalEndpoint(lbIngress), nil
  1978. }); pollErr != nil {
  1979. framework.Failf("Loadbalancer IP not changed to internal.")
  1980. }
  1981. // should have the given static internal IP.
  1982. framework.ExpectEqual(e2eservice.GetIngressPoint(lbIngress), internalStaticIP)
  1983. }
  1984. })
  1985. // This test creates a load balancer, make sure its health check interval
  1986. // equals to gceHcCheckIntervalSeconds. Then the interval is manipulated
  1987. // to be something else, see if the interval will be reconciled.
  1988. ginkgo.It("should reconcile LB health check interval [Slow][Serial]", func() {
  1989. const gceHcCheckIntervalSeconds = int64(8)
  1990. // This test is for clusters on GCE.
  1991. // (It restarts kube-controller-manager, which we don't support on GKE)
  1992. e2eskipper.SkipUnlessProviderIs("gce")
  1993. e2eskipper.SkipUnlessSSHKeyPresent()
  1994. clusterID, err := gce.GetClusterID(cs)
  1995. if err != nil {
  1996. framework.Failf("framework.GetClusterID(cs) = _, %v; want nil", err)
  1997. }
  1998. gceCloud, err := gce.GetGCECloud()
  1999. if err != nil {
  2000. framework.Failf("framework.GetGCECloud() = _, %v; want nil", err)
  2001. }
  2002. namespace := f.Namespace.Name
  2003. serviceName := "lb-hc-int"
  2004. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2005. ginkgo.By("create load balancer service")
  2006. // Create loadbalancer service with source range from node[0] and podAccept
  2007. svc, err := jig.CreateTCPService(func(svc *v1.Service) {
  2008. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  2009. })
  2010. framework.ExpectNoError(err)
  2011. defer func() {
  2012. ginkgo.By("Clean up loadbalancer service")
  2013. e2eservice.WaitForServiceDeletedWithFinalizer(cs, svc.Namespace, svc.Name)
  2014. }()
  2015. svc, err = jig.WaitForLoadBalancer(e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
  2016. framework.ExpectNoError(err)
  2017. hcName := gcecloud.MakeNodesHealthCheckName(clusterID)
  2018. hc, err := gceCloud.GetHTTPHealthCheck(hcName)
  2019. if err != nil {
  2020. framework.Failf("gceCloud.GetHttpHealthCheck(%q) = _, %v; want nil", hcName, err)
  2021. }
  2022. framework.ExpectEqual(hc.CheckIntervalSec, gceHcCheckIntervalSeconds)
  2023. ginkgo.By("modify the health check interval")
  2024. hc.CheckIntervalSec = gceHcCheckIntervalSeconds - 1
  2025. if err = gceCloud.UpdateHTTPHealthCheck(hc); err != nil {
  2026. framework.Failf("gcecloud.UpdateHttpHealthCheck(%#v) = %v; want nil", hc, err)
  2027. }
  2028. ginkgo.By("restart kube-controller-manager")
  2029. if err := framework.RestartControllerManager(); err != nil {
  2030. framework.Failf("framework.RestartControllerManager() = %v; want nil", err)
  2031. }
  2032. if err := framework.WaitForControllerManagerUp(); err != nil {
  2033. framework.Failf("framework.WaitForControllerManagerUp() = %v; want nil", err)
  2034. }
  2035. ginkgo.By("health check should be reconciled")
  2036. pollInterval := framework.Poll * 10
  2037. if pollErr := wait.PollImmediate(pollInterval, e2eservice.LoadBalancerPropagationTimeoutDefault, func() (bool, error) {
  2038. hc, err := gceCloud.GetHTTPHealthCheck(hcName)
  2039. if err != nil {
  2040. framework.Logf("ginkgo.Failed to get HttpHealthCheck(%q): %v", hcName, err)
  2041. return false, err
  2042. }
  2043. framework.Logf("hc.CheckIntervalSec = %v", hc.CheckIntervalSec)
  2044. return hc.CheckIntervalSec == gceHcCheckIntervalSeconds, nil
  2045. }); pollErr != nil {
  2046. framework.Failf("Health check %q does not reconcile its check interval to %d.", hcName, gceHcCheckIntervalSeconds)
  2047. }
  2048. })
  2049. // [LinuxOnly]: Windows does not support session affinity.
  2050. ginkgo.It("should have session affinity work for service with type clusterIP [LinuxOnly] [Flaky]", func() {
  2051. svc := getServeHostnameService("affinity-clusterip")
  2052. svc.Spec.Type = v1.ServiceTypeClusterIP
  2053. execAffinityTestForNonLBService(f, cs, svc)
  2054. })
  2055. // [LinuxOnly]: Windows does not support session affinity.
  2056. ginkgo.It("should be able to switch session affinity for service with type clusterIP [LinuxOnly] [Flaky]", func() {
  2057. svc := getServeHostnameService("affinity-clusterip-transition")
  2058. svc.Spec.Type = v1.ServiceTypeClusterIP
  2059. execAffinityTestForNonLBServiceWithTransition(f, cs, svc)
  2060. })
  2061. // [LinuxOnly]: Windows does not support session affinity.
  2062. ginkgo.It("should have session affinity work for NodePort service [LinuxOnly] [Flaky]", func() {
  2063. svc := getServeHostnameService("affinity-nodeport")
  2064. svc.Spec.Type = v1.ServiceTypeNodePort
  2065. execAffinityTestForNonLBService(f, cs, svc)
  2066. })
  2067. // [LinuxOnly]: Windows does not support session affinity.
  2068. ginkgo.It("should be able to switch session affinity for NodePort service [LinuxOnly] [Flaky]", func() {
  2069. svc := getServeHostnameService("affinity-nodeport-transition")
  2070. svc.Spec.Type = v1.ServiceTypeNodePort
  2071. execAffinityTestForNonLBServiceWithTransition(f, cs, svc)
  2072. })
  2073. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  2074. // [LinuxOnly]: Windows does not support session affinity.
  2075. ginkgo.It("should have session affinity work for LoadBalancer service with ESIPP on [Slow] [DisabledForLargeClusters] [LinuxOnly]", func() {
  2076. // L4 load balancer affinity `ClientIP` is not supported on AWS ELB.
  2077. e2eskipper.SkipIfProviderIs("aws")
  2078. svc := getServeHostnameService("affinity-lb-esipp")
  2079. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  2080. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
  2081. execAffinityTestForLBService(f, cs, svc)
  2082. })
  2083. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  2084. // [LinuxOnly]: Windows does not support session affinity.
  2085. ginkgo.It("should be able to switch session affinity for LoadBalancer service with ESIPP on [Slow] [DisabledForLargeClusters] [LinuxOnly]", func() {
  2086. // L4 load balancer affinity `ClientIP` is not supported on AWS ELB.
  2087. e2eskipper.SkipIfProviderIs("aws")
  2088. svc := getServeHostnameService("affinity-lb-esipp-transition")
  2089. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  2090. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
  2091. execAffinityTestForLBServiceWithTransition(f, cs, svc)
  2092. })
  2093. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  2094. // [LinuxOnly]: Windows does not support session affinity.
  2095. ginkgo.It("should have session affinity work for LoadBalancer service with ESIPP off [Slow] [DisabledForLargeClusters] [LinuxOnly]", func() {
  2096. // L4 load balancer affinity `ClientIP` is not supported on AWS ELB.
  2097. e2eskipper.SkipIfProviderIs("aws")
  2098. svc := getServeHostnameService("affinity-lb")
  2099. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  2100. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
  2101. execAffinityTestForLBService(f, cs, svc)
  2102. })
  2103. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  2104. // [LinuxOnly]: Windows does not support session affinity.
  2105. ginkgo.It("should be able to switch session affinity for LoadBalancer service with ESIPP off [Slow] [DisabledForLargeClusters] [LinuxOnly]", func() {
  2106. // L4 load balancer affinity `ClientIP` is not supported on AWS ELB.
  2107. e2eskipper.SkipIfProviderIs("aws")
  2108. svc := getServeHostnameService("affinity-lb-transition")
  2109. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  2110. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
  2111. execAffinityTestForLBServiceWithTransition(f, cs, svc)
  2112. })
  2113. ginkgo.It("should implement service.kubernetes.io/service-proxy-name", func() {
  2114. // this test uses e2essh.NodeSSHHosts that does not work if a Node only reports LegacyHostIP
  2115. e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
  2116. // this test does not work if the Node does not support SSH Key
  2117. e2eskipper.SkipUnlessSSHKeyPresent()
  2118. ns := f.Namespace.Name
  2119. numPods, servicePort := 3, defaultServeHostnameServicePort
  2120. serviceProxyNameLabels := map[string]string{"service.kubernetes.io/service-proxy-name": "foo-bar"}
  2121. // We will create 2 services to test creating services in both states and also dynamic updates
  2122. // svcDisabled: Created with the label, will always be disabled. We create this early and
  2123. // test again late to make sure it never becomes available.
  2124. // svcToggled: Created without the label then the label is toggled verifying reachability at each step.
  2125. ginkgo.By("creating service-disabled in namespace " + ns)
  2126. svcDisabled := getServeHostnameService("service-proxy-disabled")
  2127. svcDisabled.ObjectMeta.Labels = serviceProxyNameLabels
  2128. _, svcDisabledIP, err := StartServeHostnameService(cs, svcDisabled, ns, numPods)
  2129. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svcDisabledIP, ns)
  2130. ginkgo.By("creating service in namespace " + ns)
  2131. svcToggled := getServeHostnameService("service-proxy-toggled")
  2132. podToggledNames, svcToggledIP, err := StartServeHostnameService(cs, svcToggled, ns, numPods)
  2133. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svcToggledIP, ns)
  2134. jig := e2eservice.NewTestJig(cs, ns, svcToggled.ObjectMeta.Name)
  2135. hosts, err := e2essh.NodeSSHHosts(cs)
  2136. framework.ExpectNoError(err, "failed to find external/internal IPs for every node")
  2137. if len(hosts) == 0 {
  2138. framework.Failf("No ssh-able nodes")
  2139. }
  2140. host := hosts[0]
  2141. ginkgo.By("verifying service is up")
  2142. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podToggledNames, svcToggledIP, servicePort))
  2143. ginkgo.By("verifying service-disabled is not up")
  2144. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svcDisabledIP, servicePort))
  2145. ginkgo.By("adding service-proxy-name label")
  2146. _, err = jig.UpdateService(func(svc *v1.Service) {
  2147. svc.ObjectMeta.Labels = serviceProxyNameLabels
  2148. })
  2149. framework.ExpectNoError(err)
  2150. ginkgo.By("verifying service is not up")
  2151. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svcToggledIP, servicePort))
  2152. ginkgo.By("removing service-proxy-name annotation")
  2153. _, err = jig.UpdateService(func(svc *v1.Service) {
  2154. svc.ObjectMeta.Labels = nil
  2155. })
  2156. framework.ExpectNoError(err)
  2157. ginkgo.By("verifying service is up")
  2158. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podToggledNames, svcToggledIP, servicePort))
  2159. ginkgo.By("verifying service-disabled is still not up")
  2160. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svcDisabledIP, servicePort))
  2161. })
  2162. ginkgo.It("should implement service.kubernetes.io/headless", func() {
  2163. // this test uses e2essh.NodeSSHHosts that does not work if a Node only reports LegacyHostIP
  2164. e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
  2165. // this test does not work if the Node does not support SSH Key
  2166. e2eskipper.SkipUnlessSSHKeyPresent()
  2167. ns := f.Namespace.Name
  2168. numPods, servicePort := 3, defaultServeHostnameServicePort
  2169. serviceHeadlessLabels := map[string]string{v1.IsHeadlessService: ""}
  2170. // We will create 2 services to test creating services in both states and also dynamic updates
  2171. // svcHeadless: Created with the label, will always be disabled. We create this early and
  2172. // test again late to make sure it never becomes available.
  2173. // svcHeadlessToggled: Created without the label then the label is toggled verifying reachability at each step.
  2174. ginkgo.By("creating service-headless in namespace " + ns)
  2175. svcHeadless := getServeHostnameService("service-headless")
  2176. svcHeadless.ObjectMeta.Labels = serviceHeadlessLabels
  2177. // This should be improved, as we do not want a Headlesss Service to contain an IP...
  2178. _, svcHeadlessIP, err := StartServeHostnameService(cs, svcHeadless, ns, numPods)
  2179. framework.ExpectNoError(err, "failed to create replication controller with headless service: %s in the namespace: %s", svcHeadlessIP, ns)
  2180. ginkgo.By("creating service in namespace " + ns)
  2181. svcHeadlessToggled := getServeHostnameService("service-headless-toggled")
  2182. podHeadlessToggledNames, svcHeadlessToggledIP, err := StartServeHostnameService(cs, svcHeadlessToggled, ns, numPods)
  2183. framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svcHeadlessToggledIP, ns)
  2184. jig := e2eservice.NewTestJig(cs, ns, svcHeadlessToggled.ObjectMeta.Name)
  2185. hosts, err := e2essh.NodeSSHHosts(cs)
  2186. framework.ExpectNoError(err, "failed to find external/internal IPs for every node")
  2187. if len(hosts) == 0 {
  2188. framework.Failf("No ssh-able nodes")
  2189. }
  2190. host := hosts[0]
  2191. ginkgo.By("verifying service is up")
  2192. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podHeadlessToggledNames, svcHeadlessToggledIP, servicePort))
  2193. ginkgo.By("verifying service-headless is not up")
  2194. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svcHeadlessIP, servicePort))
  2195. ginkgo.By("adding service.kubernetes.io/headless label")
  2196. _, err = jig.UpdateService(func(svc *v1.Service) {
  2197. svc.ObjectMeta.Labels = serviceHeadlessLabels
  2198. })
  2199. framework.ExpectNoError(err)
  2200. ginkgo.By("verifying service is not up")
  2201. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svcHeadlessToggledIP, servicePort))
  2202. ginkgo.By("removing service.kubernetes.io/headless annotation")
  2203. _, err = jig.UpdateService(func(svc *v1.Service) {
  2204. svc.ObjectMeta.Labels = nil
  2205. })
  2206. framework.ExpectNoError(err)
  2207. ginkgo.By("verifying service is up")
  2208. framework.ExpectNoError(verifyServeHostnameServiceUp(cs, ns, host, podHeadlessToggledNames, svcHeadlessToggledIP, servicePort))
  2209. ginkgo.By("verifying service-headless is still not up")
  2210. framework.ExpectNoError(verifyServeHostnameServiceDown(cs, host, svcHeadlessIP, servicePort))
  2211. })
  2212. ginkgo.It("should be rejected when no endpoints exist", func() {
  2213. namespace := f.Namespace.Name
  2214. serviceName := "no-pods"
  2215. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2216. nodes, err := e2enode.GetBoundedReadySchedulableNodes(cs, e2eservice.MaxNodesForEndpointsTests)
  2217. framework.ExpectNoError(err)
  2218. port := 80
  2219. ginkgo.By("creating a service with no endpoints")
  2220. _, err = jig.CreateTCPServiceWithPort(nil, int32(port))
  2221. framework.ExpectNoError(err)
  2222. nodeName := nodes.Items[0].Name
  2223. podName := "execpod-noendpoints"
  2224. ginkgo.By(fmt.Sprintf("creating %v on node %v", podName, nodeName))
  2225. execPod := e2epod.CreateExecPodOrFail(f.ClientSet, namespace, podName, func(pod *v1.Pod) {
  2226. pod.Spec.NodeName = nodeName
  2227. })
  2228. serviceAddress := net.JoinHostPort(serviceName, strconv.Itoa(port))
  2229. framework.Logf("waiting up to %v to connect to %v", e2eservice.KubeProxyEndpointLagTimeout, serviceAddress)
  2230. cmd := fmt.Sprintf("/agnhost connect --timeout=3s %s", serviceAddress)
  2231. ginkgo.By(fmt.Sprintf("hitting service %v from pod %v on node %v", serviceAddress, podName, nodeName))
  2232. expectedErr := "REFUSED"
  2233. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.KubeProxyEndpointLagTimeout, func() (bool, error) {
  2234. _, err := framework.RunHostCmd(execPod.Namespace, execPod.Name, cmd)
  2235. if err != nil {
  2236. if strings.Contains(err.Error(), expectedErr) {
  2237. framework.Logf("error contained '%s', as expected: %s", expectedErr, err.Error())
  2238. return true, nil
  2239. }
  2240. framework.Logf("error didn't contain '%s', keep trying: %s", expectedErr, err.Error())
  2241. return false, nil
  2242. }
  2243. return true, errors.New("expected connect call to fail")
  2244. }); pollErr != nil {
  2245. framework.ExpectNoError(pollErr)
  2246. }
  2247. })
  2248. // This test verifies if service load balancer cleanup finalizer is properly
  2249. // handled during service lifecycle.
  2250. // 1. Create service with type=LoadBalancer. Finalizer should be added.
  2251. // 2. Update service to type=ClusterIP. Finalizer should be removed.
  2252. // 3. Update service to type=LoadBalancer. Finalizer should be added.
  2253. // 4. Delete service with type=LoadBalancer. Finalizer should be removed.
  2254. ginkgo.It("should handle load balancer cleanup finalizer for service [Slow]", func() {
  2255. jig := e2eservice.NewTestJig(cs, f.Namespace.Name, "lb-finalizer")
  2256. ginkgo.By("Create load balancer service")
  2257. svc, err := jig.CreateTCPService(func(svc *v1.Service) {
  2258. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  2259. })
  2260. framework.ExpectNoError(err)
  2261. defer func() {
  2262. ginkgo.By("Check that service can be deleted with finalizer")
  2263. e2eservice.WaitForServiceDeletedWithFinalizer(cs, svc.Namespace, svc.Name)
  2264. }()
  2265. ginkgo.By("Wait for load balancer to serve traffic")
  2266. svc, err = jig.WaitForLoadBalancer(e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
  2267. framework.ExpectNoError(err)
  2268. ginkgo.By("Check if finalizer presents on service with type=LoadBalancer")
  2269. e2eservice.WaitForServiceUpdatedWithFinalizer(cs, svc.Namespace, svc.Name, true)
  2270. ginkgo.By("Check if finalizer is removed on service after changed to type=ClusterIP")
  2271. err = jig.ChangeServiceType(v1.ServiceTypeClusterIP, e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
  2272. framework.ExpectNoError(err)
  2273. e2eservice.WaitForServiceUpdatedWithFinalizer(cs, svc.Namespace, svc.Name, false)
  2274. ginkgo.By("Check if finalizer is added back to service after changed to type=LoadBalancer")
  2275. err = jig.ChangeServiceType(v1.ServiceTypeLoadBalancer, e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
  2276. framework.ExpectNoError(err)
  2277. e2eservice.WaitForServiceUpdatedWithFinalizer(cs, svc.Namespace, svc.Name, true)
  2278. })
  2279. /*
  2280. Release : v1.18
  2281. Testname: Find Kubernetes Service in default Namespace
  2282. Description: List all Services in all Namespaces, response MUST include a Service named Kubernetes with the Namespace of default.
  2283. */
  2284. framework.ConformanceIt("should find a service from listing all namespaces", func() {
  2285. ginkgo.By("fetching services")
  2286. svcs, _ := f.ClientSet.CoreV1().Services("").List(context.TODO(), metav1.ListOptions{})
  2287. foundSvc := false
  2288. for _, svc := range svcs.Items {
  2289. if svc.ObjectMeta.Name == "kubernetes" && svc.ObjectMeta.Namespace == "default" {
  2290. foundSvc = true
  2291. break
  2292. }
  2293. }
  2294. framework.ExpectEqual(foundSvc, true, "could not find service 'kubernetes' in service list in all namespaces")
  2295. })
  2296. })
  2297. // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
  2298. var _ = SIGDescribe("ESIPP [Slow] [DisabledForLargeClusters]", func() {
  2299. f := framework.NewDefaultFramework("esipp")
  2300. var loadBalancerCreateTimeout time.Duration
  2301. var cs clientset.Interface
  2302. serviceLBNames := []string{}
  2303. ginkgo.BeforeEach(func() {
  2304. // requires cloud load-balancer support - this feature currently supported only on GCE/GKE
  2305. e2eskipper.SkipUnlessProviderIs("gce", "gke")
  2306. cs = f.ClientSet
  2307. loadBalancerCreateTimeout = e2eservice.GetServiceLoadBalancerCreationTimeout(cs)
  2308. })
  2309. ginkgo.AfterEach(func() {
  2310. if ginkgo.CurrentGinkgoTestDescription().Failed {
  2311. DescribeSvc(f.Namespace.Name)
  2312. }
  2313. for _, lb := range serviceLBNames {
  2314. framework.Logf("cleaning load balancer resource for %s", lb)
  2315. e2eservice.CleanupServiceResources(cs, lb, framework.TestContext.CloudConfig.Region, framework.TestContext.CloudConfig.Zone)
  2316. }
  2317. //reset serviceLBNames
  2318. serviceLBNames = []string{}
  2319. })
  2320. ginkgo.It("should work for type=LoadBalancer", func() {
  2321. namespace := f.Namespace.Name
  2322. serviceName := "external-local-lb"
  2323. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2324. svc, err := jig.CreateOnlyLocalLoadBalancerService(loadBalancerCreateTimeout, true, nil)
  2325. framework.ExpectNoError(err)
  2326. serviceLBNames = append(serviceLBNames, cloudprovider.DefaultLoadBalancerName(svc))
  2327. healthCheckNodePort := int(svc.Spec.HealthCheckNodePort)
  2328. if healthCheckNodePort == 0 {
  2329. framework.Failf("Service HealthCheck NodePort was not allocated")
  2330. }
  2331. defer func() {
  2332. err = jig.ChangeServiceType(v1.ServiceTypeClusterIP, loadBalancerCreateTimeout)
  2333. framework.ExpectNoError(err)
  2334. // Make sure we didn't leak the health check node port.
  2335. threshold := 2
  2336. nodes, err := jig.GetEndpointNodes()
  2337. framework.ExpectNoError(err)
  2338. for _, ips := range nodes {
  2339. err := TestHTTPHealthCheckNodePort(ips[0], healthCheckNodePort, "/healthz", e2eservice.KubeProxyEndpointLagTimeout, false, threshold)
  2340. framework.ExpectNoError(err)
  2341. }
  2342. err = cs.CoreV1().Services(svc.Namespace).Delete(context.TODO(), svc.Name, nil)
  2343. framework.ExpectNoError(err)
  2344. }()
  2345. svcTCPPort := int(svc.Spec.Ports[0].Port)
  2346. ingressIP := e2eservice.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0])
  2347. ginkgo.By("reading clientIP using the TCP service's service port via its external VIP")
  2348. content := GetHTTPContent(ingressIP, svcTCPPort, e2eservice.KubeProxyLagTimeout, "/clientip")
  2349. clientIP := content.String()
  2350. framework.Logf("ClientIP detected by target pod using VIP:SvcPort is %s", clientIP)
  2351. ginkgo.By("checking if Source IP is preserved")
  2352. if strings.HasPrefix(clientIP, "10.") {
  2353. framework.Failf("Source IP was NOT preserved")
  2354. }
  2355. })
  2356. ginkgo.It("should work for type=NodePort", func() {
  2357. namespace := f.Namespace.Name
  2358. serviceName := "external-local-nodeport"
  2359. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2360. svc, err := jig.CreateOnlyLocalNodePortService(true)
  2361. framework.ExpectNoError(err)
  2362. defer func() {
  2363. err := cs.CoreV1().Services(svc.Namespace).Delete(context.TODO(), svc.Name, nil)
  2364. framework.ExpectNoError(err)
  2365. }()
  2366. tcpNodePort := int(svc.Spec.Ports[0].NodePort)
  2367. endpointsNodeMap, err := jig.GetEndpointNodes()
  2368. framework.ExpectNoError(err)
  2369. path := "/clientip"
  2370. for nodeName, nodeIPs := range endpointsNodeMap {
  2371. nodeIP := nodeIPs[0]
  2372. ginkgo.By(fmt.Sprintf("reading clientIP using the TCP service's NodePort, on node %v: %v%v%v", nodeName, nodeIP, tcpNodePort, path))
  2373. content := GetHTTPContent(nodeIP, tcpNodePort, e2eservice.KubeProxyLagTimeout, path)
  2374. clientIP := content.String()
  2375. framework.Logf("ClientIP detected by target pod using NodePort is %s", clientIP)
  2376. if strings.HasPrefix(clientIP, "10.") {
  2377. framework.Failf("Source IP was NOT preserved")
  2378. }
  2379. }
  2380. })
  2381. ginkgo.It("should only target nodes with endpoints", func() {
  2382. namespace := f.Namespace.Name
  2383. serviceName := "external-local-nodes"
  2384. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2385. nodes, err := e2enode.GetBoundedReadySchedulableNodes(cs, e2eservice.MaxNodesForEndpointsTests)
  2386. framework.ExpectNoError(err)
  2387. svc, err := jig.CreateOnlyLocalLoadBalancerService(loadBalancerCreateTimeout, false,
  2388. func(svc *v1.Service) {
  2389. // Change service port to avoid collision with opened hostPorts
  2390. // in other tests that run in parallel.
  2391. if len(svc.Spec.Ports) != 0 {
  2392. svc.Spec.Ports[0].TargetPort = intstr.FromInt(int(svc.Spec.Ports[0].Port))
  2393. svc.Spec.Ports[0].Port = 8081
  2394. }
  2395. })
  2396. framework.ExpectNoError(err)
  2397. serviceLBNames = append(serviceLBNames, cloudprovider.DefaultLoadBalancerName(svc))
  2398. defer func() {
  2399. err = jig.ChangeServiceType(v1.ServiceTypeClusterIP, loadBalancerCreateTimeout)
  2400. framework.ExpectNoError(err)
  2401. err := cs.CoreV1().Services(svc.Namespace).Delete(context.TODO(), svc.Name, nil)
  2402. framework.ExpectNoError(err)
  2403. }()
  2404. healthCheckNodePort := int(svc.Spec.HealthCheckNodePort)
  2405. if healthCheckNodePort == 0 {
  2406. framework.Failf("Service HealthCheck NodePort was not allocated")
  2407. }
  2408. ips := e2enode.CollectAddresses(nodes, v1.NodeExternalIP)
  2409. ingressIP := e2eservice.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0])
  2410. svcTCPPort := int(svc.Spec.Ports[0].Port)
  2411. threshold := 2
  2412. path := "/healthz"
  2413. for i := 0; i < len(nodes.Items); i++ {
  2414. endpointNodeName := nodes.Items[i].Name
  2415. ginkgo.By("creating a pod to be part of the service " + serviceName + " on node " + endpointNodeName)
  2416. _, err = jig.Run(func(rc *v1.ReplicationController) {
  2417. rc.Name = serviceName
  2418. if endpointNodeName != "" {
  2419. rc.Spec.Template.Spec.NodeName = endpointNodeName
  2420. }
  2421. })
  2422. framework.ExpectNoError(err)
  2423. ginkgo.By(fmt.Sprintf("waiting for service endpoint on node %v", endpointNodeName))
  2424. err = jig.WaitForEndpointOnNode(endpointNodeName)
  2425. framework.ExpectNoError(err)
  2426. // HealthCheck should pass only on the node where num(endpoints) > 0
  2427. // All other nodes should fail the healthcheck on the service healthCheckNodePort
  2428. for n, publicIP := range ips {
  2429. // Make sure the loadbalancer picked up the health check change.
  2430. // Confirm traffic can reach backend through LB before checking healthcheck nodeport.
  2431. e2eservice.TestReachableHTTP(ingressIP, svcTCPPort, e2eservice.KubeProxyLagTimeout)
  2432. expectedSuccess := nodes.Items[n].Name == endpointNodeName
  2433. port := strconv.Itoa(healthCheckNodePort)
  2434. ipPort := net.JoinHostPort(publicIP, port)
  2435. framework.Logf("Health checking %s, http://%s%s, expectedSuccess %v", nodes.Items[n].Name, ipPort, path, expectedSuccess)
  2436. err := TestHTTPHealthCheckNodePort(publicIP, healthCheckNodePort, path, e2eservice.KubeProxyEndpointLagTimeout, expectedSuccess, threshold)
  2437. framework.ExpectNoError(err)
  2438. }
  2439. framework.ExpectNoError(e2erc.DeleteRCAndWaitForGC(f.ClientSet, namespace, serviceName))
  2440. }
  2441. })
  2442. ginkgo.It("should work from pods", func() {
  2443. var err error
  2444. namespace := f.Namespace.Name
  2445. serviceName := "external-local-pods"
  2446. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2447. svc, err := jig.CreateOnlyLocalLoadBalancerService(loadBalancerCreateTimeout, true, nil)
  2448. framework.ExpectNoError(err)
  2449. serviceLBNames = append(serviceLBNames, cloudprovider.DefaultLoadBalancerName(svc))
  2450. defer func() {
  2451. err = jig.ChangeServiceType(v1.ServiceTypeClusterIP, loadBalancerCreateTimeout)
  2452. framework.ExpectNoError(err)
  2453. err := cs.CoreV1().Services(svc.Namespace).Delete(context.TODO(), svc.Name, nil)
  2454. framework.ExpectNoError(err)
  2455. }()
  2456. ingressIP := e2eservice.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0])
  2457. port := strconv.Itoa(int(svc.Spec.Ports[0].Port))
  2458. ipPort := net.JoinHostPort(ingressIP, port)
  2459. path := fmt.Sprintf("%s/clientip", ipPort)
  2460. ginkgo.By("Creating pause pod deployment to make sure, pausePods are in desired state")
  2461. deployment := createPausePodDeployment(cs, "pause-pod-deployment", namespace, 1)
  2462. framework.ExpectNoError(e2edeploy.WaitForDeploymentComplete(cs, deployment), "Failed to complete pause pod deployment")
  2463. defer func() {
  2464. framework.Logf("Deleting deployment")
  2465. err = cs.AppsV1().Deployments(namespace).Delete(context.TODO(), deployment.Name, &metav1.DeleteOptions{})
  2466. framework.ExpectNoError(err, "Failed to delete deployment %s", deployment.Name)
  2467. }()
  2468. deployment, err = cs.AppsV1().Deployments(namespace).Get(context.TODO(), deployment.Name, metav1.GetOptions{})
  2469. framework.ExpectNoError(err, "Error in retrieving pause pod deployment")
  2470. labelSelector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
  2471. framework.ExpectNoError(err, "Error in setting LabelSelector as selector from deployment")
  2472. pausePods, err := cs.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelector.String()})
  2473. framework.ExpectNoError(err, "Error in listing pods associated with pause pod deployments")
  2474. pausePod := pausePods.Items[0]
  2475. framework.Logf("Waiting up to %v curl %v", e2eservice.KubeProxyLagTimeout, path)
  2476. cmd := fmt.Sprintf(`curl -q -s --connect-timeout 30 %v`, path)
  2477. var srcIP string
  2478. ginkgo.By(fmt.Sprintf("Hitting external lb %v from pod %v on node %v", ingressIP, pausePod.Name, pausePod.Spec.NodeName))
  2479. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.LoadBalancerPropagationTimeoutDefault, func() (bool, error) {
  2480. stdout, err := framework.RunHostCmd(pausePod.Namespace, pausePod.Name, cmd)
  2481. if err != nil {
  2482. framework.Logf("got err: %v, retry until timeout", err)
  2483. return false, nil
  2484. }
  2485. srcIP = strings.TrimSpace(strings.Split(stdout, ":")[0])
  2486. return srcIP == pausePod.Status.PodIP, nil
  2487. }); pollErr != nil {
  2488. framework.Failf("Source IP not preserved from %v, expected '%v' got '%v'", pausePod.Name, pausePod.Status.PodIP, srcIP)
  2489. }
  2490. })
  2491. ginkgo.It("should handle updates to ExternalTrafficPolicy field", func() {
  2492. namespace := f.Namespace.Name
  2493. serviceName := "external-local-update"
  2494. jig := e2eservice.NewTestJig(cs, namespace, serviceName)
  2495. nodes, err := e2enode.GetBoundedReadySchedulableNodes(cs, e2eservice.MaxNodesForEndpointsTests)
  2496. framework.ExpectNoError(err)
  2497. if len(nodes.Items) < 2 {
  2498. framework.Failf("Need at least 2 nodes to verify source ip from a node without endpoint")
  2499. }
  2500. svc, err := jig.CreateOnlyLocalLoadBalancerService(loadBalancerCreateTimeout, true, nil)
  2501. framework.ExpectNoError(err)
  2502. serviceLBNames = append(serviceLBNames, cloudprovider.DefaultLoadBalancerName(svc))
  2503. defer func() {
  2504. err = jig.ChangeServiceType(v1.ServiceTypeClusterIP, loadBalancerCreateTimeout)
  2505. framework.ExpectNoError(err)
  2506. err := cs.CoreV1().Services(svc.Namespace).Delete(context.TODO(), svc.Name, nil)
  2507. framework.ExpectNoError(err)
  2508. }()
  2509. // save the health check node port because it disappears when ESIPP is turned off.
  2510. healthCheckNodePort := int(svc.Spec.HealthCheckNodePort)
  2511. ginkgo.By("turning ESIPP off")
  2512. svc, err = jig.UpdateService(func(svc *v1.Service) {
  2513. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
  2514. })
  2515. framework.ExpectNoError(err)
  2516. if svc.Spec.HealthCheckNodePort > 0 {
  2517. framework.Failf("Service HealthCheck NodePort still present")
  2518. }
  2519. endpointNodeMap, err := jig.GetEndpointNodes()
  2520. framework.ExpectNoError(err)
  2521. noEndpointNodeMap := map[string][]string{}
  2522. for _, n := range nodes.Items {
  2523. if _, ok := endpointNodeMap[n.Name]; ok {
  2524. continue
  2525. }
  2526. noEndpointNodeMap[n.Name] = e2enode.GetAddresses(&n, v1.NodeExternalIP)
  2527. }
  2528. svcTCPPort := int(svc.Spec.Ports[0].Port)
  2529. svcNodePort := int(svc.Spec.Ports[0].NodePort)
  2530. ingressIP := e2eservice.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0])
  2531. path := "/clientip"
  2532. ginkgo.By(fmt.Sprintf("endpoints present on nodes %v, absent on nodes %v", endpointNodeMap, noEndpointNodeMap))
  2533. for nodeName, nodeIPs := range noEndpointNodeMap {
  2534. ginkgo.By(fmt.Sprintf("Checking %v (%v:%v%v) proxies to endpoints on another node", nodeName, nodeIPs[0], svcNodePort, path))
  2535. GetHTTPContent(nodeIPs[0], svcNodePort, e2eservice.KubeProxyLagTimeout, path)
  2536. }
  2537. for nodeName, nodeIPs := range endpointNodeMap {
  2538. ginkgo.By(fmt.Sprintf("checking kube-proxy health check fails on node with endpoint (%s), public IP %s", nodeName, nodeIPs[0]))
  2539. var body bytes.Buffer
  2540. pollfn := func() (bool, error) {
  2541. result := e2enetwork.PokeHTTP(nodeIPs[0], healthCheckNodePort, "/healthz", nil)
  2542. if result.Code == 0 {
  2543. return true, nil
  2544. }
  2545. body.Reset()
  2546. body.Write(result.Body)
  2547. return false, nil
  2548. }
  2549. if pollErr := wait.PollImmediate(framework.Poll, e2eservice.TestTimeout, pollfn); pollErr != nil {
  2550. framework.Failf("Kube-proxy still exposing health check on node %v:%v, after ESIPP was turned off. body %s",
  2551. nodeName, healthCheckNodePort, body.String())
  2552. }
  2553. }
  2554. // Poll till kube-proxy re-adds the MASQUERADE rule on the node.
  2555. ginkgo.By(fmt.Sprintf("checking source ip is NOT preserved through loadbalancer %v", ingressIP))
  2556. var clientIP string
  2557. pollErr := wait.PollImmediate(framework.Poll, e2eservice.KubeProxyLagTimeout, func() (bool, error) {
  2558. content := GetHTTPContent(ingressIP, svcTCPPort, e2eservice.KubeProxyLagTimeout, "/clientip")
  2559. clientIP = content.String()
  2560. if strings.HasPrefix(clientIP, "10.") {
  2561. return true, nil
  2562. }
  2563. return false, nil
  2564. })
  2565. if pollErr != nil {
  2566. framework.Failf("Source IP WAS preserved even after ESIPP turned off. Got %v, expected a ten-dot cluster ip.", clientIP)
  2567. }
  2568. // TODO: We need to attempt to create another service with the previously
  2569. // allocated healthcheck nodePort. If the health check nodePort has been
  2570. // freed, the new service creation will succeed, upon which we cleanup.
  2571. // If the health check nodePort has NOT been freed, the new service
  2572. // creation will fail.
  2573. ginkgo.By("setting ExternalTraffic field back to OnlyLocal")
  2574. svc, err = jig.UpdateService(func(svc *v1.Service) {
  2575. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
  2576. // Request the same healthCheckNodePort as before, to test the user-requested allocation path
  2577. svc.Spec.HealthCheckNodePort = int32(healthCheckNodePort)
  2578. })
  2579. framework.ExpectNoError(err)
  2580. pollErr = wait.PollImmediate(framework.Poll, e2eservice.KubeProxyLagTimeout, func() (bool, error) {
  2581. content := GetHTTPContent(ingressIP, svcTCPPort, e2eservice.KubeProxyLagTimeout, path)
  2582. clientIP = content.String()
  2583. ginkgo.By(fmt.Sprintf("Endpoint %v:%v%v returned client ip %v", ingressIP, svcTCPPort, path, clientIP))
  2584. if !strings.HasPrefix(clientIP, "10.") {
  2585. return true, nil
  2586. }
  2587. return false, nil
  2588. })
  2589. if pollErr != nil {
  2590. framework.Failf("Source IP (%v) is not the client IP even after ESIPP turned on, expected a public IP.", clientIP)
  2591. }
  2592. })
  2593. })
  2594. func execSourceipTest(pausePod v1.Pod, serviceAddress string) (string, string) {
  2595. var err error
  2596. var stdout string
  2597. timeout := 2 * time.Minute
  2598. framework.Logf("Waiting up to %v to get response from %s", timeout, serviceAddress)
  2599. cmd := fmt.Sprintf(`curl -q -s --connect-timeout 30 %s/clientip`, serviceAddress)
  2600. for start := time.Now(); time.Since(start) < timeout; time.Sleep(2 * time.Second) {
  2601. stdout, err = framework.RunHostCmd(pausePod.Namespace, pausePod.Name, cmd)
  2602. if err != nil {
  2603. framework.Logf("got err: %v, retry until timeout", err)
  2604. continue
  2605. }
  2606. // Need to check output because it might omit in case of error.
  2607. if strings.TrimSpace(stdout) == "" {
  2608. framework.Logf("got empty stdout, retry until timeout")
  2609. continue
  2610. }
  2611. break
  2612. }
  2613. framework.ExpectNoError(err)
  2614. // The stdout return from RunHostCmd is in this format: x.x.x.x:port or [xx:xx:xx::x]:port
  2615. host, _, err := net.SplitHostPort(stdout)
  2616. if err != nil {
  2617. // ginkgo.Fail the test if output format is unexpected.
  2618. framework.Failf("exec pod returned unexpected stdout: [%v]\n", stdout)
  2619. }
  2620. return pausePod.Status.PodIP, host
  2621. }
  2622. func execAffinityTestForNonLBServiceWithTransition(f *framework.Framework, cs clientset.Interface, svc *v1.Service) {
  2623. execAffinityTestForNonLBServiceWithOptionalTransition(f, cs, svc, true)
  2624. }
  2625. func execAffinityTestForNonLBService(f *framework.Framework, cs clientset.Interface, svc *v1.Service) {
  2626. execAffinityTestForNonLBServiceWithOptionalTransition(f, cs, svc, false)
  2627. }
  2628. // execAffinityTestForNonLBServiceWithOptionalTransition is a helper function that wrap the logic of
  2629. // affinity test for non-load-balancer services. Session afinity will be
  2630. // enabled when the service is created. If parameter isTransitionTest is true,
  2631. // session affinity will be switched off/on and test if the service converges
  2632. // to a stable affinity state.
  2633. func execAffinityTestForNonLBServiceWithOptionalTransition(f *framework.Framework, cs clientset.Interface, svc *v1.Service, isTransitionTest bool) {
  2634. ns := f.Namespace.Name
  2635. numPods, servicePort, serviceName := 3, defaultServeHostnameServicePort, svc.ObjectMeta.Name
  2636. ginkgo.By("creating service in namespace " + ns)
  2637. serviceType := svc.Spec.Type
  2638. svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP
  2639. _, _, err := StartServeHostnameService(cs, svc, ns, numPods)
  2640. framework.ExpectNoError(err, "failed to create replication controller with service in the namespace: %s", ns)
  2641. defer func() {
  2642. StopServeHostnameService(cs, ns, serviceName)
  2643. }()
  2644. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  2645. svc, err = jig.Client.CoreV1().Services(ns).Get(context.TODO(), serviceName, metav1.GetOptions{})
  2646. framework.ExpectNoError(err, "failed to fetch service: %s in namespace: %s", serviceName, ns)
  2647. var svcIP string
  2648. if serviceType == v1.ServiceTypeNodePort {
  2649. nodes, err := e2enode.GetReadySchedulableNodes(cs)
  2650. framework.ExpectNoError(err)
  2651. addrs := e2enode.CollectAddresses(nodes, v1.NodeInternalIP)
  2652. gomega.Expect(len(addrs)).To(gomega.BeNumerically(">", 0), "ginkgo.Failed to get Node internal IP")
  2653. svcIP = addrs[0]
  2654. servicePort = int(svc.Spec.Ports[0].NodePort)
  2655. } else {
  2656. svcIP = svc.Spec.ClusterIP
  2657. }
  2658. execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod-affinity", nil)
  2659. defer func() {
  2660. framework.Logf("Cleaning up the exec pod")
  2661. err := cs.CoreV1().Pods(ns).Delete(context.TODO(), execPod.Name, nil)
  2662. framework.ExpectNoError(err, "failed to delete pod: %s in namespace: %s", execPod.Name, ns)
  2663. }()
  2664. err = jig.CheckServiceReachability(svc, execPod)
  2665. framework.ExpectNoError(err)
  2666. if !isTransitionTest {
  2667. framework.ExpectEqual(checkAffinity(execPod, svcIP, servicePort, true), true)
  2668. }
  2669. if isTransitionTest {
  2670. _, err = jig.UpdateService(func(svc *v1.Service) {
  2671. svc.Spec.SessionAffinity = v1.ServiceAffinityNone
  2672. })
  2673. framework.ExpectNoError(err)
  2674. framework.ExpectEqual(checkAffinity(execPod, svcIP, servicePort, false), true)
  2675. _, err = jig.UpdateService(func(svc *v1.Service) {
  2676. svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP
  2677. })
  2678. framework.ExpectNoError(err)
  2679. framework.ExpectEqual(checkAffinity(execPod, svcIP, servicePort, true), true)
  2680. }
  2681. }
  2682. func execAffinityTestForLBServiceWithTransition(f *framework.Framework, cs clientset.Interface, svc *v1.Service) {
  2683. execAffinityTestForLBServiceWithOptionalTransition(f, cs, svc, true)
  2684. }
  2685. func execAffinityTestForLBService(f *framework.Framework, cs clientset.Interface, svc *v1.Service) {
  2686. execAffinityTestForLBServiceWithOptionalTransition(f, cs, svc, false)
  2687. }
  2688. // execAffinityTestForLBServiceWithOptionalTransition is a helper function that wrap the logic of
  2689. // affinity test for load balancer services, similar to
  2690. // execAffinityTestForNonLBServiceWithOptionalTransition.
  2691. func execAffinityTestForLBServiceWithOptionalTransition(f *framework.Framework, cs clientset.Interface, svc *v1.Service, isTransitionTest bool) {
  2692. numPods, ns, serviceName := 3, f.Namespace.Name, svc.ObjectMeta.Name
  2693. ginkgo.By("creating service in namespace " + ns)
  2694. svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP
  2695. _, _, err := StartServeHostnameService(cs, svc, ns, numPods)
  2696. framework.ExpectNoError(err, "failed to create replication controller with service in the namespace: %s", ns)
  2697. jig := e2eservice.NewTestJig(cs, ns, serviceName)
  2698. ginkgo.By("waiting for loadbalancer for service " + ns + "/" + serviceName)
  2699. svc, err = jig.WaitForLoadBalancer(e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
  2700. framework.ExpectNoError(err)
  2701. defer func() {
  2702. podNodePairs, err := e2enode.PodNodePairs(cs, ns)
  2703. framework.Logf("[pod,node] pairs: %+v; err: %v", podNodePairs, err)
  2704. StopServeHostnameService(cs, ns, serviceName)
  2705. lb := cloudprovider.DefaultLoadBalancerName(svc)
  2706. framework.Logf("cleaning load balancer resource for %s", lb)
  2707. e2eservice.CleanupServiceResources(cs, lb, framework.TestContext.CloudConfig.Region, framework.TestContext.CloudConfig.Zone)
  2708. }()
  2709. ingressIP := e2eservice.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0])
  2710. port := int(svc.Spec.Ports[0].Port)
  2711. if !isTransitionTest {
  2712. framework.ExpectEqual(checkAffinity(nil, ingressIP, port, true), true)
  2713. }
  2714. if isTransitionTest {
  2715. svc, err = jig.UpdateService(func(svc *v1.Service) {
  2716. svc.Spec.SessionAffinity = v1.ServiceAffinityNone
  2717. })
  2718. framework.ExpectNoError(err)
  2719. framework.ExpectEqual(checkAffinity(nil, ingressIP, port, false), true)
  2720. svc, err = jig.UpdateService(func(svc *v1.Service) {
  2721. svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP
  2722. })
  2723. framework.ExpectNoError(err)
  2724. framework.ExpectEqual(checkAffinity(nil, ingressIP, port, true), true)
  2725. }
  2726. }
  2727. func createAndGetExternalServiceFQDN(cs clientset.Interface, ns, serviceName string) string {
  2728. _, _, err := StartServeHostnameService(cs, getServeHostnameService(serviceName), ns, 2)
  2729. framework.ExpectNoError(err, "Expected Service %s to be running", serviceName)
  2730. return fmt.Sprintf("%s.%s.svc.%s", serviceName, ns, framework.TestContext.ClusterDNSDomain)
  2731. }
  2732. func createPausePodDeployment(cs clientset.Interface, name, ns string, replicas int) *appsv1.Deployment {
  2733. labels := map[string]string{"deployment": "agnhost-pause"}
  2734. pauseDeployment := e2edeploy.NewDeployment(name, int32(replicas), labels, "", "", appsv1.RollingUpdateDeploymentStrategyType)
  2735. pauseDeployment.Spec.Template.Spec.Containers[0] = v1.Container{
  2736. Name: "agnhost-pause",
  2737. Image: imageutils.GetE2EImage(imageutils.Agnhost),
  2738. Args: []string{"pause"},
  2739. }
  2740. pauseDeployment.Spec.Template.Spec.Affinity = &v1.Affinity{
  2741. PodAntiAffinity: &v1.PodAntiAffinity{
  2742. RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
  2743. {
  2744. LabelSelector: &metav1.LabelSelector{MatchLabels: labels},
  2745. TopologyKey: "kubernetes.io/hostname",
  2746. Namespaces: []string{ns},
  2747. },
  2748. },
  2749. },
  2750. }
  2751. deployment, err := cs.AppsV1().Deployments(ns).Create(context.TODO(), pauseDeployment, metav1.CreateOptions{})
  2752. framework.ExpectNoError(err, "Error in creating deployment for pause pod")
  2753. return deployment
  2754. }
  2755. // createPodOrFail creates a pod with the specified containerPorts.
  2756. func createPodOrFail(c clientset.Interface, ns, name string, labels map[string]string, containerPorts []v1.ContainerPort) {
  2757. ginkgo.By(fmt.Sprintf("Creating pod %s in namespace %s", name, ns))
  2758. pod := &v1.Pod{
  2759. ObjectMeta: metav1.ObjectMeta{
  2760. Name: name,
  2761. Labels: labels,
  2762. },
  2763. Spec: v1.PodSpec{
  2764. Containers: []v1.Container{
  2765. {
  2766. Name: "pause",
  2767. Image: imageutils.GetE2EImage(imageutils.Agnhost),
  2768. Args: []string{"pause"},
  2769. Ports: containerPorts,
  2770. // Add a dummy environment variable to work around a docker issue.
  2771. // https://github.com/docker/docker/issues/14203
  2772. Env: []v1.EnvVar{{Name: "FOO", Value: " "}},
  2773. },
  2774. },
  2775. },
  2776. }
  2777. _, err := c.CoreV1().Pods(ns).Create(context.TODO(), pod, metav1.CreateOptions{})
  2778. framework.ExpectNoError(err, "failed to create pod %s in namespace %s", name, ns)
  2779. }
  2780. // launchHostExecPod launches a hostexec pod in the given namespace and waits
  2781. // until it's Running
  2782. func launchHostExecPod(client clientset.Interface, ns, name string) *v1.Pod {
  2783. hostExecPod := e2epod.NewExecPodSpec(ns, name, true)
  2784. pod, err := client.CoreV1().Pods(ns).Create(context.TODO(), hostExecPod, metav1.CreateOptions{})
  2785. framework.ExpectNoError(err)
  2786. err = e2epod.WaitForPodRunningInNamespace(client, pod)
  2787. framework.ExpectNoError(err)
  2788. return pod
  2789. }
  2790. // checkReachabilityFromPod checks reachability from the specified pod.
  2791. func checkReachabilityFromPod(expectToBeReachable bool, timeout time.Duration, namespace, pod, target string) {
  2792. cmd := fmt.Sprintf("wget -T 5 -qO- %q", target)
  2793. err := wait.PollImmediate(framework.Poll, timeout, func() (bool, error) {
  2794. _, err := framework.RunHostCmd(namespace, pod, cmd)
  2795. if expectToBeReachable && err != nil {
  2796. framework.Logf("Expect target to be reachable. But got err: %v. Retry until timeout", err)
  2797. return false, nil
  2798. }
  2799. if !expectToBeReachable && err == nil {
  2800. framework.Logf("Expect target NOT to be reachable. But it is reachable. Retry until timeout")
  2801. return false, nil
  2802. }
  2803. return true, nil
  2804. })
  2805. framework.ExpectNoError(err)
  2806. }
  2807. // proxyMode returns a proxyMode of a kube-proxy.
  2808. func proxyMode(f *framework.Framework) (string, error) {
  2809. pod := &v1.Pod{
  2810. ObjectMeta: metav1.ObjectMeta{
  2811. Name: "kube-proxy-mode-detector",
  2812. Namespace: f.Namespace.Name,
  2813. },
  2814. Spec: v1.PodSpec{
  2815. HostNetwork: true,
  2816. Containers: []v1.Container{
  2817. {
  2818. Name: "detector",
  2819. Image: framework.AgnHostImage,
  2820. Args: []string{"pause"},
  2821. },
  2822. },
  2823. },
  2824. }
  2825. f.PodClient().CreateSync(pod)
  2826. defer f.PodClient().DeleteSync(pod.Name, &metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout)
  2827. cmd := "curl -q -s --connect-timeout 1 http://localhost:10249/proxyMode"
  2828. stdout, err := framework.RunHostCmd(pod.Namespace, pod.Name, cmd)
  2829. if err != nil {
  2830. return "", err
  2831. }
  2832. framework.Logf("proxyMode: %s", stdout)
  2833. return stdout, nil
  2834. }
  2835. // enableAndDisableInternalLB returns two functions for enabling and disabling the internal load balancer
  2836. // setting for the supported cloud providers (currently GCE/GKE and Azure) and empty functions for others.
  2837. func enableAndDisableInternalLB() (enable func(svc *v1.Service), disable func(svc *v1.Service)) {
  2838. return framework.TestContext.CloudConfig.Provider.EnableAndDisableInternalLB()
  2839. }
  2840. func validatePorts(ep e2eendpoints.PortsByPodUID, expectedEndpoints e2eendpoints.PortsByPodUID) error {
  2841. if len(ep) != len(expectedEndpoints) {
  2842. // should not happen because we check this condition before
  2843. return fmt.Errorf("invalid number of endpoints got %v, expected %v", ep, expectedEndpoints)
  2844. }
  2845. for podUID := range expectedEndpoints {
  2846. if _, ok := ep[podUID]; !ok {
  2847. return fmt.Errorf("endpoint %v not found", podUID)
  2848. }
  2849. if len(ep[podUID]) != len(expectedEndpoints[podUID]) {
  2850. return fmt.Errorf("invalid list of ports for uid %v. Got %v, expected %v", podUID, ep[podUID], expectedEndpoints[podUID])
  2851. }
  2852. sort.Ints(ep[podUID])
  2853. sort.Ints(expectedEndpoints[podUID])
  2854. for index := range ep[podUID] {
  2855. if ep[podUID][index] != expectedEndpoints[podUID][index] {
  2856. return fmt.Errorf("invalid list of ports for uid %v. Got %v, expected %v", podUID, ep[podUID], expectedEndpoints[podUID])
  2857. }
  2858. }
  2859. }
  2860. return nil
  2861. }
  2862. func translatePodNameToUID(c clientset.Interface, ns string, expectedEndpoints portsByPodName) (e2eendpoints.PortsByPodUID, error) {
  2863. portsByUID := make(e2eendpoints.PortsByPodUID)
  2864. for name, portList := range expectedEndpoints {
  2865. pod, err := c.CoreV1().Pods(ns).Get(context.TODO(), name, metav1.GetOptions{})
  2866. if err != nil {
  2867. return nil, fmt.Errorf("failed to get pod %s, that's pretty weird. validation failed: %s", name, err)
  2868. }
  2869. portsByUID[pod.ObjectMeta.UID] = portList
  2870. }
  2871. return portsByUID, nil
  2872. }
  2873. // validateEndpointsPorts validates that the given service exists and is served by the given expectedEndpoints.
  2874. func validateEndpointsPorts(c clientset.Interface, namespace, serviceName string, expectedEndpoints portsByPodName) error {
  2875. ginkgo.By(fmt.Sprintf("waiting up to %v for service %s in namespace %s to expose endpoints %v", framework.ServiceStartTimeout, serviceName, namespace, expectedEndpoints))
  2876. i := 1
  2877. for start := time.Now(); time.Since(start) < framework.ServiceStartTimeout; time.Sleep(1 * time.Second) {
  2878. ep, err := c.CoreV1().Endpoints(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
  2879. if err != nil {
  2880. framework.Logf("Get endpoints failed (%v elapsed, ignoring for 5s): %v", time.Since(start), err)
  2881. continue
  2882. }
  2883. portsByPodUID := e2eendpoints.GetContainerPortsByPodUID(ep)
  2884. expectedPortsByPodUID, err := translatePodNameToUID(c, namespace, expectedEndpoints)
  2885. if err != nil {
  2886. return err
  2887. }
  2888. if len(portsByPodUID) == len(expectedEndpoints) {
  2889. err := validatePorts(portsByPodUID, expectedPortsByPodUID)
  2890. if err != nil {
  2891. return err
  2892. }
  2893. framework.Logf("successfully validated that service %s in namespace %s exposes endpoints %v (%v elapsed)",
  2894. serviceName, namespace, expectedEndpoints, time.Since(start))
  2895. return nil
  2896. }
  2897. if i%5 == 0 {
  2898. framework.Logf("Unexpected endpoints: found %v, expected %v (%v elapsed, will retry)", portsByPodUID, expectedEndpoints, time.Since(start))
  2899. }
  2900. i++
  2901. }
  2902. if pods, err := c.CoreV1().Pods(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{}); err == nil {
  2903. for _, pod := range pods.Items {
  2904. framework.Logf("Pod %s\t%s\t%s\t%s", pod.Namespace, pod.Name, pod.Spec.NodeName, pod.DeletionTimestamp)
  2905. }
  2906. } else {
  2907. framework.Logf("Can't list pod debug info: %v", err)
  2908. }
  2909. return fmt.Errorf("Timed out waiting for service %s in namespace %s to expose endpoints %v (%v elapsed)", serviceName, namespace, expectedEndpoints, framework.ServiceStartTimeout)
  2910. }