KEP-5394: PSI based Node Conditions

Implementation History
ALPHA Implementable
Created 2025-06-11
Latest v1.36
Milestones
Alpha v1.36
Ownership
Owning SIG
SIG Node
Participating SIGs

KEP-5394: PSI Based Node Conditions

Release Signoff Checklist

Items marked with (R) are required prior to targeting to a milestone / release.

  • (R) Enhancement issue in release milestone, which links to KEP dir in kubernetes/enhancements (not the initial KEP PR)
  • (R) KEP approvers have approved the KEP status as implementable
  • (R) Design details are appropriately documented
  • (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input (including test refactors)
    • e2e Tests for all Beta API Operations (endpoints)
    • (R) Ensure GA e2e tests meet requirements for Conformance Tests
    • (R) Minimum Two Week Window for GA e2e tests to prove flake free
  • (R) Graduation criteria is in place
  • (R) Production readiness review completed
  • (R) Production readiness review approved
  • “Implementation History” section is up-to-date for milestone
  • User-facing documentation has been created in kubernetes/website , for publication to kubernetes.io
  • Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes

Summary

This KEP proposes enabling kubelet to report node conditions which will be utilized to prevent scheduling of pods on nodes experiencing significant resource constraints.

Motivation

PSI metric provides a quantifiable way to see resource pressure increases as they develop, with a new pressure metric for three major resources (memory, CPU, IO). These pressure metrics are useful for detecting resource shortages and provide nodes the opportunity to respond intelligently - by updating the node condition.

In short, PSI metric are like barometers that provide fair warning of impending resource shortages on the node, and enable nodes to take more proactive, granular and nuanced steps when major resources (memory, CPU, IO) start becoming scarce.

Goals

This proposal aims to:

  1. Utilize the node level PSI metric to set node condition and node taints.

Non-Goals

  • Invest in more opportunities to further use PSI metric for pod evictions, userspace OOM kills, and so on, for future KEPs.

Proposal

User Stories (Optional)

Story 1

Kubernetes users want to prevent new pods to be scheduled on the nodes that have resource starvation. By using PSI metric, the kubelet will set Node Condition to avoid pods being scheduled on nodes under high resource pressure. The node controller could then set a taint on the node based on these new Node Conditions .

Risks and Mitigations

There is a potential risk of early reporting for nodes under pressure. We intend to address this concern by conducting careful experimentation with PSI threshold values to identify the optimal default threshold to be used for reporting the nodes under heavy resource pressure.

Design Details

Note: These actions are tentative, and will depend on different the outcome from testing and discussions with sig-node members, users, and other folks.

Note: In the initial Alpha implementation, we are not introducing node pressure condition for CPU. This is because unlike memory and IO, CPU is a compressible resource. See https://github.com/kubernetes/enhancements/issues/5062 for more details.

  1. Introduce a new kubelet config parameter, pressure threshold, to let users specify the pressure percentage beyond which the kubelet would report the node condition to disallow workloads to be scheduled on it.

  2. Add new node conditions corresponding to high PSI (beyond threshold levels) on Memory and IO.

// These are valid conditions of the node. Currently, we don't have enough information to decide
// node condition.
const (

	// Conditions based on pressure at system level cgroup.
	NodeSystemMemoryContentionPressure NodeConditionType = "SystemMemoryContentionPressure"
	NodeSystemDiskContentionPressure   NodeConditionType = "SystemDiskContentionPressure"

	// Conditions based on pressure at kubepods level cgroup.
	NodeKubepodsMemoryContentionPressure NodeConditionType = "KubepodsMemoryContentionPressure"
	NodeKubepodsDiskContentionPressure   NodeConditionType = "KubepodsDiskContentionPressure"
)
  1. Kernel collects PSI data for 10s, 60s and 300s timeframes. To determine the optimal observation timeframe, it is necessary to conduct tests and benchmark performance. In theory, 10s interval might be rapid to taint a node with NoSchedule effect. Therefore, as an initial approach, opting for a 60s timeframe for observation logic appears more appropriate.

Add the observation logic to add node condition and taint as per following scenarios:

  • If avg60 >= threshold, then record an event indicating high resource pressure.
  • If avg60 >= threshold and is trending higher i.e. avg10 >= threshold, then set Node Condition for high resource contention pressure. This should ensure no new pods are scheduled on the nodes under heavy resource contention pressure.
  • If avg60 >= threshold for a node tainted with NoSchedule effect, and is trending lower i.e. avg10 <= threshold, record an event mentioning the resource contention pressure is trending lower.
  • If avg60 < threshold for a node tainted with NoSchedule effect, remove the NodeCondition.
  1. Collaborate with sig-scheduling to modify TaintNodesByCondition feature to integrate new taints for the new Node Conditions introduced in this enhancement.
  • node.kubernetes.io/memory-contention-pressure=:NoSchedule
  • node.kubernetes.io/cpu-contention-pressure=:NoSchedule
  • node.kubernetes.io/disk-contention-pressure=:NoSchedule
  1. Perform experiments to finalize the default optimal pressure threshold value.

  2. Add a new feature gate PSINodeCondition, and guard the node condition related logic behind the feature gate. Set --feature-gates=PSINodeCondition=true to enable the feature.

Test Plan

[X] I/we understand the owners of the involved components may require updates to existing tests to make this code solid enough prior to committing the changes necessary to implement this enhancement.

Prerequisite testing updates
Unit tests
  • k8s.io/kubernetes/pkg/kubelet/server/stats: 2023-10-04 - 74.4%
Integration tests

Any identified external user of either of these endpoints (prometheus, metrics-server) should be tested to make sure they’re not broken by new fields in the API response.

e2e tests

Test plan:

  • Enable the feature gate.
  • For each of memory and IO
    • Schedule workloads to a node that overwhelms the resource.
    • Ensure the node is marked with corresponding PSI pressure node condition and taint.
    • Create more workloads and observe that the workloads cannot be scheduled onto this node.
    • Delete existing workloads to free up the resource.
    • Ensure the node condition and taint are removed.
    • Create more workloads and observe the the workloads can be scheduled.
    • Clean up.

Graduation Criteria

Alpha

  • Conduct experiments to decide the scope of the node condition (system v.s. kubepods v.s. node) as well as the default threshold
  • Enables kubelet to report node conditions based off PSI values.
  • Initial e2e tests completed and enabled if CRI implementation supports it.
  • Add documentation for the feature.

Beta

  • Decide whether CPU PSI will be used for node conditions.
  • Feature gate is enabled by default.
  • Extend e2e test coverage.
  • Allowing time for feedback.

GA

  • TBD

Deprecation

N/A

Upgrade / Downgrade Strategy

No impact. Runc will be upgraded to 1.2.0 version as a prerequisite for this feature, and all the other components will already be at expected levels. Hence there shouldn’t be a problem in upgrading or downgrading. Besides, it’s always possible to upgrade/downgrade to a different kubelet version.

Version Skew Strategy

kubelet is responsible of setting node conditions to True or False. While kube-scheduler is responsible of applying / removing taints to the nodes based on the conditions.

Any / Both component being rolled back could result in stale node conditions and/or taints. Stale node condition can be misleading, while stale taint can be even worse as it may affect workload scheduling.

We need to ensure the node conditions and taints get cleaned up when

  1. The feature gate is disabled in any of the component
  2. The version is rolled back in any of the component

in which case the feature can be safely disabled / rolled back.

Production Readiness Review Questionnaire

Feature Enablement and Rollback

How can this feature be enabled / disabled in a live cluster?
  • Feature gate (also fill in values in kep.yaml)
    • Feature gate name: PSINodeCondition
    • Components depending on the feature gate: kubelet, kube-controller-manager, kube-scheduler
  • Other
    • Describe the mechanism:
    • Will enabling / disabling the feature require downtime of the control plane?
    • Will enabling / disabling the feature require downtime or reprovisioning of a node?
Does enabling the feature change any default behavior?

No behavior change when there is no node level resource pressure.

When there is node level memory / IO pressure, the node will be marked with the corresponding resource pressure condition and taint, which will prevent new workloads from being scheduled to this node.

Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?

Yes

What happens if we reenable the feature if it was previously rolled back?

When the feature is disabled, the Node Conditions will still exist on the nodes. However, they won’t be any consumers of these node conditions. When the feature is re-enabled, the kubelet will override out of date Node Conditions as expected.

Are there any tests for feature enablement/disablement?

Unit tests

Rollout, Upgrade and Rollback Planning

How can a rollout or rollback fail? Can it impact already running workloads?
What specific metrics should inform a rollback?
Were upgrade and rollback tested? Was the upgrade->downgrade->upgrade path tested?
Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?

Monitoring Requirements

How can an operator determine if the feature is in use by workloads?

One can check if the proposed node conditions are set (True or False) in all nodes in the cluster.

If the cluster admin sets up metrics that monitor node conditions in the cluster, that metrics can be used to tell if the feature is used. Note that such metrics could show no usage even when the feature is enabled and in use, since the node condition may not be set to True if there is no node-level resource pressure.

One can also check if kubelet is surfacing PSI metrics in /metrics/cadvisor. Surfacing PSI metrics is a prerequisite for the PSI-based node condition feature.

How can someone using this feature know that it is working for their instance?
  • Events
    • Event Reason: kubelet should record an event when setting the node condition to True / False and record the reasons (based on PSI data).
  • API .status
    • Condition name:
      • SystemMemoryContentionPressure
      • SystemDiskContentionPressure
      • KubepodsMemoryContentionPressure
      • KubepodsDiskContentionPressure
    • Other field:
      • Check the actual PSI data for the nodes in kubelet metrics
What are the reasonable SLOs (Service Level Objectives) for the enhancement?
What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
  • Metrics
    • Metric name:
    • [Optional] Aggregation method:
    • Components exposing the metric:
  • Other (treat as last resort)
    • Details:

TBD. Since kubelet checks the PSI data and sets node condition accordingly, we should have metrics in place to monitor that kubelet is indeed performing this tasks and refreshing node conditions. This can help us detect issues where a bug causes kubelet to get stuck and the node conditions become stale.

Are there any missing metrics that would be useful to have to improve observability of this feature?

Dependencies

Does this feature depend on any specific services running in the cluster?

N/A

Scalability

Will enabling / using this feature result in any new API calls?

No

Will enabling / using this feature result in introducing new API types?

Yes, PSIStats is the new API type that will be added to Summary API.

Will enabling / using this feature result in any new calls to the cloud provider?

No

Will enabling / using this feature result in increasing size or count of the existing API objects?

No

Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?

No

Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, …) in any components?

No. Additional metric i.e. PSI is being read from cadvisor.

Can enabling / using this feature result in resource exhaustion of some node resources (PIDs, sockets, inodes, etc.)?

No

Troubleshooting

NA

How does this feature react if the API server and/or etcd is unavailable?
  • NA.
What are other known failure modes?

NA

What steps should be taken if SLOs are not being met to determine the problem?

Implementation History

  • 2023/09/13: Initial proposal
  • 2025/06/11: Only keep Phase 2 contents in this new KEP. Phase 1 contents are kept in the original KEP.
  • 2025/06/11: Update Alpha requirements. Make CPU PSI a Beta requirement.

Drawbacks

Infrastructure Needed (Optional)

No new infrastructure is needed.