Merge pull request #109188 from wojtek-t/pf_mitigate_delegated_requests

Fix the overestimated cost of deletaged API requests in P&F
This commit is contained in:
Kubernetes Prow Robot 2022-03-31 15:49:17 -07:00 committed by GitHub
commit 885f14d162
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 8 deletions

View File

@ -68,17 +68,23 @@ func (e *listWorkEstimator) estimate(r *http.Request, flowSchemaName, priorityLe
// pruner will eventually remove the CRD from the cache. // pruner will eventually remove the CRD from the cache.
return WorkEstimate{InitialSeats: maximumSeats} return WorkEstimate{InitialSeats: maximumSeats}
case err == ObjectCountNotFoundErr: case err == ObjectCountNotFoundErr:
// there are two scenarios in which we can see this error: // there are multiple scenarios in which we can see this error:
// a. the type is truly unknown, a typo on the caller's part. // a. the type is truly unknown, a typo on the caller's part.
// b. the count has gone stale for too long and the pruner // b. the count has gone stale for too long and the pruner
// has removed the type from the cache. // has removed the type from the cache.
// we don't have a way to distinguish between a and b. b seems to indicate // c. the type is an aggregated resource that is served by a
// to a more severe case of degradation, although b can naturally trigger // different apiserver (thus its object count is not updated)
// when a CRD is removed. let's be conservative and allocate maximum seats. // we don't have a way to distinguish between those situations.
return WorkEstimate{InitialSeats: maximumSeats} // However, in case c, the request is delegated to a different apiserver,
// and thus its cost for our server is minimal. To avoid the situation
// when aggregated API calls are overestimated, we allocate the minimum
// possible seats (see #109106 as an example when being more conservative
// led to problems).
return WorkEstimate{InitialSeats: minimumSeats}
case err != nil: case err != nil:
// we should never be here since Get returns either ObjectCountStaleErr or // we should never be here since Get returns either ObjectCountStaleErr or
// ObjectCountNotFoundErr, return maximumSeats to be on the safe side. // ObjectCountNotFoundErr, return maximumSeats to be on the safe side.
klog.ErrorS(err, "Unexpected error from object count tracker")
return WorkEstimate{InitialSeats: maximumSeats} return WorkEstimate{InitialSeats: maximumSeats}
} }

View File

@ -125,7 +125,7 @@ func TestWorkEstimator(t *testing.T) {
Resource: "events", Resource: "events",
}, },
countErr: ObjectCountNotFoundErr, countErr: ObjectCountNotFoundErr,
initialSeatsExpected: maximumSeats, initialSeatsExpected: minimumSeats,
}, },
{ {
name: "request verb is list, continuation is set", name: "request verb is list, continuation is set",
@ -214,7 +214,7 @@ func TestWorkEstimator(t *testing.T) {
Resource: "events", Resource: "events",
}, },
countErr: ObjectCountNotFoundErr, countErr: ObjectCountNotFoundErr,
initialSeatsExpected: maximumSeats, initialSeatsExpected: minimumSeats,
}, },
{ {
name: "request verb is list, object count is stale", name: "request verb is list, object count is stale",
@ -239,7 +239,7 @@ func TestWorkEstimator(t *testing.T) {
Resource: "events", Resource: "events",
}, },
countErr: ObjectCountNotFoundErr, countErr: ObjectCountNotFoundErr,
initialSeatsExpected: maximumSeats, initialSeatsExpected: minimumSeats,
}, },
{ {
name: "request verb is list, count getter throws unknown error", name: "request verb is list, count getter throws unknown error",