Skip to content

Commit 3e8c7c8

Browse files
committed
UPSTREAM: <carry>: provide events, messages, and bodies for probe failures of important pods
1 parent 3e36a97 commit 3e8c7c8

File tree

4 files changed

+87
-11
lines changed

4 files changed

+87
-11
lines changed

pkg/kubelet/prober/patch_prober.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package prober
2+
3+
import (
4+
"net/http"
5+
"net/url"
6+
"strings"
7+
"time"
8+
9+
v1 "k8s.io/api/core/v1"
10+
"k8s.io/klog/v2"
11+
"k8s.io/kubernetes/pkg/probe"
12+
httpprobe "k8s.io/kubernetes/pkg/probe/http"
13+
)
14+
15+
func (pb *prober) maybeProbeForBody(prober httpprobe.Prober, url *url.URL, headers http.Header, timeout time.Duration, pod *v1.Pod, container v1.Container, probeType probeType) (probe.Result, string, error) {
16+
if !isInterestingPod(pod) {
17+
return prober.Probe(url, headers, timeout)
18+
}
19+
bodyProber, ok := prober.(httpprobe.DetailedProber)
20+
if !ok {
21+
return prober.Probe(url, headers, timeout)
22+
}
23+
result, output, body, probeError := bodyProber.ProbeForBody(url, headers, timeout)
24+
switch result {
25+
case probe.Success:
26+
return result, output, probeError
27+
case probe.Warning, probe.Failure, probe.Unknown:
28+
// these pods are interesting enough to show the body content
29+
klog.Infof("interesting pod/%s container/%s namespace/%s: %s probe status=%v output=%q start-of-body=%s",
30+
pod.Name, container.Name, pod.Namespace, probeType, result, output, body)
31+
32+
// in fact, they are so interesting we'll try to send events for them
33+
pb.recordContainerEvent(pod, &container, v1.EventTypeWarning, "ProbeError", "%s probe error: %s\nbody: %s\n", probeType, output, body)
34+
return result, output, probeError
35+
default:
36+
return result, output, probeError
37+
}
38+
}
39+
40+
func isInterestingPod(pod *v1.Pod) bool {
41+
if pod == nil {
42+
return false
43+
}
44+
if strings.HasPrefix(pod.Namespace, "openshift-") {
45+
return true
46+
}
47+
48+
return false
49+
}

pkg/kubelet/prober/prober.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ func (pb *prober) runProbe(probeType probeType, p *v1.Probe, pod *v1.Pod, status
177177
klog.V(4).Infof("HTTP-Probe Headers: %v", headers)
178178
switch probeType {
179179
case liveness:
180-
return pb.livenessHTTP.Probe(url, headers, timeout)
180+
return pb.maybeProbeForBody(pb.livenessHTTP, url, headers, timeout, pod, container, probeType)
181181
case startup:
182-
return pb.startupHTTP.Probe(url, headers, timeout)
182+
return pb.maybeProbeForBody(pb.startupHTTP, url, headers, timeout, pod, container, probeType)
183183
default:
184-
return pb.readinessHTTP.Probe(url, headers, timeout)
184+
return pb.maybeProbeForBody(pb.readinessHTTP, url, headers, timeout, pod, container, probeType)
185185
}
186186
}
187187
if p.TCPSocket != nil {

pkg/probe/http/http.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ func (pr httpProber) Probe(url *url.URL, headers http.Header, timeout time.Durat
7676
Transport: pr.transport,
7777
CheckRedirect: redirectChecker(pr.followNonLocalRedirects),
7878
}
79-
return DoHTTPProbe(url, headers, client)
79+
result, details, _, err := DoHTTPProbe(url, headers, client)
80+
return result, details, err
8081
}
8182

8283
// GetHTTPInterface is an interface for making HTTP requests, that returns a response and error.
@@ -88,11 +89,11 @@ type GetHTTPInterface interface {
8889
// If the HTTP response code is successful (i.e. 400 > code >= 200), it returns Success.
8990
// If the HTTP response code is unsuccessful or HTTP communication fails, it returns Failure.
9091
// This is exported because some other packages may want to do direct HTTP probes.
91-
func DoHTTPProbe(url *url.URL, headers http.Header, client GetHTTPInterface) (probe.Result, string, error) {
92+
func DoHTTPProbe(url *url.URL, headers http.Header, client GetHTTPInterface) (probe.Result, string, string, error) {
9293
req, err := http.NewRequest("GET", url.String(), nil)
9394
if err != nil {
9495
// Convert errors into failures to catch timeouts.
95-
return probe.Failure, err.Error(), nil
96+
return probe.Failure, err.Error(), "", nil
9697
}
9798
if _, ok := headers["User-Agent"]; !ok {
9899
if headers == nil {
@@ -114,28 +115,28 @@ func DoHTTPProbe(url *url.URL, headers http.Header, client GetHTTPInterface) (pr
114115
res, err := client.Do(req)
115116
if err != nil {
116117
// Convert errors into failures to catch timeouts.
117-
return probe.Failure, err.Error(), nil
118+
return probe.Failure, err.Error(), "", nil
118119
}
119120
defer res.Body.Close()
120121
b, err := utilio.ReadAtMost(res.Body, maxRespBodyLength)
121122
if err != nil {
122123
if err == utilio.ErrLimitReached {
123124
klog.V(4).Infof("Non fatal body truncation for %s, Response: %v", url.String(), *res)
124125
} else {
125-
return probe.Failure, "", err
126+
return probe.Failure, "", "", err
126127
}
127128
}
128129
body := string(b)
129130
if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusBadRequest {
130131
if res.StatusCode >= http.StatusMultipleChoices { // Redirect
131132
klog.V(4).Infof("Probe terminated redirects for %s, Response: %v", url.String(), *res)
132-
return probe.Warning, body, nil
133+
return probe.Warning, body, body, nil
133134
}
134135
klog.V(4).Infof("Probe succeeded for %s, Response: %v", url.String(), *res)
135-
return probe.Success, body, nil
136+
return probe.Success, body, body, nil
136137
}
137138
klog.V(4).Infof("Probe failed for %s with request headers %v, response body: %v", url.String(), headers, body)
138-
return probe.Failure, fmt.Sprintf("HTTP probe failed with statuscode: %d", res.StatusCode), nil
139+
return probe.Failure, fmt.Sprintf("HTTP probe failed with statuscode: %d", res.StatusCode), body, nil
139140
}
140141

141142
func redirectChecker(followNonLocalRedirects bool) func(*http.Request, []*http.Request) error {

pkg/probe/http/patch_http.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package http
2+
3+
import (
4+
"net/http"
5+
"net/url"
6+
"time"
7+
8+
"k8s.io/kubernetes/pkg/probe"
9+
)
10+
11+
// Prober is an interface that defines the Probe function for doing HTTP readiness/liveness checks.
12+
type DetailedProber interface {
13+
ProbeForBody(url *url.URL, headers http.Header, timeout time.Duration) (probe.Result, string, string, error)
14+
}
15+
16+
// ProbeForBody returns a ProbeRunner capable of running an HTTP check.
17+
// returns result, details, body, error
18+
func (pr httpProber) ProbeForBody(url *url.URL, headers http.Header, timeout time.Duration) (probe.Result, string, string, error) {
19+
pr.transport.DisableCompression = true // removes Accept-Encoding header
20+
client := &http.Client{
21+
Timeout: timeout,
22+
Transport: pr.transport,
23+
CheckRedirect: redirectChecker(pr.followNonLocalRedirects),
24+
}
25+
return DoHTTPProbe(url, headers, client)
26+
}

0 commit comments

Comments
 (0)