@@ -782,6 +782,118 @@ APF adds the following two headers to each HTTP response message.
782
782
- ` X-Kubernetes-PF-PriorityLevel-UID ` holds the UID of the
783
783
PriorityLevelConfiguration object associated with that FlowSchema.
784
784
785
+ ## Good practices for using API Priority and Fairness
786
+
787
+ When a given priority level exceeds its permitted concurrency, requests can
788
+ experience increased latency or be dropped with an HTTP 429 (Too Many Requests)
789
+ error. To prevent these side effects of APF, you can modify your workload or
790
+ tweak your APF settings to ensure there are sufficient seats available to serve
791
+ your requests.
792
+
793
+ To detect whether requests are being rejected due to APF, check the following
794
+ metrics:
795
+ - apiserver_flowcontrol_rejected_requests_total: the total number of requests
796
+ rejected per FlowSchema and PriorityLevelConfiguration.
797
+ - apiserver_flowcontrol_current_inqueue_requests: the current number of requests
798
+ queued per FlowSchema and PriorityLevelConfiguration.
799
+ - apiserver_flowcontrol_request_wait_duration_seconds: the latency added to
800
+ requests waiting in queues.
801
+ - apiserver_flowcontrol_priority_level_seat_utilization: the seat utilization
802
+ per PriorityLevelConfiguration.
803
+
804
+ ### Workload modifications {#good-practice-workload-modifications}
805
+
806
+ To prevent requests from queuing and adding latency or being dropped due to APF,
807
+ you can optimize your requests by:
808
+
809
+ - Reducing the rate at which requests are executed. A fewer number of requests
810
+ over a fixed period will result in a fewer number of seats being needed at a
811
+ given time.
812
+ - Avoid issuing a large number of expensive requests concurrently. Requests can
813
+ be optimized to use fewer seats or have lower latency so that these requests
814
+ hold those seats for a shorter duration. List requests can occupy more than 1
815
+ seat depending on the number of objects fetched during the request. Restricting
816
+ the number of objects retrieved in a list request, for example by using
817
+ pagination, will use less total seats over a shorter period. Furthermore,
818
+ replacing list requests with watch requests will require lower total concurrency
819
+ shares as watch requests only occupy 1 seat during its initial burst of
820
+ notifications. If using streaming lists in versions 1.27 and later, watch
821
+ requests will occupy the same number of seats as a list request for its initial
822
+ burst of notifications because the entire state of the collection has to be
823
+ streamed. Note that in both cases, a watch request will not hold any seats after
824
+ this initial phase.
825
+
826
+ Keep in mind that queuing or rejected requests from APF could be induced by
827
+ either an increase in the number of requests or an increase in latency for
828
+ existing requests. For example, if requests that normally take 1s to execute
829
+ start taking 60s, it is possible that APF will start rejecting requests because
830
+ requests are occupying seats for a longer duration than normal due to this
831
+ increase in latency. If APF starts rejecting requests across multiple priority
832
+ levels without a significant change in workload, it is possible there is an
833
+ underlying issue with control plane performance rather than the workload or APF
834
+ settings.
835
+
836
+ ### Priority and fairness settings {#good-practice-apf-settings}
837
+
838
+ You can also modify the default FlowSchema and PriorityLevelConfiguration
839
+ objects or create new objects of these types to better accommodate your
840
+ workload.
841
+
842
+ APF settings can be modified to:
843
+ - Give more seats to high priority requests.
844
+ - Isolate non-essential or expensive requests that would starve a concurrency
845
+ level if it was shared with other flows.
846
+
847
+ #### Give more seats to high priority requests
848
+
849
+ 1 . If possible, the number of seats available across all priority levels for a
850
+ particular ` kube-apiserver ` can be increased by increasing the values for the
851
+ ` max-requests-inflight ` and ` max-mutating-requests-inflight ` flags. Alternatively,
852
+ horizontally scaling the number of ` kube-apiserver ` instances will increase the
853
+ total concurrency per priority level across the cluster assuming there is
854
+ sufficient load balancing of requests.
855
+ 2 . You can create a new FlowSchema which references a PriorityLevelConfiguration
856
+ with a larger concurrency level. This new PriorityLevelConfiguration could be an
857
+ existing level or a new level with its own set of nominal concurrency shares.
858
+ For example, a new FlowSchema could be introduced to change the
859
+ PriorityLevelConfiguration for your requests from global-default to workload-low
860
+ to increase the number of seats available to your user. Creating a new
861
+ PriorityLevelConfiguration will reduce the number of seats designated for
862
+ existing levels. Recall that editing a default FlowSchema or
863
+ PriorityLevelConfiguration will require setting the
864
+ ` apf.kubernetes.io/autoupdate-spec ` annotation to false.
865
+ 3 . You can also increase the NominalConcurrencyShares for the
866
+ PriorityLevelConfiguration which is serving your high priority requests.
867
+ Alternatively, for versions 1.26 and later, you can increase the LendablePercent
868
+ for competing priority levels so that the given priority level has a higher pool
869
+ of seats it can borrow.
870
+
871
+ #### Isolate non-essential requests from starving other flows
872
+
873
+ For request isolation, you can create a FlowSchema whose subject matches the
874
+ user making these requests or create a FlowSchema that matches what the request
875
+ is (corresponding to the resourceRules). Next, you can map this FlowSchema to a
876
+ PriorityLevelConfiguration with a low share of seats.
877
+
878
+ For example, suppose list event requests from Pods running in the default namespace
879
+ are using 10 seats each and execute for 1 minute. To prevent these expensive
880
+ requests from impacting requests from other Pods using the existing service-accounts
881
+ FlowSchema, you can apply the following FlowSchema to isolate these list calls
882
+ from other requests.
883
+
884
+ Example FlowSchema object to isolate list event requests:
885
+
886
+ {{% code file="priority-and-fairness/list-events-default-service-account.yaml" %}}
887
+
888
+ - This FlowSchema captures all list event calls made by the default service
889
+ account in the default namespace. The matching precedence 8000 is lower than the
890
+ value of 9000 used by the existing service-accounts FlowSchema so these list
891
+ event calls will match list-events-default-service-account rather than
892
+ service-accounts.
893
+ - The catch-all PriorityLevelConfiguration is used to isolate these requests.
894
+ The catch-all priority level has a very small concurrency share and does not
895
+ queue requests.
896
+
785
897
## {{% heading "whatsnext" %}}
786
898
787
899
0 commit comments