Skip to content

fix(kubevirt-operator): move PrometheusRule to Helm-rendered template - #2543

Merged
Andrei Kvapil (kvaps) merged 2 commits into
mainfrom
fix/kubevirt-prometheusrule-helm
May 4, 2026
Merged

Andrei Kvapil (kvaps) merged 2 commits into
mainfrom
fix/kubevirt-prometheusrule-helm

Conversation

@IvanHunters

@IvanHunters IvanHunters commented Apr 30, 2026 •

Copy link
Copy Markdown
Collaborator

What this PR does

Move alerts/PrometheusRule.yaml from raw-file loading (via .Files.Glob in
templates/alerts.yaml) to a proper Helm-rendered template
templates/prometheusrule.yaml.

The raw-file approach silently passed unescaped {{ $labels.xxx }} to
Kubernetes unchanged, which worked by accident. As a Helm template, those
expressions must be escaped with {{ "{{" }} to prevent Helm from trying
to evaluate them as Go template variables.

Also removes templates/alerts.yaml which became dead code once the
alerts/ directory is empty.

Release note

```release-note
fix(kubevirt-operator): move PrometheusRule alerts to Helm-rendered template and escape Prometheus template variables
```

Summary by CodeRabbit

  • Refactor
    • Reorganized alert configuration structure for VM and VMI monitoring. Alerts that trigger when virtual machines or machine instances remain in a non-running state for 10 minutes are now managed through an updated template-based approach, consolidating alert definitions while maintaining the same monitoring behavior.

Move alerts/PrometheusRule.yaml from raw-file loading (via Files.Glob)
to templates/prometheusrule.yaml as a proper Helm template. Escape
Prometheus template variables with {{ "{{" }} to prevent Helm from
evaluating them during chart rendering.

Remove templates/alerts.yaml which is now dead code since the alerts/
directory is empty.

Signed-off-by: IvanHunters <[email protected]>
@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 improves the maintainability and reliability of the KubeVirt operator's monitoring configuration. By transitioning from raw file loading to native Helm templates, the deployment process is now more robust, ensuring that template variables are correctly handled and preventing potential rendering issues during installation.

Highlights

  • Template Migration: Migrated the PrometheusRule definition from a raw file to a standard Helm-rendered template.
  • Variable Escaping: Escaped Prometheus template variables to prevent conflicts with Helm's Go template engine.
  • Cleanup: Removed the legacy alerts.yaml template and the associated raw alerts directory.

🧠 New Feature in Public Preview: You can now enable Memory 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.

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 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 counter productive. 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. ↩

@dosubot dosubot Bot added the size/XS This PR changes 0-9 lines, ignoring generated files label Apr 30, 2026
@coderabbitai

coderabbitai Bot commented Apr 30, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b1b5d68f-6eae-4c87-8515-65b8b487606b

📥 Commits

Reviewing files that changed from the base of the PR and between 7106f07 and 000157f.

📒 Files selected for processing (1)
  • packages/system/kubevirt-operator/templates/prometheusrule.yaml
✅ Files skipped from review due to trivial changes (1)
  • packages/system/kubevirt-operator/templates/prometheusrule.yaml

📝 Walkthrough

Walkthrough

This PR refactors KubeVirt alert definitions by consolidating them from a separate alerts/ directory into a direct PrometheusRule template. The glob-based alert loader template is removed, and the vm-not-running-alert PrometheusRule is migrated to templates/prometheusrule.yaml with identical alert logic intact.

Changes

Alert Definition Consolidation

Layer / File(s) Summary
New PrometheusRule Template
packages/system/kubevirt-operator/templates/prometheusrule.yaml
Adds vm-not-running-alert PrometheusRule with two alert rules: VMNotRunningFor10Minutes (fires on non-running VMs for 10 min) and VMINotRunningFor10Minutes (fires on non-running VMIs for 10 min), both with critical severity and templated labels/annotations.
Remove Glob Loader
packages/system/kubevirt-operator/templates/alerts.yaml
Deletes the template that discovered and emitted alerts via {{ .Files.Glob }} pattern, no longer needed with direct template definition.
Consolidate Alert Manifest
packages/system/kubevirt-operator/alerts/PrometheusRule.yaml
Removes the original alert manifest from the separate alerts directory; functionality now provided by templates/prometheusrule.yaml.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • #2503: PR consolidates the KubeVirt PrometheusRule alerts (VMNotRunningFor10Minutes and VMINotRunningFor10Minutes) into the proper templates/prometheusrule.yaml location, resolving the alert definition structure.

Poem

🐰 The alerts hop from scattered lands,
Now bundled in templates' gentle hands,
No glob to chase, just clarity bright,
VMs watched round the clock, day and night! ✨

🚥 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 accurately describes the main change: moving PrometheusRule from raw file loading via .Files.Glob to a Helm-rendered template, which is the core refactoring in this PR.
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 fix/kubevirt-prometheusrule-helm

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

@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 labels Apr 30, 2026
@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) kind/cleanup Categorizes issue or PR as related to cleanup of code, process, or technical debt labels Apr 30, 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 migrates Prometheus alert rules from a dynamic loading system to a dedicated Helm template in packages/system/kubevirt-operator/templates/prometheusrule.yaml. The review feedback identifies that the current alert expressions using max_over_time are overly sensitive and suggests using a for: 10m duration instead to ensure the alerts only trigger for persistent issues. The reviewer also recommends formatting improvements for the alert annotations, such as using block scalars for descriptions and consistent quoting.

Comment on lines +9 to +23
- alert: VMNotRunningFor10Minutes
expr: |
max_over_time(
kubevirt_vm_info{
status!="running",
exported_namespace=~".+",
name=~".+"
}[10m]
) == 1
labels:
severity: critical
namespace: '{{ "{{" }} $labels.exported_namespace {{ "}}" }}'
annotations:
summary: 'VM {{ "{{" }} $labels.name {{ "}}" }} in namespace {{ "{{" }} $labels.exported_namespace {{ "}}" }} is not Running for more than 10 minutes'
description: 'The VM {{ "{{" }} $labels.name {{ "}}" }} in namespace {{ "{{" }} $labels.exported_namespace {{ "}}" }} has been in a non-Running state for more than 10 minutes. Please investigate the issue.'

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 current expression max_over_time(...)[10m] == 1 triggers the alert if the VM was in a non-running state at any point during the last 10 minutes. For an alert named VMNotRunningFor10Minutes, it is more appropriate to use a persistent condition with a for: 10m duration. Additionally, I've restored the single quotes in the annotations for consistency with the original version and improved the description readability using a block scalar.

    - alert: VMNotRunningFor10Minutes
      expr: kubevirt_vm_info{status!="running",exported_namespace=~".+",name=~".+"} == 1
      for: 10m
      labels:
        severity: critical
        namespace: '{{ "{{" }} $labels.exported_namespace {{ "}}" }}'
      annotations:
        summary: "VM '{{ "{{" }} $labels.name {{ "}}" }}' in namespace '{{ "{{" }} $labels.exported_namespace {{ "}}" }}' is not Running for more than 10 minutes"
        description: >-
          The VM '{{ "{{" }} $labels.name {{ "}}" }}' in namespace '{{ "{{" }} $labels.exported_namespace {{ "}}" }}'
          has been in a non-Running state for more than 10 minutes. Please investigate the issue.

Comment on lines +24 to +38
- alert: VMINotRunningFor10Minutes
expr: |
max_over_time(
kubevirt_vmi_info{
phase!="running",
exported_namespace=~".+",
name=~".+"
}[10m]
) == 1
labels:
severity: critical
namespace: '{{ "{{" }} $labels.exported_namespace {{ "}}" }}'
annotations:
summary: 'VMI {{ "{{" }} $labels.name {{ "}}" }} in namespace {{ "{{" }} $labels.exported_namespace {{ "}}" }} is not Running for more than 10 minutes'
description: 'The VMI {{ "{{" }} $labels.name {{ "}}" }} in namespace {{ "{{" }} $labels.exported_namespace {{ "}}" }} has been in a non-Running state for more than 10 minutes. Please investigate the issue.'

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

Similar to the VM alert, the expression max_over_time(...)[10m] == 1 is likely too sensitive for a '10 minutes' alert. Using for: 10m ensures the VMI has been in a non-running phase for the entire duration. I've also restored the single quotes in the annotations and used a block scalar for the description.

    - alert: VMINotRunningFor10Minutes
      expr: kubevirt_vmi_info{phase!="running",exported_namespace=~".+",name=~".+"} == 1
      for: 10m
      labels:
        severity: critical
        namespace: '{{ "{{" }} $labels.exported_namespace {{ "}}" }}'
      annotations:
        summary: "VMI '{{ "{{" }} $labels.name {{ "}}" }}' in namespace '{{ "{{" }} $labels.exported_namespace {{ "}}" }}' is not Running for more than 10 minutes"
        description: >-
          The VMI '{{ "{{" }} $labels.name {{ "}}" }}' in namespace '{{ "{{" }} $labels.exported_namespace {{ "}}" }}'
          has been in a non-Running state for more than 10 minutes. Please investigate the issue.

@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

KubeVirt monitoring alerts are reorganized by removing a standalone PrometheusRule manifest and its loader template, replacing them with a new Helm template that defines equivalent VM/VMI "not running for 10 minutes" alerting rules.

Changes

Cohort / File(s) Summary
Removed Alert Files
packages/system/kubevirt-operator/alerts/PrometheusRule.yaml, packages/system/kubevirt-operator/templates/alerts.yaml
Deletion of the vm-not-running-alert PrometheusRule manifest and the alert file loader template that previously rendered all alerts from the alerts/ directory.
New PrometheusRule Template
packages/system/kubevirt-operator/templates/prometheusrule.yaml
Introduction of a Helm template defining two alerting rules: VMNotRunningFor10Minutes and VMINotRunningFor10Minutes, with critical severity and templated annotations referencing VM/VMI namespace and name labels.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 Alerts hop to templates new,
Where Helm weaves rules fresh and true,
VMs and VMIs run or rest,
Monitored with every test,
Organization's latest quest!

🚥 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 PR title 'fix(kubevirt-operator): move PrometheusRule to Helm-rendered template' accurately summarizes the main change—moving the PrometheusRule from raw file loading to a Helm-rendered template with proper escaping.
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 fix/kubevirt-prometheusrule-helm

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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

@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 the current code and only fix it if needed.

Inline comments:
In `@packages/system/kubevirt-operator/templates/prometheusrule.yaml`:
- Around line 9-38: The rules VMNotRunningFor10Minutes and
VMINotRunningFor10Minutes currently use max_over_time(...[10m]) == 1 which only
detects a single non-running sample; replace each max_over_time expression
targeting kubevirt_vm_info and kubevirt_vmi_info with an equivalent instant
vector selector (e.g.
kubevirt_vm_info{status!="running",exported_namespace=~".+",name=~".+"} and
kubevirt_vmi_info{phase!="running",exported_namespace=~".+",name=~".+"}) and add
a top-level for: 10m to each alert block so the alert only fires if the
non-running condition is sustained for 10 minutes.
🪄 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: 074c50d1-bc9a-4c2d-b5f1-ca2a38c96a55

📥 Commits

Reviewing files that changed from the base of the PR and between f45facc and 7106f07.

📒 Files selected for processing (3)
  • packages/system/kubevirt-operator/alerts/PrometheusRule.yaml
  • packages/system/kubevirt-operator/templates/alerts.yaml
  • packages/system/kubevirt-operator/templates/prometheusrule.yaml
💤 Files with no reviewable changes (2)
  • packages/system/kubevirt-operator/templates/alerts.yaml
  • packages/system/kubevirt-operator/alerts/PrometheusRule.yaml

Comment thread packages/system/kubevirt-operator/templates/prometheusrule.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.

NOT LGTM — the structural refactor (raw-glob loader → Helm-rendered template with {{ "{{" }} escape) is correct, but both Gemini and CodeRabbit flagged a real PromQL-semantic bug in the alert expressions that this PR moves verbatim. Per the rule that pre-existing issues in the neighborhood of the diff are owned by the PR (the touched lines themselves contain the bug), this should be addressed before merge — either fixed inline or explicitly punted to a tracked follow-up issue.

Business context: Move kubevirt-operator's VM/VMI alert rules from raw-file glob loading (templates/alerts.yaml + alerts/PrometheusRule.yaml) to a standard Helm-rendered template, escaping Prometheus's {{ $labels.X }} syntax so Helm doesn't try to evaluate it.

Blocker

B1: alert expression doesn't match its name — fires on any non-running event in the last 10 min, not "non-running for 10 min"

File: packages/system/kubevirt-operator/templates/prometheusrule.yaml:13-21 (VMNotRunningFor10Minutes) and 28-36 (VMINotRunningFor10Minutes)
Issue: The expression max_over_time(kubevirt_vm_info{status!="running"}[10m]) == 1 returns 1 whenever the metric was 1 at any point in the last 10 minutes. So a VM that was briefly non-running 9 minutes ago but is currently running still triggers the alert. The alert name promises "non-running for 10 minutes", which means continuous non-running for the full window.
Evidence: Prometheus max_over_time semantics return the maximum value over the lookback window, not the minimum or the duration of true. To express "the condition has held for the entire window", either use min_over_time(metric{...}[10m]) == 1 (the metric was always 1 in the window) or change the expression to kubevirt_vm_info{status!="running"} == 1 and add a for: 10m PromQL clause to the alert. Both bots flagged this; CodeRabbit cited the upstream Prometheus docs explicitly. The expression is preserved verbatim from the deleted alerts/PrometheusRule.yaml — this PR didn't introduce the bug, but it's now in the diff and the touched lines own it.
Impact: False positives on transient VM/VMI restarts (e.g. brief reschedules, node maintenance). Operators get paged for events that resolved themselves minutes ago.
Fix: One of:
(a) Change to kubevirt_vm_info{status!="running"} == 1 with for: 10m (idiomatic Prometheus alert-fires-after-stable-condition pattern).
(b) Change to min_over_time(kubevirt_vm_info{status!="running"}[10m]) == 1 (alert if metric was non-running for the entire 10m window).
(c) Punt explicitly: open a tracking issue for the alert tuning, reference it in the PR body, and add a comment in the YAML noting the known issue is tracked separately. This keeps the refactor scope minimal but doesn't leave the bot findings unanswered.

…ax_over_time

Replace max_over_time([10m]) == 1 with an instant vector selector
and a top-level for: 10m clause. The previous expression fired as
long as the metric was non-running at any point in the last 10 minutes;
the new expression fires only when the condition is sustained continuously
for the full 10-minute window, matching the alert name semantics.

Signed-off-by: IvanHunters <[email protected]>
@dosubot dosubot Bot added size:XS and removed size/XS This PR changes 0-9 lines, ignoring generated files labels May 2, 2026
@github-actions github-actions Bot added size/M This PR changes 30-99 lines, ignoring generated files size/XS This PR changes 0-9 lines, ignoring generated files and removed size:XS labels May 2, 2026

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.

LGTM. The PromQL semantic blocker from the prior review is addressed in 000157f9:

  • VMNotRunningFor10Minutes / VMINotRunningFor10Minutes now use instant vector selectors (kubevirt_vm_info{status!="running", …} == 1, kubevirt_vmi_info{phase!="running", …} == 1) with for: 10m at the alert level.
  • This is the idiomatic Prometheus pattern for "condition has held continuously for the duration" — the alert fires only after the metric has stayed at 1 for the full 10-minute window, which matches the alert name and resolves the false-positive class on transient VM/VMI restarts.

Verification:

  • Both alerts now match shape: instant vector + for: 10m. The exact form recommended as option (a) in the prior review.
  • Diff is minimal: 12 insertions, 14 deletions in prometheusrule.yaml — no other rule logic touched.
  • Helm-template escaping ({{ "{{" }} $labels.X {{ "}}" }}) survives the rewrite intact, so the original PR's structural goal (raw-glob loader → Helm-rendered template) still holds.
  • CI green: pre-commit, Build, E2E Tests, CodeRabbit.

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label May 4, 2026
@kvaps
Andrei Kvapil (kvaps) merged commit 0a3a503 into main May 4, 2026
14 checks passed
@kvaps
Andrei Kvapil (kvaps) deleted the fix/kubevirt-prometheusrule-helm branch May 4, 2026 18:38
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/uncategorized PR auto-labeler could not map title scope to a known area/*; please review area/virtualization Issues or PRs related to virtualization (kubevirt, cdi, vmi, vm-import) kind/bug Categorizes issue or PR as related to a bug kind/cleanup Categorizes issue or PR as related to cleanup of code, process, or technical debt lgtm This PR has been approved by a maintainer size/M This PR changes 30-99 lines, ignoring generated files size/XS This PR changes 0-9 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants