Status¶
The status subresource provides isolated read/write access to a resource's .status field. Controllers and operators use it to update observed state without inadvertently modifying user-managed spec fields.
Availability¶
Only resources with the HasStatusSubresource marker interface expose api.status. Most workload resources implement it: Deployment, StatefulSet, DaemonSet, ReplicaSet, Job, CronJob, Pod, Node, Namespace, and many more.
from kubex.k8s.v1_35.apps.v1.deployment import Deployment
deploy_api.status.get(...) # OK: Deployment has HasStatusSubresource
from kubex.k8s.v1_35.core.v1.config_map import ConfigMap
cm_api.status.get(...) # type error + runtime NotImplementedError
Reading status¶
api.status.get() returns the full resource object. The returned object contains the current .status field populated by the control plane. The .spec is also present, but write operations via this subresource only persist changes to .status.
from kubex.api import Api
from kubex.client import create_client
from kubex.k8s.v1_35.apps.v1.deployment import Deployment
async def main() -> None:
client = await create_client()
async with client:
api: Api[Deployment] = Api(Deployment, client=client, namespace="default")
current = await api.status.get("my-deployment")
print(
f"Status: replicas={current.status and current.status.replicas}, "
f"available={current.status and current.status.available_replicas}"
)
Replacing status¶
api.status.replace() writes a new status. Only .status is persisted — changes to .spec in the submitted object are silently ignored by the Kubernetes API.
This pattern is typical for controllers: read the current object, compute the new status, write it back:
from typing import cast
from kubex.api import Api
from kubex.client import create_client
from kubex.k8s.v1_35.apps.v1.deployment import Deployment
from kubex.k8s.v1_35.apps.v1.deployment_spec import DeploymentSpec
from kubex.k8s.v1_35.apps.v1.deployment_status import DeploymentStatus
from kubex.k8s.v1_35.core.v1.container import Container
from kubex.k8s.v1_35.core.v1.pod_spec import PodSpec
from kubex.k8s.v1_35.core.v1.pod_template_spec import PodTemplateSpec
from kubex.k8s.v1_35.meta.v1.label_selector import LabelSelector
from kubex_core.models.metadata import ObjectMetadata
async def main() -> None:
client = await create_client()
async with client:
api: Api[Deployment] = Api(Deployment, client=client, namespace="default")
deployment = await api.create(
Deployment(
metadata=ObjectMetadata(
name="example-status",
labels={"app": "example-status"},
),
spec=DeploymentSpec(
replicas=1,
selector=LabelSelector(match_labels={"app": "example-status"}),
template=PodTemplateSpec(
metadata=ObjectMetadata(labels={"app": "example-status"}),
spec=PodSpec(
containers=[Container(name="nginx", image="nginx:latest")],
),
),
),
),
)
name = cast(str, deployment.metadata.name)
try:
current = await api.status.get(name)
print(
f"Status: replicas={current.status and current.status.replicas}, "
f"available={current.status and current.status.available_replicas}"
)
current.status = DeploymentStatus(replicas=1, available_replicas=1)
updated = await api.status.replace(name, current)
print(
f"After replace: "
f"replicas={updated.status and updated.status.replicas}, "
f"available={updated.status and updated.status.available_replicas}"
)
finally:
await api.delete(name)
Replace options¶
| Option | Type | Description |
|---|---|---|
dry_run |
DryRun | bool | None |
Validate without persisting |
field_manager |
str | None |
Field manager name |
namespace |
str | None | ... |
Override the Api instance namespace |
request_timeout |
Timeout | float | None | ... |
Override the client-level timeout |
Patching status¶
api.status.patch() applies a partial status update. Only the fields present in the patch body are merged into .status. MergePatch is usually the right choice for status updates:
from kubex.core.patch import MergePatch
updated = await api.status.patch(
"my-deployment",
MergePatch({"status": {"availableReplicas": 3}}),
)
JsonPatch is also accepted for operation-level control (e.g., conditional updates with test):
from kubex.core.patch import JsonPatch
updated = await api.status.patch(
"my-deployment",
JsonPatch().replace("/status/availableReplicas", 3),
)
For server-side apply on status, use ApplyPatch with force=True and a field_manager:
from kubex.core.patch import ApplyPatch
updated = await api.status.patch(
"my-deployment",
ApplyPatch({"status": {"conditions": [...]}}),
force=True,
field_manager="my-controller",
)
patch() accepts the same options as replace() plus force and field_validation.
Status vs spec updates¶
Kubernetes splits resource management into two separate write paths:
- Write to the resource itself (via
api.replace()orapi.patch()) to update spec — user intent. - Write via
api.status.replace()orapi.status.patch()to update status — observed state.
RBAC rules can be configured to allow a controller to write status without being able to modify spec, and vice versa. Keeping the two paths separate also prevents accidental spec overwrites when a controller only intends to report progress.