Skip to content

Right-size native sidecar containers (+ bump kubernetes client to 29)#535

Open
JReko wants to merge 1 commit into
robusta-dev:mainfrom
JReko:feat/native-sidecar-rightsizing
Open

Right-size native sidecar containers (+ bump kubernetes client to 29)#535
JReko wants to merge 1 commit into
robusta-dev:mainfrom
JReko:feat/native-sidecar-rightsizing

Conversation

@JReko

@JReko JReko commented Jul 3, 2026

Copy link
Copy Markdown

What

Right-size native sidecar containers — init containers with restartPolicy: Always (GA in Kubernetes 1.29) — alongside regular containers.

Why

KRR discovers containers only from spec.template.spec.containers, so native sidecars are never discovered, never queried for metrics, and never appear in reports. But they run for the whole pod lifetime and reserve real CPU/memory requests, so they should be right-sized like any other container. In one namespace we manage, native sidecars accounted for ~160 cores / ~250 GiB of reserved capacity that was completely invisible to KRR — and hid real under-provisioning.

One-shot init containers are intentionally excluded: they run only briefly at startup, so their usage is not representative of steady state and a "recommendation" for them would be misleading.

How

  • New module-level helper _native_sidecars(pod_spec) in robusta_krr/core/integrations/kubernetes/__init__.py that returns init containers with restartPolicy: Always.
  • It's invoked in every workload discovery path, so sidecars flow through the normal metric + strategy pipeline and show up as ordinary container rows: Deployment, StatefulSet, DaemonSet, Job, CronJob, GroupedJob, Rollout, DeploymentConfig, StrimziPodSet. (Jobs/GroupedJobs don't route through _list_scannable_objects, so they're handled at their own loops.)
  • Handles both typed clients (snake_case init_containers / restart_policy) and custom-resource workloads returned as camelCase dicts (initContainers / restartPolicy).
  • Reads the field via getattr(..., None), so on an older client that lacks it the helper simply finds no sidecars and the feature degrades to a no-op rather than raising.

Kubernetes client bump

Distinguishing a native sidecar from a one-shot init container requires the container-level restartPolicy field, which the kubernetes Python client only exposes on the container model from 28.1.0. KRR currently pins ^26.1.0, so this PR bumps it:

  • pyproject.toml: ^26.1.0^29.0.0
  • requirements.txt: 26.1.029.0.0
  • poetry.lock: regenerated (poetry lock --no-update)

KRR's kubernetes API surface (AppsV1Api/BatchV1Api/CoreV1Api/CustomObjectsApi/Autoscaling*Api list calls, config.list_kube_config_contexts) is unchanged across 26.x → 29.x, so there's no breaking risk. 28.1.0 is the acceptable strict minimum if you'd prefer a smaller bump — happy to change it.

Tests

New tests/test_native_sidecars.py (9 cases): native sidecar discovered; one-shot init container excluded; mixed; no init containers; None spec; old client without the field → no-op; CRD camelCase; plus integration tests through the real Deployment extractor and the Job loop. Full existing suite still passes (pytest → 64 passed).

Relation to #491

#491 also addresses init containers but right-sizes all of them across the workload types. This PR is deliberately narrower and safer: it right-sizes only native sidecars (restartPolicy: Always) and leaves one-shot init containers untouched, which avoids emitting misleading recommendations for containers that only run at startup. That correctness distinction is what motivates the client bump. Happy to reconcile the two approaches if maintainers prefer.


  • I have signed the CLA (will complete when the CLA-assistant bot prompts).

Native sidecars (init containers with restartPolicy: Always, GA in
Kubernetes 1.29) run for the whole pod lifetime and reserve real
resource requests, but KRR only discovered spec.template.spec.containers,
so they were never right-sized. Add a _native_sidecars() helper and
include them in every workload discovery path: Deployment, StatefulSet,
DaemonSet, Job, CronJob, GroupedJob, Rollout, DeploymentConfig and
StrimziPodSet.

One-shot init containers are intentionally excluded: they run only
briefly at startup, so their usage is not representative of steady state.
Telling the two apart requires the container-level restartPolicy field,
which the kubernetes client exposes only from 28.1.0, so bump the pin
26.1.0 -> 29.0.0 (pyproject.toml, requirements.txt, poetry.lock). The
helper reads the field via getattr, so on an older client it simply finds
no sidecars and the feature degrades to a no-op.

Handles both typed clients (snake_case init_containers/restart_policy)
and custom-resource workloads returned as camelCase dicts. Adds
tests/test_native_sidecars.py.
@CLAassistant

CLAassistant commented Jul 3, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR adds detection and inclusion of Kubernetes native sidecar init containers (restartPolicy: Always) across all workload extraction paths (Deployments, Rollouts, StrimziPodSet, StatefulSets, DaemonSets, DeploymentConfig, Jobs, CronJobs, GroupedJob), bumps the kubernetes client dependency to ^29.0.0, updates README documentation, and adds corresponding tests.

Changes

Native sidecar detection

Layer / File(s) Summary
Native sidecar detection helper
robusta_krr/core/integrations/kubernetes/__init__.py
Adds private _native_sidecars(pod_spec) helper that returns init containers with restartPolicy Always, handling both typed objects and camelCase wrapper shapes.
Wire native sidecars into workload extractors
robusta_krr/core/integrations/kubernetes/__init__.py
Updates container extraction for Deployments, Rollouts, StrimziPodSet, StatefulSets, DaemonSets, DeploymentConfig, Jobs, CronJobs, and GroupedJob to append _native_sidecars(...) results.
Native sidecar tests
tests/test_native_sidecars.py
Adds unit tests for _native_sidecars and async integration tests for Deployment and Job discovery paths.
Dependency bump and documentation
pyproject.toml, requirements.txt, README.md
Bumps kubernetes dependency to ^29.0.0/29.0.0 and documents native sidecar handling and client version requirement.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClusterLoader
  participant extract_containers
  participant _native_sidecars
  ClusterLoader->>extract_containers: request containers for workload
  extract_containers->>_native_sidecars: pod_spec
  _native_sidecars-->>extract_containers: init containers with restartPolicy Always
  extract_containers-->>ClusterLoader: regular containers + native sidecars
Loading

Suggested reviewers: arikalon1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title accurately summarizes the main change: native sidecar right-sizing and the Kubernetes client bump.
Description check ✅ Passed The description is clearly related to the implemented native sidecar support, dependency bump, and tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
robusta_krr/core/integrations/kubernetes/__init__.py (1)

448-456: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Repeated list(x.containers) + _native_sidecars(x) pattern across 9 call sites.

Consider extracting a small helper (e.g. _scannable_containers(spec)) that returns list(spec.containers) + _native_sidecars(spec), to reduce duplication and make future changes (e.g., dedup logic, additional container classes) a single-point edit.

♻️ Example helper
def _scannable_containers(pod_spec: Any) -> list[Any]:
    """Regular containers plus native sidecars, for a pod spec."""
    return list(pod_spec.containers) + _native_sidecars(pod_spec)

Then callers become e.g.:

-            extract_containers=lambda item: list(item.spec.template.spec.containers)
-            + _native_sidecars(item.spec.template.spec),
+            extract_containers=lambda item: _scannable_containers(item.spec.template.spec),

Also applies to: 473-473, 521-522, 546-565, 604-607, 627-628, 715-724

🤖 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 `@robusta_krr/core/integrations/kubernetes/__init__.py` around lines 448 - 456,
The repeated list(spec.containers) + _native_sidecars(spec) pattern in the
Kubernetes integration should be centralized to avoid duplication. Add a small
helper such as _scannable_containers(pod_spec) near the existing
container-extraction logic in __init__.py, have it return the combined
containers list, and update the call sites in _list_rollouts and the other
affected extract_containers lambdas to use that helper instead of inlining the
merge.
🤖 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 `@robusta_krr/core/integrations/kubernetes/__init__.py`:
- Around line 448-456: The repeated list(spec.containers) +
_native_sidecars(spec) pattern in the Kubernetes integration should be
centralized to avoid duplication. Add a small helper such as
_scannable_containers(pod_spec) near the existing container-extraction logic in
__init__.py, have it return the combined containers list, and update the call
sites in _list_rollouts and the other affected extract_containers lambdas to use
that helper instead of inlining the merge.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 50d15904-0639-4255-a0ac-79963f68f547

📥 Commits

Reviewing files that changed from the base of the PR and between 8ca245f and a940e34.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • README.md
  • pyproject.toml
  • requirements.txt
  • robusta_krr/core/integrations/kubernetes/__init__.py
  • tests/test_native_sidecars.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants