apiserver: allow zero value for the 'nominalConcurrencyShares' field

Kubernetes-commit: 9fd2ab419ad771790d3cb80ea7b8e6828d9ce305
This commit is contained in:
Abu Kashem 2023-10-27 19:26:08 -04:00 committed by Kubernetes Publisher
parent 2a3f44cd21
commit b041969f97
10 changed files with 46 additions and 30 deletions

View File

@ -23,7 +23,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
)
// The objects that define an apiserver's initial behavior. The
@ -90,8 +90,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(0),
LendablePercent: pointer.Int32(0),
NominalConcurrencyShares: ptr.To(int32(0)),
LendablePercent: ptr.To(int32(0)),
},
},
)
@ -100,8 +100,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 5,
LendablePercent: pointer.Int32(0),
NominalConcurrencyShares: ptr.To(int32(5)),
LendablePercent: ptr.To(int32(0)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeReject,
},
@ -173,8 +173,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 30,
LendablePercent: pointer.Int32(33),
NominalConcurrencyShares: ptr.To(int32(30)),
LendablePercent: ptr.To(int32(33)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@ -190,8 +190,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 40,
LendablePercent: pointer.Int32(25),
NominalConcurrencyShares: ptr.To(int32(40)),
LendablePercent: ptr.To(int32(25)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@ -208,8 +208,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 10,
LendablePercent: pointer.Int32(0),
NominalConcurrencyShares: ptr.To(int32(10)),
LendablePercent: ptr.To(int32(0)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@ -226,8 +226,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 40,
LendablePercent: pointer.Int32(50),
NominalConcurrencyShares: ptr.To(int32(40)),
LendablePercent: ptr.To(int32(50)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@ -244,8 +244,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 100,
LendablePercent: pointer.Int32(90),
NominalConcurrencyShares: ptr.To(int32(100)),
LendablePercent: ptr.To(int32(90)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@ -262,8 +262,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 20,
LendablePercent: pointer.Int32(50),
NominalConcurrencyShares: ptr.To(int32(20)),
LendablePercent: ptr.To(int32(50)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{

View File

@ -89,7 +89,7 @@ func TestBootstrapPriorityLevelConfigurationWithBorrowing(t *testing.T) {
t.Errorf("bootstrap PriorityLevelConfiguration %q is not %q", test.name, flowcontrol.PriorityLevelEnablementLimited)
continue
}
if test.nominalSharesExpected != bootstrapPL.Spec.Limited.NominalConcurrencyShares {
if test.nominalSharesExpected != *bootstrapPL.Spec.Limited.NominalConcurrencyShares {
t.Errorf("bootstrap PriorityLevelConfiguration %q: expected NominalConcurrencyShares: %d, but got: %d", test.name, test.nominalSharesExpected, bootstrapPL.Spec.Limited.NominalConcurrencyShares)
}
if test.lendablePercentexpected != *bootstrapPL.Spec.Limited.LendablePercent {

View File

@ -251,6 +251,14 @@ const (
//
// Allow the API server to serve consistent lists from cache
ConsistentListFromCache featuregate.Feature = "ConsistentListFromCache"
// owner: @tkashem
// beta: v1.29
//
// Allow Priority & Fairness in the API server to use a zero value for
// the 'nominalConcurrencyShares' field of the 'limited' section of a
// priority level.
ZeroLimitedNominalConcurrencyShares featuregate.Feature = "ZeroLimitedNominalConcurrencyShares"
)
func init() {
@ -315,4 +323,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
WatchList: {Default: false, PreRelease: featuregate.Alpha},
ConsistentListFromCache: {Default: false, PreRelease: featuregate.Alpha},
ZeroLimitedNominalConcurrencyShares: {Default: false, PreRelease: featuregate.Beta},
}

View File

@ -52,6 +52,7 @@ import (
"k8s.io/component-base/metrics/testutil"
"k8s.io/klog/v2"
clocktesting "k8s.io/utils/clock/testing"
"k8s.io/utils/ptr"
"github.com/google/go-cmp/cmp"
)
@ -1307,7 +1308,7 @@ func newConfiguration(fsName, plName, user string, concurrency int32, queueLengt
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: concurrency,
NominalConcurrencyShares: ptr.To(concurrency),
LimitResponse: flowcontrol.LimitResponse{
Type: responseType,
Queuing: qcfg,

View File

@ -702,7 +702,7 @@ func (meal *cfgMeal) digestNewPLsLocked(newPLs []*flowcontrol.PriorityLevelConfi
state.quiescing = false
}
nominalConcurrencyShares, _, _ := plSpecCommons(state.pl)
meal.shareSum += float64(nominalConcurrencyShares)
meal.shareSum += float64(*nominalConcurrencyShares)
meal.haveExemptPL = meal.haveExemptPL || pl.Name == flowcontrol.PriorityLevelConfigurationNameExempt
meal.haveCatchAllPL = meal.haveCatchAllPL || pl.Name == flowcontrol.PriorityLevelConfigurationNameCatchAll
}
@ -807,7 +807,7 @@ func (meal *cfgMeal) processOldPLsLocked() {
// allocation determined by all the share values in the
// regular way.
nominalConcurrencyShares, _, _ := plSpecCommons(plState.pl)
meal.shareSum += float64(nominalConcurrencyShares)
meal.shareSum += float64(*nominalConcurrencyShares)
meal.haveExemptPL = meal.haveExemptPL || plName == flowcontrol.PriorityLevelConfigurationNameExempt
meal.haveCatchAllPL = meal.haveCatchAllPL || plName == flowcontrol.PriorityLevelConfigurationNameCatchAll
meal.newPLStates[plName] = plState
@ -823,7 +823,7 @@ func (meal *cfgMeal) finishQueueSetReconfigsLocked() {
// The use of math.Ceil here means that the results might sum
// to a little more than serverConcurrencyLimit but the
// difference will be negligible.
concurrencyLimit := int(math.Ceil(float64(meal.cfgCtlr.serverConcurrencyLimit) * float64(nominalConcurrencyShares) / meal.shareSum))
concurrencyLimit := int(math.Ceil(float64(meal.cfgCtlr.serverConcurrencyLimit) * float64(*nominalConcurrencyShares) / meal.shareSum))
var lendableCL, borrowingCL int
if lendablePercent != nil {
lendableCL = int(math.Round(float64(concurrencyLimit) * float64(*lendablePercent) / 100))
@ -974,7 +974,7 @@ func (meal *cfgMeal) imaginePL(proto *flowcontrol.PriorityLevelConfiguration) {
seatDemandRatioedGauge: seatDemandRatioedGauge,
}
nominalConcurrencyShares, _, _ := plSpecCommons(proto)
meal.shareSum += float64(nominalConcurrencyShares)
meal.shareSum += float64(*nominalConcurrencyShares)
}
// startRequest classifies and, if appropriate, enqueues the request.
@ -1112,7 +1112,7 @@ func relDiff(x, y float64) float64 {
}
// plSpecCommons returns the (NominalConcurrencyShares, LendablePercent, BorrowingLimitPercent) of the given priority level config
func plSpecCommons(pl *flowcontrol.PriorityLevelConfiguration) (int32, *int32, *int32) {
func plSpecCommons(pl *flowcontrol.PriorityLevelConfiguration) (*int32, *int32, *int32) {
if limiter := pl.Spec.Limited; limiter != nil {
return limiter.NominalConcurrencyShares, limiter.LendablePercent, limiter.BorrowingLimitPercent
}
@ -1121,5 +1121,5 @@ func plSpecCommons(pl *flowcontrol.PriorityLevelConfiguration) (int32, *int32, *
if limiter.NominalConcurrencyShares != nil {
nominalConcurrencyShares = *limiter.NominalConcurrencyShares
}
return nominalConcurrencyShares, limiter.LendablePercent, nil
return &nominalConcurrencyShares, limiter.LendablePercent, nil
}

View File

@ -33,6 +33,7 @@ import (
fcrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
"k8s.io/client-go/informers"
clientsetfake "k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)
// TestQueueWaitTimeLatencyTracker tests the queue wait times recorded by the P&F latency tracker
@ -80,7 +81,7 @@ func TestQueueWaitTimeLatencyTracker(t *testing.T) {
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 100,
NominalConcurrencyShares: ptr.To(int32(100)),
LendablePercent: &lendable,
BorrowingLimitPercent: &borrowingLimit,
LimitResponse: flowcontrol.LimitResponse{

View File

@ -36,6 +36,7 @@ import (
fcrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
"k8s.io/client-go/informers"
clientsetfake "k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)
type borrowingTestConstraints struct {
@ -115,7 +116,7 @@ func TestBorrowing(t *testing.T) {
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 100,
NominalConcurrencyShares: ptr.To(int32(100)),
LendablePercent: &testCase.constraints[flow].lendable,
BorrowingLimitPercent: &testCase.constraints[flow].borrowing,
LimitResponse: flowcontrol.LimitResponse{

View File

@ -41,6 +41,7 @@ import (
fcclient "k8s.io/client-go/kubernetes/typed/flowcontrol/v1"
"k8s.io/klog/v2"
"k8s.io/utils/clock"
"k8s.io/utils/ptr"
)
// Some tests print a lot of debug logs which slows down tests considerably,
@ -357,7 +358,7 @@ func TestAPFControllerWithGracefulShutdown(t *testing.T) {
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 10,
NominalConcurrencyShares: ptr.To(int32(10)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeReject,
},

View File

@ -23,6 +23,7 @@ import (
"testing"
"k8s.io/utils/clock"
"k8s.io/utils/ptr"
flowcontrol "k8s.io/api/flowcontrol/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -47,7 +48,7 @@ func genPL(rng *rand.Rand, name string) *flowcontrol.PriorityLevelConfiguration
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: rng.Int31n(100) + 1,
NominalConcurrencyShares: ptr.To(int32(rng.Int31n(100) + 1)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeReject}}}}
if rng.Float32() < 0.95 {

View File

@ -27,6 +27,7 @@ import (
"k8s.io/apiserver/pkg/util/flowcontrol/metrics"
"k8s.io/client-go/informers"
clientsetfake "k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)
// Test_GetMaxSeats tests max seats retrieved from MaxSeatsTracker
@ -120,7 +121,7 @@ func Test_GetMaxSeats(t *testing.T) {
Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
Type: flowcontrolv1.PriorityLevelEnablementLimited,
Limited: &flowcontrolv1.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 10000,
NominalConcurrencyShares: ptr.To(int32(10000)),
LimitResponse: flowcontrolv1.LimitResponse{
Queuing: &flowcontrolv1.QueuingConfiguration{
HandSize: testcase.handSize,