Merge pull request #109483 from cyclinder/fix_healthz

kube-proxy: fix healthz return unexpect code 200
This commit is contained in:
Kubernetes Prow Robot 2022-05-05 06:40:19 -07:00 committed by GitHub
commit 8f7e80cd89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -44,6 +44,7 @@ type ProxierHealthUpdater interface {
}
var _ ProxierHealthUpdater = &proxierHealthServer{}
var zeroTime = time.Time{}
// proxierHealthServer returns 200 "OK" by default. It verifies that the delay between
// QueuedUpdate() calls and Updated() calls never exceeds healthTimeout.
@ -57,8 +58,8 @@ type proxierHealthServer struct {
recorder events.EventRecorder
nodeRef *v1.ObjectReference
lastUpdated atomic.Value
lastQueued atomic.Value
lastUpdated atomic.Value
oldestPendingQueued atomic.Value
}
// NewProxierHealthServer returns a proxier health http server.
@ -80,12 +81,14 @@ func newProxierHealthServer(listener listener, httpServerFactory httpServerFacto
// Updated updates the lastUpdated timestamp.
func (hs *proxierHealthServer) Updated() {
hs.oldestPendingQueued.Store(zeroTime)
hs.lastUpdated.Store(hs.clock.Now())
}
// QueuedUpdate updates the lastQueued timestamp.
func (hs *proxierHealthServer) QueuedUpdate() {
hs.lastQueued.Store(hs.clock.Now())
// Set oldestPendingQueued only if it's currently zero
hs.oldestPendingQueued.CompareAndSwap(zeroTime, hs.clock.Now())
}
// Run starts the healthz HTTP server and blocks until it exits.
@ -117,9 +120,9 @@ type healthzHandler struct {
}
func (h healthzHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
var lastQueued, lastUpdated time.Time
if val := h.hs.lastQueued.Load(); val != nil {
lastQueued = val.(time.Time)
var oldestPendingQueued, lastUpdated time.Time
if val := h.hs.oldestPendingQueued.Load(); val != nil {
oldestPendingQueued = val.(time.Time)
}
if val := h.hs.lastUpdated.Load(); val != nil {
lastUpdated = val.(time.Time)
@ -128,15 +131,11 @@ func (h healthzHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
healthy := false
switch {
case lastUpdated.IsZero():
case oldestPendingQueued.IsZero():
// The proxy is healthy while it's starting up
// TODO: this makes it useless as a readinessProbe. Consider changing
// to only become healthy after the proxy is fully synced.
// or the proxy is fully synced.
healthy = true
case lastUpdated.After(lastQueued):
// We've processed all updates
healthy = true
case currentTime.Sub(lastQueued) < h.hs.healthTimeout:
case currentTime.Sub(oldestPendingQueued) < h.hs.healthTimeout:
// There's an unprocessed update queued, but it's not late yet
healthy = true
}
@ -147,14 +146,12 @@ func (h healthzHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
resp.WriteHeader(http.StatusServiceUnavailable)
} else {
resp.WriteHeader(http.StatusOK)
// In older releases, the returned "lastUpdated" time indicated the last
// time the proxier sync loop ran, even if nothing had changed. To
// preserve compatibility, we use the same semantics: the returned
// lastUpdated value is "recent" if the server is healthy. The kube-proxy
// metrics provide more detailed information.
lastUpdated = currentTime
}
fmt.Fprintf(resp, `{"lastUpdated": %q,"currentTime": %q}`, lastUpdated, currentTime)
}