Skip to content

Commit 64b2336

Browse files
authored
Merge pull request #42114 from natherz97/patch-1
Add section for APF best practices
2 parents 4c0a7ad + fbd11ee commit 64b2336

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

content/en/docs/concepts/cluster-administration/flow-control.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,118 @@ APF adds the following two headers to each HTTP response message.
782782
- `X-Kubernetes-PF-PriorityLevel-UID` holds the UID of the
783783
PriorityLevelConfiguration object associated with that FlowSchema.
784784

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+
785897
## {{% heading "whatsnext" %}}
786898

787899

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: flowcontrol.apiserver.k8s.io/v1beta3
2+
kind: FlowSchema
3+
metadata:
4+
name: list-events-default-service-account
5+
spec:
6+
distinguisherMethod:
7+
type: ByUser
8+
matchingPrecedence: 8000
9+
priorityLevelConfiguration:
10+
name: catch-all
11+
rules:
12+
- resourceRules:
13+
- apiGroups:
14+
- '*'
15+
namespaces:
16+
- default
17+
resources:
18+
- events
19+
verbs:
20+
- list
21+
subjects:
22+
- kind: ServiceAccount
23+
serviceAccount:
24+
name: default
25+
namespace: default

0 commit comments

Comments
 (0)