Skip to content

Commit 3e438a9

Browse files
authored
Merge pull request kubernetes#92427 from wojtek-t/improve_affinity_tests
Improve LB session affinity tests
2 parents c90427d + 3c34b56 commit 3e438a9

File tree

1 file changed

+60
-21
lines changed

1 file changed

+60
-21
lines changed

test/e2e/network/service.go

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -101,42 +101,81 @@ var (
101101
// portsByPodName is a map that maps pod name to container ports.
102102
type portsByPodName map[string][]int
103103

104+
// affinityCheckFromPod returns interval, timeout and function pinging the service and
105+
// returning pinged hosts for pinging the service from execPod.
106+
func affinityCheckFromPod(execPod *v1.Pod, serviceIP string, servicePort int) (time.Duration, time.Duration, func() []string) {
107+
timeout := AffinityTimeout
108+
// interval considering a maximum of 2 seconds per connection
109+
interval := 2 * AffinityConfirmCount * time.Second
110+
111+
serviceIPPort := net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))
112+
curl := fmt.Sprintf(`curl -q -s --connect-timeout 2 http://%s/`, serviceIPPort)
113+
cmd := fmt.Sprintf("for i in $(seq 0 %d); do echo; %s ; done", AffinityConfirmCount, curl)
114+
getHosts := func() []string {
115+
stdout, err := framework.RunHostCmd(execPod.Namespace, execPod.Name, cmd)
116+
if err != nil {
117+
framework.Logf("Failed to get response from %s. Retry until timeout", serviceIPPort)
118+
return nil
119+
}
120+
return strings.Split(stdout, "\n")
121+
}
122+
123+
return interval, timeout, getHosts
124+
}
125+
126+
// affinityCheckFromTest returns interval, timeout and function pinging the service and
127+
// returning pinged hosts for pinging the service from the test itself.
128+
func affinityCheckFromTest(cs clientset.Interface, serviceIP string, servicePort int) (time.Duration, time.Duration, func() []string) {
129+
interval := 2 * time.Second
130+
timeout := e2eservice.GetServiceLoadBalancerPropagationTimeout(cs)
131+
132+
params := &e2enetwork.HTTPPokeParams{Timeout: 2 * time.Second}
133+
getHosts := func() []string {
134+
var hosts []string
135+
for i := 0; i < AffinityConfirmCount; i++ {
136+
result := e2enetwork.PokeHTTP(serviceIP, servicePort, "", params)
137+
if result.Status == e2enetwork.HTTPSuccess {
138+
hosts = append(hosts, string(result.Body))
139+
}
140+
}
141+
return hosts
142+
}
143+
144+
return interval, timeout, getHosts
145+
}
146+
104147
// CheckAffinity function tests whether the service affinity works as expected.
105148
// If affinity is expected, the test will return true once affinityConfirmCount
106149
// number of same response observed in a row. If affinity is not expected, the
107150
// test will keep observe until different responses observed. The function will
108151
// return false only in case of unexpected errors.
109152
func checkAffinity(cs clientset.Interface, execPod *v1.Pod, serviceIP string, servicePort int, shouldHold bool) bool {
110-
serviceIPPort := net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))
111-
curl := fmt.Sprintf(`curl -q -s --connect-timeout 2 http://%s/`, serviceIPPort)
112-
cmd := fmt.Sprintf("for i in $(seq 0 %d); do echo; %s ; done", AffinityConfirmCount, curl)
113-
timeout := AffinityTimeout
114-
if execPod == nil {
115-
timeout = e2eservice.GetServiceLoadBalancerPropagationTimeout(cs)
153+
var interval, timeout time.Duration
154+
var getHosts func() []string
155+
if execPod != nil {
156+
interval, timeout, getHosts = affinityCheckFromPod(execPod, serviceIP, servicePort)
157+
} else {
158+
interval, timeout, getHosts = affinityCheckFromTest(cs, serviceIP, servicePort)
116159
}
160+
117161
var tracker affinityTracker
118-
// interval considering a maximum of 2 seconds per connection
119-
interval := 2 * AffinityConfirmCount * time.Second
120162
if pollErr := wait.PollImmediate(interval, timeout, func() (bool, error) {
121-
if execPod != nil {
122-
stdout, err := framework.RunHostCmd(execPod.Namespace, execPod.Name, cmd)
123-
if err != nil {
124-
framework.Logf("Failed to get response from %s. Retry until timeout", serviceIPPort)
125-
return false, nil
126-
}
127-
hosts := strings.Split(stdout, "\n")
128-
for _, host := range hosts {
163+
hosts := getHosts()
164+
for _, host := range hosts {
165+
if len(host) > 0 {
129166
tracker.recordHost(strings.TrimSpace(host))
130167
}
131-
} else {
132-
rawResponse := GetHTTPContent(serviceIP, servicePort, timeout, "")
133-
tracker.recordHost(rawResponse.String())
134168
}
169+
135170
trackerFulfilled, affinityHolds := tracker.checkHostTrace(AffinityConfirmCount)
171+
if !trackerFulfilled {
172+
return false, nil
173+
}
174+
136175
if !shouldHold && !affinityHolds {
137176
return true, nil
138177
}
139-
if shouldHold && trackerFulfilled && affinityHolds {
178+
if shouldHold && affinityHolds {
140179
return true, nil
141180
}
142181
return false, nil
@@ -147,7 +186,7 @@ func checkAffinity(cs clientset.Interface, execPod *v1.Pod, serviceIP string, se
147186
return false
148187
}
149188
if !trackerFulfilled {
150-
checkAffinityFailed(tracker, fmt.Sprintf("Connection to %s timed out or not enough responses.", serviceIPPort))
189+
checkAffinityFailed(tracker, fmt.Sprintf("Connection timed out or not enough responses."))
151190
}
152191
if shouldHold {
153192
checkAffinityFailed(tracker, "Affinity should hold but didn't.")

0 commit comments

Comments
 (0)