Operator Status, State, Stage, and Condition Definitions
This document provides concise definitions for the status, state, stage, and condition concepts used throughout the NodeWright operator to track package operations and node lifecycle management.
Key Relationships
-
Status reflects the overall health and progress of nodes and the NodeWright resource
-
State tracks the execution status of individual package operations
-
Stage defines the specific lifecycle phase a package is currently in
-
A node’s Status is derived from the collective States of its packages
-
Stages progress sequentially, with State indicating success/failure at each stage
-
All stages except for interrupts include validation checks that must succeed for progression
Usage in Operations
- Monitoring: Use Status for high-level health checks and dashboards
- Debugging: Examine State and Stage for detailed package-level troubleshooting
- Automation: State transitions trigger the next appropriate Stage in the lifecycle
- Scheduling: Status values like
blockedandpausedcontrol operation scheduling and dependencies
Status
Scope: Applied to the overall NodeWright resource and individual nodes
Purpose: High-level operational status indicating the current condition
Conditions
NodeWright publishes Kubernetes conditions on .status.conditions. The Ready condition is the standard user-facing summary for kubectl wait --for=condition=Ready, while other condition types report specific operator states that can coexist with Ready.
Ready Condition
Ready is a boolean projection of the NodeWright’s multivalued .status.status field:
.status.status remains the canonical rollout summary used by the operator’s scheduling and state machine. Ready exists to expose that state in Kubernetes condition form for standard tooling, while .status.nodeStatus remains the authoritative per-node source of truth.
Ready Condition Message
The Ready.message field summarizes node progress by status:
- It always starts with
<complete>/<total> nodes complete. - It appends one segment for each non-empty node-status bucket, such as
<count> in progress,<count> blocked, or<count> erroring. - When a bucket has a short node list, the node names are included in sorted order:
2 blocked (node-a, node-b). - When a bucket exceeds the message cap, the node names are dropped and the segment becomes
(list truncated; see controller logs).
Example for a small rollout:
Example for a large rollout:
The truncation cap exists to keep condition payloads bounded for etcd object size and watch bandwidth. When truncation happens, the controller logs the full per-status node lists at Info, and .status.nodeStatus still contains the complete per-node view.
Other Condition Types
The operator also sets additional condition types that may be useful for troubleshooting:
Blocked: rollout progress is blocked on one or more nodes. Reasons include:NonInterruptPodsRunning: node drain is held because pods matchingspec.podNonInterruptLabelsare still running or pending on selected nodes. A held node keeps its slot in the compartment’s current batch, and can readwaitingorin_progressdepending on what has already run on it (see interrupt-flow.md)DependencyUninstalled: a package that still has work to do depends on a package that is being or has been uninstalled. A dependent that is itself being uninstalled, byuninstall.applyor by the NodeWright’s deletion withuninstall.enabled, is not reported
TaintNotTolerable: selected nodes are skipped because their taints are not tolerated by the NodeWrightNodesIgnored: selected nodes are skipped because they have the ignore label setApplyPackage: the controller is applying a package to a nodeDeploymentPolicyNotFound: the referencedDeploymentPolicyis missing at reconcile timeImagePullFailed: one or more package pods have been unable to pull their image (ErrImagePull/ImagePullBackOff) for more than 2 minutes, measured from the pod’s creation, from the last init container that finished, or from the end of the container’s previous run when it restarts and pulls again. The message names the nodes (past 10 the list is logged by the controller instead) and the package and container of the first node’s failing pod, the lowest package name when several fail; the kubelet’s pull error is in theWarningevent emitted when the condition first appears, since it changes on every retry. The kubelet keeps retrying the pull, so this is deliberately not a package State or node Status: a package or node readsin_progressthroughout, and the condition clears by itself once no pod is waiting on a failed pull. If the pull never recovers, the stage’s deadline (stageTimeout) fails it and marks the nodeerroring. WithstageTimeout: 0, or nostageTimeoutandJOB_STAGE_TIMEOUTset to0, there is no deadline: the node staysin_progressand this condition is the only signalDrainBlocked: one or more selected nodes have a drain that cannot currently make progress. Reasons:PodDisruptionBudget,UnmanagedPod,EmptyDirData, orMultipleCauseswhen more than one kind of blocker is present. Independent ofBlocked— a NodeWright can be both dependency-blocked and drain-blocked at once.
These conditions complement, rather than replace, .status.status and Ready.
Legacy Prefixed Condition Types
Canonical condition types are now the bare names above, such as Ready and TaintNotTolerable. During the one-release deprecation window, the operator also mirrors them to the legacy prefixed condition types for backward compatibility:
Readycontinues to be emitted asnodewright.nvidia.com/Ready- the rollout-transition summary also remains available as
nodewright.nvidia.com/Transition - other bare condition types continue to be mirrored as
nodewright.nvidia.com/<Type>
New consumers should read the canonical bare condition types now. Existing consumers of the prefixed condition types should migrate during the deprecation window.
State
Scope: Applied to individual packages within a node
Purpose: Current execution state of a specific package operation
Stage
Scope: Applied to individual packages
Purpose: Indicates which phase of the package installation/management process is currently executing
NOTE: All stages except for interrupts include validation checks that must succeed for progression
Stage Flow
The typical stage progression depends on whether the package has interrupts:
Without Interrupts:
With Interrupts:
When a package requires an interrupt, the node is first cordoned and drained before package operations begin:
Note: The cordon, wait, and drain phases ensure that workloads are safely removed from the node before any package operations that require interrupts (such as reboots or kernel module changes) are executed.
NodeWright Status Fields
The NodeWright resource’s .status object includes fields that track batch rollout state. Two fields are particularly relevant for batch stickiness and node ordering:
Both fields are persisted in the CRD and survive controller restarts. They are cleared by kubectl nodewright reset; kubectl nodewright deployment-policy reset keeps them.