Skip to content

fix: startupProbes for kubevirt-cdi-operator and grafana-operator - #2725

Merged
myasnikovdaniil merged 2 commits into
mainfrom
ci/operator-startup-probes
May 26, 2026
Merged

myasnikovdaniil merged 2 commits into
mainfrom
ci/operator-startup-probes

Conversation

@myasnikovdaniil

@myasnikovdaniil myasnikovdaniil commented May 25, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Adds startupProbe to two operator deployments whose readiness probes fail repeatedly during a cold cluster install, generating noise and (for CDI) blocking dependants on slow leader-election:

  • kubevirt-cdi-operator — leader-election against a slow kube-apiserver (Kamaji control plane bringup) consistently takes >30s on a cold install. The default readinessProbe with 1s periodSeconds / 3 failureThreshold fires the first time election times out, the operator pod gets marked NotReady, and dependants block on it.
  • grafana-operator — bootstrap CRD discovery + Helm-managed Dashboard reconcile loop spikes startup duration past readinessProbe's default budget under load.

startupProbe gives each operator a longer one-time window to reach steady state; the regular readinessProbe then takes over with its tight per-second cadence to detect genuine ongoing failures.

Origin

Both commits lifted unchanged from #2619.

Release note

NONE

Summary by CodeRabbit

  • Configuration Updates
    • Added startup health checks to Grafana operator container
    • Added startup health checks to KubeVirt CDI operator container

Review Change Stack

myasnikovdaniil and others added 2 commits May 25, 2026 11:54
…lection

cdi-operator's controller-runtime starts the health probe HTTP server
(:8444) only after the leader election lease is acquired. On a fresh
cluster the lease can take 15–20 s, exceeding the liveness probe's
5s + 3×10s grace under load. Kubelet kills the container before the
probe can succeed; the pod loops in CrashLoopBackOff, CDI never
reconciles its CR, datavolumes.cdi.kubevirt.io stays unavailable, and
every downstream test that creates a DataVolume (tenant kubernetes
worker VMs, vm-instance) fails.

Add a startupProbe that hits /healthz with 30×5s grace (150 s total).
Once it succeeds once, liveness/readiness take over with their existing
strict config. No effect on healthy clusters; only relaxes the
ramp-up window.

Implemented as a patches/*.diff applied from the Makefile update
target, mirroring the fluxcd-operator pattern. Survives the next
upstream regen; if upstream restructures the area around the
readinessProbe/resources boundary the patch will fail loudly so the
maintainer notices.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
Signed-off-by: Myasnikov Daniil <[email protected]>
(cherry picked from commit 8f5d45e)
… load

Install Cozystack failed because grafana-operator pod looped in
CrashLoopBackOff under concurrent helm-install load (Flux v2.8
helm-controller dispatching every system HR in parallel + kstatus
walking all applied resources). The chain that fell over:

  grafana-operator pod  liveness probe :8081/healthz fails 3x in 30s
    -> monitoring-rd     dependency 'cozy-grafana-operator/grafana-operator'
    -> tenant-rd         dependency 'cozy-system/monitoring-rd'
    -> cozystack-basics  dependency 'cozy-system/tenant-rd'
                         (cozystack-basics creates the cozy-public ns)
    -> kubevirt-cdi      RoleBinding cdi-clone-dv: namespace
                         "cozy-public" not found
    -> vm-disk-rd, dashboard, flux-plunger   all wait, install times out

Pod log shows the manager starts at T+0, controllers spin up workers,
folder/dashboard/datasource sync completes by T+10s — then SIGTERM at
T+27s. Liveness probe is the upstream chart default (delay=0s,
timeout=1s, period=10s, failureThreshold=3) which gives ~30s grace,
not enough on a fresh cluster where controller-runtime's HTTP probe
server is still binding while kubelet starts polling immediately.

Same shape as the kubevirt-cdi-operator commit already in this branch
(37b06e2). Mirror the fix:

- Edit deployment.yaml on the vendored chart to add a startupProbe
  (30 x 5s = 150s grace, /healthz on :8081). Once it passes once,
  liveness/readiness keep the existing strict config.
- Stash the change as patches/startupProbe.diff and re-apply it from
  the Makefile update target after the curl|tar upstream fetch, so
  the next chart bump does not silently regress.

The patch uses package-relative paths (a/charts/...) so `patch -p1`
from the package dir resolves correctly — repo-relative paths would
need patch's fuzzy fallback which is unreliable across distros.

Signed-off-by: Myasnikov Daniil <[email protected]>
(cherry picked from commit 40949c8)
@github-actions github-actions Bot added area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/bug Categorizes issue or PR as related to a bug size/M This PR changes 30-99 lines, ignoring generated files labels May 25, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses issues where operator pods were failing readiness checks during cold cluster installs due to slow initialization or high load. By introducing startup probes, the operators are granted a sufficient grace period to reach a steady state before the more aggressive readiness probes begin monitoring them, thereby preventing unnecessary service disruptions and blocking dependencies.

Highlights

  • Improved Startup Stability: Added startupProbe configurations to both kubevirt-cdi-operator and grafana-operator to prevent premature readiness probe failures during cold cluster initialization.
  • Build Process Updates: Updated the Makefiles for both operators to automatically apply the necessary startup probe patches during the build and update cycles.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: **/*.diff (2)
    • packages/system/grafana-operator/patches/startupProbe.diff
    • packages/system/kubevirt-cdi-operator/patches/startupProbe.diff
  • Ignored by pattern: **/charts/** (1)
    • packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@coderabbitai

coderabbitai Bot commented May 25, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR adds Kubernetes startup probes to two operators: grafana-operator and kubevirt-cdi-operator. Each operator receives an HTTP-based startup probe configured to hit its existing /healthz endpoint with consistent timing parameters (5-second period, 10-second timeout, 30 failure threshold). Patch files define the probe configurations, and Makefile updates apply them during the chart update process.

Changes

Operator Startup Probes

Layer / File(s) Summary
Grafana operator startup probe
packages/system/grafana-operator/patches/startupProbe.diff, packages/system/grafana-operator/Makefile, packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml
Introduces a startup probe to the grafana-operator container that performs HTTP GET to /healthz on port 8081. Makefile is updated to apply the patch during the chart update phase.
CDI operator startup probe
packages/system/kubevirt-cdi-operator/patches/startupProbe.diff, packages/system/kubevirt-cdi-operator/Makefile, packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
Introduces a startup probe to the cdi-operator container that performs HTTP GET to /healthz on port 8444. Makefile is updated to apply the patch during the template generation phase.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐇 Two operators now wake with a gentle health check,
Probing the /healthz before giving them a heck,
Thirty failures 'til shutdown, ten seconds to reply,
Startup probes in place—no more wondering why!
✨

🚥 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 The title clearly and specifically describes the main change: adding startupProbes to two named operator deployments (kubevirt-cdi-operator and grafana-operator).
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/operator-startup-probes

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 and usage tips.

@dosubot dosubot Bot added area/monitoring Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) area/virtualization Issues or PRs related to virtualization (kubevirt, cdi, vmi, vm-import) labels May 25, 2026

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request adds startupProbe configurations to the grafana-operator and kubevirt-cdi-operator packages by modifying their Makefiles to apply patches. The review identifies that the patch command for kubevirt-cdi-operator uses an incorrect path depth which will lead to failure. Additionally, the reviewer suggests switching the probe endpoint from /healthz to /readyz to properly handle leader election during the startup phase.

wget https://github.com/kubevirt/containerized-data-importer/releases/download/$$VERSION/cdi-operator.yaml -O templates/cdi-operator.yaml
sed -i 's/namespace: cdi/namespace: cozy-kubevirt-cdi/g' templates/cdi-operator.yaml
awk -i inplace -v RS="---" '!/kind: Namespace/{printf "%s", $$0 RS}' templates/cdi-operator.yaml
patch --no-backup-if-mismatch -p1 < patches/startupProbe.diff

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.

high

The patch command uses -p1, but the patch file patches/startupProbe.diff contains paths relative to the repository root (e.g., a/packages/system/kubevirt-cdi-operator/...). When running make update from the package directory, this will cause the patch to fail as it will look for a packages/ subdirectory. Please recreate the patch file relative to the package root (similar to the one in grafana-operator) or adjust the -p level to -p4.

References
  1. Structural changes to vendored or downloaded manifests should be applied via patch files in the package root, and the Makefile must correctly apply them.

timeoutSeconds: 10
startupProbe:
httpGet:
path: /healthz

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.

medium

The startupProbe is configured to check /healthz, but the PR description indicates that the primary issue is with the readinessProbe failing during leader election. In controller-runtime based operators, /healthz often becomes healthy as soon as the process starts, while /readyz waits for leader election. To effectively suppress readiness probe noise and prevent dependants from blocking prematurely, the startupProbe should target the /readyz endpoint.

            path: /readyz

mkdir -p charts
curl -sSL https://github.com/grafana-operator/grafana-operator/archive/refs/heads/master.tar.gz | \
tar xzvf - --strip 3 -C charts grafana-operator-master/deploy/helm/grafana-operator
patch --no-backup-if-mismatch -p1 < patches/startupProbe.diff

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.

medium

The patch patches/startupProbe.diff being applied here uses the /healthz endpoint for the startupProbe, while the readinessProbe in the upstream chart uses /readyz. If the goal is to prevent readiness probe failures during a long bootstrap or reconcile loop, the startupProbe should likely target the /readyz endpoint to ensure the tight readiness checks only begin once the operator is truly ready.

@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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@packages/system/kubevirt-cdi-operator/patches/startupProbe.diff`:
- Around line 1-4: The patch header in startupProbe.diff uses repo-root-relative
paths (packages/system/kubevirt-cdi-operator/...) which don't match the
Makefile's patch -p1 context; update the diff headers so paths are package-local
(e.g., change
a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml and b/... to
a/templates/cdi-operator.yaml and b/templates/cdi-operator.yaml) so the patch
applies correctly when run from the package directory; verify the hunk paths in
startupProbe.diff and any other patch files in this package follow the same
package-local convention.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c0d2e3e-4854-4e28-a37a-c84d29009568

📥 Commits

Reviewing files that changed from the base of the PR and between 1810263 and 9118cb3.

📒 Files selected for processing (6)
  • packages/system/grafana-operator/Makefile
  • packages/system/grafana-operator/charts/grafana-operator/templates/deployment.yaml
  • packages/system/grafana-operator/patches/startupProbe.diff
  • packages/system/kubevirt-cdi-operator/Makefile
  • packages/system/kubevirt-cdi-operator/patches/startupProbe.diff
  • packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml

Comment on lines +1 to +4
diff --git a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
index f46ba09e6..03ac3b3a2 100644
--- a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
+++ b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Patch header path is incompatible with the current patch -p1 invocation.

Line 1 uses repo-root-relative paths (packages/system/kubevirt-cdi-operator/...), but this package Makefile applies the patch from packages/system/kubevirt-cdi-operator with -p1. That combination can fail to locate the target file and break update.

💡 Suggested fix (normalize patch paths to package-local)
-diff --git a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
+diff --git a/templates/cdi-operator.yaml b/templates/cdi-operator.yaml
 index f46ba09e6..03ac3b3a2 100644
---- a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
-+++ b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
+--- a/templates/cdi-operator.yaml
++++ b/templates/cdi-operator.yaml
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
diff --git a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
index f46ba09e6..03ac3b3a2 100644
--- a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
+++ b/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml
diff --git a/templates/cdi-operator.yaml b/templates/cdi-operator.yaml
index f46ba09e6..03ac3b3a2 100644
++ b/templates/cdi-operator.yaml
🤖 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 `@packages/system/kubevirt-cdi-operator/patches/startupProbe.diff` around lines
1 - 4, The patch header in startupProbe.diff uses repo-root-relative paths
(packages/system/kubevirt-cdi-operator/...) which don't match the Makefile's
patch -p1 context; update the diff headers so paths are package-local (e.g.,
change a/packages/system/kubevirt-cdi-operator/templates/cdi-operator.yaml and
b/... to a/templates/cdi-operator.yaml and b/templates/cdi-operator.yaml) so the
patch applies correctly when run from the package directory; verify the hunk
paths in startupProbe.diff and any other patch files in this package follow the
same package-local convention.

@lexfrei Aleksei Sviridkin (lexfrei) removed the area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review label May 25, 2026

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@myasnikovdaniil
myasnikovdaniil merged commit 2fa15ce into main May 26, 2026
20 of 22 checks passed
@myasnikovdaniil
myasnikovdaniil deleted the ci/operator-startup-probes branch May 26, 2026 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/monitoring Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) area/virtualization Issues or PRs related to virtualization (kubevirt, cdi, vmi, vm-import) kind/bug Categorizes issue or PR as related to a bug size/M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants