diff --git a/pkg/apis/flowcontrol/bootstrap/default.go b/pkg/apis/flowcontrol/bootstrap/default.go index 355fa912a..aca968de6 100644 --- a/pkg/apis/flowcontrol/bootstrap/default.go +++ b/pkg/apis/flowcontrol/bootstrap/default.go @@ -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{ diff --git a/pkg/apis/flowcontrol/bootstrap/default_test.go b/pkg/apis/flowcontrol/bootstrap/default_test.go index 3865cee05..09fffc4f8 100644 --- a/pkg/apis/flowcontrol/bootstrap/default_test.go +++ b/pkg/apis/flowcontrol/bootstrap/default_test.go @@ -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 { diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 941b352ba..e157518f5 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -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}, } diff --git a/pkg/server/filters/priority-and-fairness_test.go b/pkg/server/filters/priority-and-fairness_test.go index bf619b898..ad3ac780b 100644 --- a/pkg/server/filters/priority-and-fairness_test.go +++ b/pkg/server/filters/priority-and-fairness_test.go @@ -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, diff --git a/pkg/util/flowcontrol/apf_controller.go b/pkg/util/flowcontrol/apf_controller.go index bfdd4d615..d40cae509 100644 --- a/pkg/util/flowcontrol/apf_controller.go +++ b/pkg/util/flowcontrol/apf_controller.go @@ -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 } diff --git a/pkg/util/flowcontrol/apf_filter_test.go b/pkg/util/flowcontrol/apf_filter_test.go index 20c83bd3d..72e9c7390 100644 --- a/pkg/util/flowcontrol/apf_filter_test.go +++ b/pkg/util/flowcontrol/apf_filter_test.go @@ -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{ diff --git a/pkg/util/flowcontrol/borrowing_test.go b/pkg/util/flowcontrol/borrowing_test.go index 17e820153..3a51da004 100644 --- a/pkg/util/flowcontrol/borrowing_test.go +++ b/pkg/util/flowcontrol/borrowing_test.go @@ -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{ diff --git a/pkg/util/flowcontrol/controller_test.go b/pkg/util/flowcontrol/controller_test.go index 0c35a0087..c706a7c3c 100644 --- a/pkg/util/flowcontrol/controller_test.go +++ b/pkg/util/flowcontrol/controller_test.go @@ -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, }, diff --git a/pkg/util/flowcontrol/gen_test.go b/pkg/util/flowcontrol/gen_test.go index 8dffc0f66..21b88367f 100644 --- a/pkg/util/flowcontrol/gen_test.go +++ b/pkg/util/flowcontrol/gen_test.go @@ -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 { diff --git a/pkg/util/flowcontrol/max_seats_test.go b/pkg/util/flowcontrol/max_seats_test.go index da76c6a28..7c385625e 100644 --- a/pkg/util/flowcontrol/max_seats_test.go +++ b/pkg/util/flowcontrol/max_seats_test.go @@ -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,