February 3, 2026·4 min read·engineeringkubernetesschedulingcontrollersreadiness

Node Readiness Controller makes infrastructure prerequisites explicit

Custom node conditions can now drive declarative scheduling taints through a dedicated controller. The useful design decision is the separation between health reporting and readiness policy.

The Node Readiness Controller introduction addresses a gap between a node reporting Ready and a platform being prepared to place application pods there. A network agent, storage driver, or hardware dependency may need additional initialization. The new controller lets operators express those prerequisites as rules over node conditions and apply taints while the requirements remain unmet.

I am interested in this because Kubernetes controllers make operational policy inspectable through API objects. After eight years with Kubernetes, I am particularly attached to level-triggered reconciliation. This project applies that model to a problem that otherwise invites installation-order assumptions. I would prefer a declared readiness requirement that can be inspected after an interruption to an undocumented expectation about which daemon starts first.

The project is at an early stage. Its initial release supports the NodeReadinessRule API under readiness.node.x-k8s.io/v1alpha1. That version matters when evaluating adoption. An announcement under the Kubernetes project does not imply that this is a stable built-in API or that every cluster already provides it.

Health reporting and policy have different owners

The controller does not perform the dependency checks. It reads conditions on Node objects. The concepts documentation at v0.1.1 describes a rule in terms of selected nodes, required condition statuses, and a taint applied when the conditions do not match. This gives the health reporter and policy controller separate responsibilities.

Node Problem Detector can supply conditions through custom monitoring scripts. The project also supplies a Readiness Condition Reporter that checks local HTTP endpoints and patches node status. The introduction presents both options. I would choose the reporting mechanism according to the component's actual health contract and the tools already responsible for node status.

A successful HTTP response needs a documented meaning. For example, I would ask whether a dependency's endpoint confirms completion of initialization or merely confirms that its process is serving requests. The readiness controller cannot infer that distinction from a condition named NetworkReady. The person defining the check must decide what condition status permits application scheduling.

This is where I would start a review. The rule should identify the producer of each condition and explain what a passing result establishes. Without that information, the declarative object makes a hidden assumption easier to distribute. A condition name alone cannot explain the operational dependency that justified adding another scheduling restriction.

Enforcement duration changes the policy

The project provides continuous and bootstrap-only enforcement. Continuous enforcement maintains the rule throughout the node's lifecycle. When a required condition fails, the controller applies the taint again to prevent new scheduling. A later passing result allows the controller to remove it. This is appropriate to evaluate for dependencies whose continued health matters to new workloads.

Bootstrap-only enforcement stops evaluating a rule for a node after successful completion. The versioned concepts document describes an annotation recording that completion. Subsequent failure of the condition does not reactivate that rule for the node. The introduction gives image preparation and hardware provisioning as examples of one-time initialization work.

I would require a reason for the chosen mode in configuration review. A bootstrap-only rule cannot establish an ongoing dependency guarantee after completion. Conversely, applying continuous enforcement to an initialization check needs a clear interpretation of a later failure. The choice expresses how long the platform wants a health signal to control scheduling.

The example below follows the introduction's network rule and adds its documented dry-run setting. It requires the project's installed controller and custom resource definition. The example domain and condition type are illustrative and must match a real reporter before enforcement becomes useful.

apiVersion: readiness.node.x-k8s.io/v1alpha1
kind: NodeReadinessRule
metadata:
  name: network-readiness-rule
spec:
  conditions:
    - type: cniplugin.example.net/NetworkReady
      requiredStatus: "True"
  taint:
    key: readiness.k8s.io/acme.com/network-unavailable
    effect: NoSchedule
    value: pending
  enforcementMode: bootstrap-only
  dryRun: true
  nodeSelector:
    matchLabels:
      node-role.kubernetes.io/worker: ""

This policy selects workers with the specified label and evaluates the named condition. In enforcement mode, the configured NoSchedule taint controls new placement while the requirement remains unmet. I would describe the effect precisely in an operating procedure. The announcement promises scheduling protection, and that should not become an unsupported claim that the rule repairs dependencies or recovers applications already running there.

Dry run supplies a rollout check

The versioned documentation says dry run applies or removes no taints. Instead, the rule reports intended actions in status.dryRunResults. That is a useful starting point for introducing policy across heterogeneous nodes. The introduction explicitly supports selecting node groups with distinct requirements, including specialized hardware nodes.

I would inspect the selected population before enabling enforcement. A correct condition check attached to the wrong node group can still produce an incorrect scheduling policy. Dry-run results should therefore be compared with an independently understood inventory of the nodes that require the dependency. A missing node and an unexpectedly included node both need explanation.

I would then verify the signal transitions in a bounded test environment. The checks should include an unmet prerequisite and its subsequent completion. A continuous rule also needs a test of failure after initial success. For a bootstrap-only rule, the corresponding test should confirm that completion has the intended lasting meaning. Those tests establish the policy being adopted without assuming that similarly named modes are interchangeable.

There is already evidence that cleanup deserves attention. The v0.1.1 release notes, published before this introduction, describe a fix for a rule-deletion race that could leave taints on nodes. They also record a correction to persisting evaluation results in rule status. I would include deletion and status inspection in an adoption exercise, because operators need to understand how a readiness policy is removed as well as how it is enabled.

For my use, a readiness rule would need an owner who can explain the condition producer and respond when the rule prevents placement. I would keep that explanation with the declared configuration and review it when the dependency changes. The controller provides a common implementation for condition-driven taint management. The platform still has to define which prerequisite the condition proves and how long that proof should affect scheduling.