Skip to content

fix(docker,jobs): scope container cleanup to owner labels and preserve pause/cancel status - #586

Merged
ironcommit merged 1 commit into
mainfrom
deploy-race/rsadler
Jul 7, 2026
Merged

fix(docker,jobs): scope container cleanup to owner labels and preserve pause/cancel status#586
ironcommit merged 1 commit into
mainfrom
deploy-race/rsadler

Conversation

@ironcommit

@ironcommit ironcommit commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Docker: scope container cleanup and orphan reconciliation to owner labels

Add models_docker_container_labels config field to DockerBackendConfig so containers created by the models controller carry arbitrary labels. Integration test fixtures use this to stamp containers with test-run and test-worker identity labels, scoping teardown cleanup and orphan reconciliation to the owning pytest-xdist worker.

  • New _managed_container_labels() helper on the creation reconciler centralises label construction for NIM, sidecar, and puller containers
  • cleanup_model_deployment_containers() accepts optional owner labels and only removes matching containers
  • Pass ignore_removed=True on Docker container list calls to prevent races when another worker removes a container during enumeration
  • Diagnostic output now includes owner labels for easier debugging

Jobs: preserve pause/cancel status when pods report task errors

When a Kubernetes job is pausing, paused, cancelling, or cancelled, pod-level task errors (e.g. SIGTERM exit code 137) no longer override the job status to ERROR. This prevents user-initiated pause/cancel from incorrectly surfacing as a failure.

Tests: fix intake ATIF ingest timestamp

Replace the frozen _BASE_TIME (2026-01-15) with a dynamic timestamp 7 days in the past so ingested spans stay within ClickHouse's 90-day TTL and tests don't start failing as time passes.

Summary by CodeRabbit

  • New Features
    • Added configurable model_labels support for applying custom labels to model resources across Docker and Kubernetes backends.
    • Test runs now tag model resources with run-/worker-specific labels to enable scoped teardown and better traceability.
  • Bug Fixes
    • Docker cleanup now stops/removes only containers that match the expected label set; orphan detection and port selection ignore containers already marked removed.
    • Kubernetes job reconciliation now preserves PAUSED/CANCELLED when task errors occur during terminal transitions.
  • Documentation
    • Updated the configuration reference with the new Docker Models service label option.
  • Tests
    • Added unit and regression test coverage for label scoping and reconciliation edge cases.

@ironcommit
ironcommit requested review from a team as code owners July 7, 2026 01:33
@github-actions github-actions Bot added the fix label Jul 7, 2026
@ironcommit
ironcommit requested a review from benmccown July 7, 2026 01:33
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds model-label propagation and label-scoped Docker cleanup/reconciliation, updates Kubernetes object creation to carry extra model labels, preserves paused or cancelled job states when task errors appear, and switches one intake test base timestamp to a computed recent value.

Changes

Docker and Kubernetes label scoping

Layer / File(s) Summary
Config and label propagation
docs/set-up/config-reference.mdx, services/core/models/.../docker/config.py, services/core/models/.../k8s_nim_operator/config.py, services/core/models/.../docker/creation_reconciler.py, services/core/models/.../k8s_nim_operator/...
Adds model_labels config fields, updates label merging, and threads extra model labels into Docker and Kubernetes resource compilation.
Cleanup and reconciliation filters
packages/nmp_testing/src/nmp/testing/docker.py, services/core/models/.../docker/backend.py
Scopes Docker cleanup and managed-deployment lookup by owner labels and ignores removed containers.
Test fixture wiring
services/core/inference-gateway/tests/integration/conftest.py, services/core/models/tests/integration/conftest.py, services/core/models/tests/integration/test_models_controller.py
Adds worker/run-scoped owner-label fixtures and passes them into cleanup and backend config fixtures.
Docker and Kubernetes tests
packages/nmp_testing/tests/unit/test_docker.py, services/core/models/tests/unit/controllers/*, services/core/models/tests/integration/*
Adds tests for label propagation, cleanup scoping, port discovery, orphan reconciliation, and raw Kubernetes object labels.

Kubernetes terminal-state handling

Layer / File(s) Summary
Step status override
services/core/jobs/src/nmp/core/jobs/controllers/backends/kubernetes/kubernetes_job.py
Suppresses the error override for PAUSING, PAUSED, CANCELLING, and CANCELLED step states when task errors are present.
Regression tests
services/core/jobs/tests/controllers/test_kubernetes_backend.py
Adds sync tests that keep PAUSED and CANCELLED results stable when pod task errors appear during suspension or termination.

Intake test timestamp update

Layer / File(s) Summary
Base time computation
services/intake/tests/integration/spans/test_atif_ingest.py
Updates the test base timestamp to derive from the current time with a 7-day offset and refreshes the comment.

Suggested reviewers: mckornfield

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title matches the main changes: owner-label-scoped Docker cleanup and Kubernetes job status preservation for pausing/cancelling states.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch deploy-race/rsadler

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
services/core/inference-gateway/tests/integration/conftest.py (1)

231-263: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate fixture logic with services/core/models/tests/integration/conftest.py.

docker_owner_labels, models_controller_container_cleanup, and docker_backend_config's label wiring are near-identical across both integration conftest files. Since nmp_testing already hosts shared Docker test helpers, consider moving docker_owner_labels (and possibly the cleanup fixture) there to avoid drift between services.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/core/inference-gateway/tests/integration/conftest.py` around lines
231 - 263, The Docker test fixture setup is duplicated across integration
conftest files, so the label generation and cleanup logic can drift. Move the
shared `docker_owner_labels` helper into the common test utilities in
`nmp_testing`, and have `models_controller_container_cleanup` and
`docker_backend_config` reuse that shared fixture instead of defining
near-identical label wiring locally. Keep the service-specific fixtures only for
settings that truly differ, and reference the existing
`cleanup_model_deployment_containers` and `get_worker_port_range` usage when
wiring the shared helper in.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@services/core/inference-gateway/tests/integration/conftest.py`:
- Around line 231-263: The Docker test fixture setup is duplicated across
integration conftest files, so the label generation and cleanup logic can drift.
Move the shared `docker_owner_labels` helper into the common test utilities in
`nmp_testing`, and have `models_controller_container_cleanup` and
`docker_backend_config` reuse that shared fixture instead of defining
near-identical label wiring locally. Keep the service-specific fixtures only for
settings that truly differ, and reference the existing
`cleanup_model_deployment_containers` and `get_worker_port_range` usage when
wiring the shared helper in.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d4c08a7c-64b5-4267-b8e2-b7cf10cbbcd0

📥 Commits

Reviewing files that changed from the base of the PR and between feee4ba and ce72c89.

📒 Files selected for processing (10)
  • docs/set-up/config-reference.mdx
  • packages/nmp_testing/src/nmp/testing/docker.py
  • packages/nmp_testing/tests/unit/test_docker.py
  • services/core/inference-gateway/tests/integration/conftest.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/backend.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/config.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/creation_reconciler.py
  • services/core/models/tests/integration/conftest.py
  • services/core/models/tests/integration/test_models_controller.py
  • services/core/models/tests/unit/controllers/test_docker_backend.py

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 23273/30443 76.4% 61.2%
Integration Tests 13618/29123 46.8% 20.0%

@ironcommit ironcommit changed the title fix(docker): scope container cleanup and orphan reconciliation fix(docker,jobs): scope container cleanup to owner labels and preserve pause/cancel status Jul 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/vllm_k8s_compiler.py (1)

85-101: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

common_labels lets extra/model_labels clobber reserved controller-identity labels — opposite precedence vs. the other two label-merge implementations in this PR.

common_labels() builds MODEL_MANAGED_BY_LABEL, DEPLOYMENT_WORKSPACE_LABEL, DEPLOYMENT_NAME_LABEL, engine first, then does labels.update(extra) — so extra (now wired as self._backend_config.model_labels from k8s.py) wins on key conflict. compile_deployment's manual pod_labels.update(extra_labels) has the same issue.

Compare to nimservice_compiler._merge_model_labels (base wins) and Docker's _managed_container_labels (controller labels applied after model_labels) — both correctly protect controller labels. Here it's reversed.

If model_labels ever contains a colliding key (typo, copy/paste), the Deployment/PVC/Job/Service lose their correct DEPLOYMENT_WORKSPACE_LABEL/DEPLOYMENT_NAME_LABEL/MODEL_MANAGED_BY_LABEL, which k8s.py's list_managed_deployment_names() relies on for orphan reconciliation — exactly the mechanism this PR is trying to make safe.

🐛 Proposed fix — controller labels take precedence
 def common_labels(
     workspace: str,
     name: str,
     engine: str,
     *,
     extra: Optional[dict[str, str]] = None,
 ) -> dict[str, str]:
     """Labels stamped on every emitted object for management + orphan listing."""
-    labels = {
-        MODEL_MANAGED_BY_LABEL: MODEL_MANAGED_BY_MODELS_CONTROLLER,
-        DEPLOYMENT_WORKSPACE_LABEL: workspace,
-        DEPLOYMENT_NAME_LABEL: name,
-        "nmp.nvidia.com/engine": engine,
-    }
-    if extra:
-        labels.update(extra)
-    return labels
+    labels = dict(extra or {})
+    labels.update(
+        {
+            MODEL_MANAGED_BY_LABEL: MODEL_MANAGED_BY_MODELS_CONTROLLER,
+            DEPLOYMENT_WORKSPACE_LABEL: workspace,
+            DEPLOYMENT_NAME_LABEL: name,
+            "nmp.nvidia.com/engine": engine,
+        }
+    )
+    return labels

And in compile_deployment, apply the same precedence to pod_labels:

-    selector_labels = {"app": resource_name}
-    pod_labels = {
-        **selector_labels,
-        **common_labels(workspace, name, engine),
-    }
-    if extra_labels:
-        pod_labels.update(extra_labels)
+    selector_labels = {"app": resource_name}
+    pod_labels = dict(extra_labels or {})
+    pod_labels.update(selector_labels)
+    pod_labels.update(common_labels(workspace, name, engine))

Also applies to: 156-156, 169-169, 199-199, 214-214, 328-334, 397-397, 418-425

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/vllm_k8s_compiler.py`
around lines 85 - 101, `common_labels` and the `compile_deployment` label merge
currently let `extra`/`model_labels` override reserved controller labels, which
is the wrong precedence. Update `common_labels` so `MODEL_MANAGED_BY_LABEL`,
`DEPLOYMENT_WORKSPACE_LABEL`, `DEPLOYMENT_NAME_LABEL`, and the engine label
always win over `extra`, and apply the same controller-first merge order in
`compile_deployment` for `pod_labels`. Use `common_labels` and
`compile_deployment` as the touchpoints, and make the label behavior consistent
with `_merge_model_labels` and `_managed_container_labels`.
🧹 Nitpick comments (1)
services/core/models/tests/unit/controllers/backends/test_vllm_k8s_compiler.py (1)

48-101: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Good coverage for the happy path. Consider adding a case where extra_labels collides with a reserved key (e.g. nmp.nvidia.com/deployment-workspace) to catch the precedence bug flagged in vllm_k8s_compiler.py.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/core/models/tests/unit/controllers/backends/test_vllm_k8s_compiler.py`
around lines 48 - 101, Add a test in the vllm_k8s_compiler controller suite that
covers a collision between extra_labels and a reserved label key such as
nmp.nvidia.com/deployment-workspace. Update the assertions around compile_pvc,
compile_puller_job, compile_deployment, and compile_service to verify the
reserved key keeps the compiler-defined value and is not overridden by
extra_labels, while still preserving non-reserved labels.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/vllm_k8s_compiler.py`:
- Around line 85-101: `common_labels` and the `compile_deployment` label merge
currently let `extra`/`model_labels` override reserved controller labels, which
is the wrong precedence. Update `common_labels` so `MODEL_MANAGED_BY_LABEL`,
`DEPLOYMENT_WORKSPACE_LABEL`, `DEPLOYMENT_NAME_LABEL`, and the engine label
always win over `extra`, and apply the same controller-first merge order in
`compile_deployment` for `pod_labels`. Use `common_labels` and
`compile_deployment` as the touchpoints, and make the label behavior consistent
with `_merge_model_labels` and `_managed_container_labels`.

---

Nitpick comments:
In
`@services/core/models/tests/unit/controllers/backends/test_vllm_k8s_compiler.py`:
- Around line 48-101: Add a test in the vllm_k8s_compiler controller suite that
covers a collision between extra_labels and a reserved label key such as
nmp.nvidia.com/deployment-workspace. Update the assertions around compile_pvc,
compile_puller_job, compile_deployment, and compile_service to verify the
reserved key keeps the compiler-defined value and is not overridden by
extra_labels, while still preserving non-reserved labels.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 612e4f01-f98a-4fe6-a4ae-2a0cf2492108

📥 Commits

Reviewing files that changed from the base of the PR and between 14e85ca and 17d89d6.

📒 Files selected for processing (15)
  • docs/set-up/config-reference.mdx
  • services/core/inference-gateway/tests/integration/conftest.py
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/kubernetes/kubernetes_job.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/backend.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/config.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/creation_reconciler.py
  • services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/config.py
  • services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/nimservice_compiler.py
  • services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/reconcilers/k8s.py
  • services/core/models/src/nmp/core/models/controllers/backends/k8s_nim_operator/vllm_k8s_compiler.py
  • services/core/models/tests/integration/conftest.py
  • services/core/models/tests/integration/test_models_controller.py
  • services/core/models/tests/unit/controllers/backends/test_vllm_k8s_compiler.py
  • services/core/models/tests/unit/controllers/test_backend_config_fields.py
  • services/core/models/tests/unit/controllers/test_docker_backend.py
✅ Files skipped from review due to trivial changes (1)
  • docs/set-up/config-reference.mdx
🚧 Files skipped from review as they are similar to previous changes (7)
  • services/core/models/tests/integration/conftest.py
  • services/core/models/tests/integration/test_models_controller.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/backend.py
  • services/core/inference-gateway/tests/integration/conftest.py
  • services/core/jobs/src/nmp/core/jobs/controllers/backends/kubernetes/kubernetes_job.py
  • services/core/models/tests/unit/controllers/test_docker_backend.py
  • services/core/models/src/nmp/core/models/controllers/backends/docker/creation_reconciler.py

@ironcommit
ironcommit added this pull request to the merge queue Jul 7, 2026
@ironcommit
ironcommit removed this pull request from the merge queue due to a manual request Jul 7, 2026
…t-run owner labels

Add models_docker_container_labels config field to DockerBackendConfig so
containers created by the models controller can carry arbitrary labels.
Integration test fixtures use this to stamp containers with test-run and
test-worker identity labels, scoping teardown cleanup and orphan
reconciliation to the owning pytest-xdist worker.

Also pass ignore_removed=True on Docker container list calls to prevent
races when another worker removes a container during enumeration.

Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
@ironcommit
ironcommit force-pushed the deploy-race/rsadler branch from 922910b to 499117d Compare July 7, 2026 16:35
@ironcommit
ironcommit enabled auto-merge July 7, 2026 16:36
Comment thread docs/set-up/config-reference.mdx
@ironcommit
ironcommit added this pull request to the merge queue Jul 7, 2026
Merged via the queue into main with commit 8765450 Jul 7, 2026
99 of 100 checks passed
@ironcommit
ironcommit deleted the deploy-race/rsadler branch July 7, 2026 18:28
arpitsardhana pushed a commit that referenced this pull request Jul 9, 2026
…t-run owner labels (#586)

Add models_docker_container_labels config field to DockerBackendConfig so
containers created by the models controller can carry arbitrary labels.
Integration test fixtures use this to stamp containers with test-run and
test-worker identity labels, scoping teardown cleanup and orphan
reconciliation to the owning pytest-xdist worker.

Also pass ignore_removed=True on Docker container list calls to prevent
races when another worker removes a container during enumeration.

Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants