Skip to content

Add dedicated alert for HostedClusters stuck deleting - #7767

Open
Chai-bot (redhat-chai-bot) wants to merge 4 commits into
Azure:mainfrom
redhat-chai-bot:alert-hostedcluster-deletion-stuck
Open

Chai-bot (redhat-chai-bot) wants to merge 4 commits into
Azure:mainfrom
redhat-chai-bot:alert-hostedcluster-deletion-stuck

Conversation

@redhat-chai-bot

@redhat-chai-bot Chai-bot (redhat-chai-bot) commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Add userJourneyClusterDeletionStuck, a severity 4 alert for HostedClusters whose deletion timestamp is more than 48 hours old, with a 15-minute pending period. Detection is independent of delete-operation records.
  • Expose hostedClusterAPI_deletion_timestamp_seconds as a Gauge from metadata.deletionTimestamp with nilIsZero: true, replacing the copied deleting Info declaration.
  • Deduplicate scrape replicas while preserving per-HostedCluster identity. Filter timestamps greater than zero without converting their values to booleans.
  • Align the alert name, summary, and subscription-scoped correlation ID with the RP alert conventions. Retain resource details for diagnosis.
  • Regenerate Bicep, Helm fixtures, and the alert-diagnostics corpus; update tests and documentation. Existing KAS rules are unchanged. No duration-converter changes remain relative to the base.

Alert semantics

time() - max by (name, namespace, _id, subscription_id, resource_id, cluster, region) (
  hostedClusterAPI_deletion_timestamp_seconds > 0
) > 172800

The rule uses for: 15m, not for: 48h. An already-old deletion must satisfy only the short pending period. Missing telemetry can interrupt pending state and must not be interpreted as successful deletion.

Validation

  • Ten committed RP-HCP alert scenarios passed.
  • Uncached alert-diagnostics corpus tests passed with update mode unset.
  • Configuration materialization consistency, Helm fixtures, seven scheduling cases, infrastructure tests, generator tests/scoped lint, formatting, and monitoring Bicep build/lint passed.
  • Compiled output contains the intended expression, PT15M, severity 4, and correlation ID. Full correction and cumulative diffs reviewed; KAS content unchanged.
  • An additional executable probe loaded the rendered ConfigMap through upstream kube-state-metrics v2.20.0 configuration/factory code. Seven cases passed, including RFC3339 conversion, fractional-second truncation, absent/null timestamps producing zero, and an invalid empty timestamp producing no sample. This diagnostic probe is outside repository CI; the configured version annotation does not establish deployed image identity or digest provenance.

Remaining rollout and review dependencies


AI-generated. Review for accuracy.

Haoran Wang (@wanghaoran1988) requested from Slack

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification

This PR uses the pipeline controller for second-stage tests. Selection and triggering follow the repository configuration.

Use /test ? to list jobs and /pipeline help for commands.

Copilot AI balanced review requested due to automatic review settings October 27, 2026 02:34
@openshift-ci openshift-ci Bot added area/docs Automatically applied by owners-label for area/docs area/infrastructure Deployment/pipeline infrastructure config area/observability Automatically applied by owners-label for area/observability area/tooling Automatically applied by owners-label for area/tooling labels Oct 27, 2026

Copilot AI 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.

🔵 Needs a closer look

Human validation is still needed for Azure acceptance of the 48-hour timeout and the metric identity labels collected in the deployed environment.

No open issues 🎉

What changed in this PR

Adds a dedicated severity 4 alert for HostedClusters continuously observed deleting for 48 hours, without changing existing KAS rules.

Changes:

  • Adds the deletion metric shared with #7237, deduplicates scrape series while preserving cluster identity, and registers the alert.
  • Corrects Azure duration conversion to emit PT48H and adds duration and alert regression tests.
  • Regenerates deployment artifacts and Helm fixtures, and documents observation semantics and triage.
File Description
tooling/​prometheus-rules/​internal/​generator.go Converts durations into Azure-compatible hours, minutes, and seconds.
tooling/​prometheus-rules/​internal/​generator_test.go Covers long, compound, and fractional durations.
observability/​prometheus/​values-mgmt.yaml Declares the HostedCluster deletion Info metric.
observability/​prometheus/​testdata/​zz_fixture_TestHelmTemplate_helmtest_mgmt_resources.yaml Updates the rendered metric fixture.
observability/​prometheus/​testdata/​zz_fixture_TestHelmTemplate_helmtest_mgmt_resources_unset.yaml Updates the unset-values metric fixture.
observability/​alerts/​hosted-cluster-deletion-stuck-prometheusRule.yaml Defines the per-cluster, 48-hour deletion alert.
observability/​alerts/​hosted-cluster-deletion-stuck-prometheusRule_test.yaml Tests timing, identity, replica churn, and telemetry gaps.
observability/​alerts-rp-hcps.yaml Registers the alert for RP HCP generation.
docs/​prometheus-rules.md Links to the deletion alert documentation.
docs/​hosted-cluster-deletion-stuck.md Explains semantics, triage, and rollout checks.
dev-infrastructure/​zz_fixture_TestHelmTemplate_dev_westus3_mgmt_1_arohcp_monitor.yaml Updates the development monitoring fixture.
dev-infrastructure/​modules/​metrics/​rules/​generatedRPHCPPrometheusAlertingRules.bicep Adds the generated Azure alert with PT48H.

Review effort: Balanced

@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

The test-unit failure is attributable to this PR: TestRepositoryCorpus detects the new HostedClusterDeletionStuck definitions, but the repository-wide alert corpus fixture was not regenerated. The generator package tests passed. I’m regenerating the missing fixture and will validate its consumer tests before pushing the correction; a retest alone would not address this mismatch.


AI-generated. Review for accuracy.

Copilot AI balanced review requested due to automatic review settings October 27, 2026 03:00
@openshift-ci openshift-ci Bot added the area/test Automatically applied by owners-label for area/test label Oct 27, 2026
@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

Pushed the fixture correction in 003fbd9857bd03e441a2d6acb943c5e2fd77daea. Regenerated test/util/alertdiagnostics/testdata/zz_fixture_TestRepositoryCorpus.yaml through its supported test path; the diff contains only 37 added lines for the new alert’s YAML and Bicep entries.

Validation: uncached TestRepositoryCorpus and its affected package passed with UPDATE unset; applicable YAML lint and whitespace checks passed. Alert behavior and KAS rules are unchanged. The full repository unit suite was not rerun locally; repository-wide CI results for this revision are still outstanding.


AI-generated. Review for accuracy.

Copilot AI 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.

🔵 Needs a closer look

Azure acceptance of the 48-hour timeout and verification of deployed metric identity labels remain outstanding checks requiring human validation.

No open issues 🎉

Review effort: Balanced

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

labels:
component: cluster-deletion
rules:
- alert: HostedClusterDeletionStuck

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.

RP-lane alerts need the userJourney prefix, so this should be named something like userJourneyClusterDeletionStuck to sit alongside userJourneyClusterDeletionStuckOperation.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 5baf037: renamed the alert to userJourneyClusterDeletionStuck and regenerated the rule output, tests, and alert-diagnostics fixture.


AI-generated. Review for accuracy.

max by (name, namespace, _id, subscription_id, resource_id, cluster, region) (
hostedClusterAPI_deleting{deletion_timestamp!=""}
) == 1
for: 48h

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.

for: 48h counts how long Prometheus has continuously seen the series rather than how long the cluster has been deleting, so any scrape gap or rule redeploy restarts the clock and clusters already stuck at rollout wait another two days; adding a Gauge on [metadata, deletionTimestamp] with nilIsZero: true to the HostedCluster config (KSM v2.20 parses RFC3339 to unix seconds) and alerting on time() - (hostedClusterAPI_deletion_timestamp_seconds > 0) > 172800 with a short for such as 15m measures real deletion age and removes the need for PT48H.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 5baf037: replaced the copied Info declaration with hostedClusterAPI_deletion_timestamp_seconds, a Gauge from metadata.deletionTimestamp with nilIsZero: true. The rule now checks actual age >172800 seconds, with for: 15m, preserving timestamp values through the positive filter and deduplicating replicas by HostedCluster identity. The PR-only duration-converter changes have been removed; those files now match the base.

Ten committed alert scenarios passed. A separate executable probe loading the rendered ConfigMap through upstream KSM v2.20.0 configuration/factory code passed seven cases, including RFC3339 conversion and absent/null timestamps. That probe is outside repository CI and does not verify the deployed image or live metric identity; live verification remains outstanding.


AI-generated. Review for accuracy.

labels:
severity: "4"
annotations:
summary: "HostedCluster {{ $labels.cluster }}/{{ $labels.namespace }}/{{ $labels.name }} continuously observed deleting for 48h ({{ $labels._id }}, {{ $labels.subscription_id }}, {{ $labels.resource_id }})"

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.

The summary should drop {{ $labels.cluster }}, since IcM already adds the cluster to the title.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 5baf037: removed the management-cluster label from the summary. Resource identity remains available for diagnosis.


AI-generated. Review for accuracy.

annotations:
summary: "HostedCluster {{ $labels.cluster }}/{{ $labels.namespace }}/{{ $labels.name }} continuously observed deleting for 48h ({{ $labels._id }}, {{ $labels.subscription_id }}, {{ $labels.resource_id }})"
description: "Resource {{ $labels.resource_id }} (cluster ID {{ $labels._id }}, subscription {{ $labels.subscription_id }}) has been continuously observed with a non-empty deletion timestamp for 48h. This measures observation time, not timestamp age. Check deletion progress and telemetry before concluding deletion succeeded."
runbook_url: https://aka.ms/cluster-deletion-tsg

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.

This alert needs its own entry in the cluster-deletion-tsg Alert Triage table with diagnosis steps and the escalation path, since docs/hosted-cluster-deletion-stuck.md in the repo isn't what on-call opens from the IcM.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Still outstanding: the external cluster-deletion TSG Alert Triage table has not been updated. The repository documentation now describes the actual-age Gauge behavior, but that is not a substitute for the requested on-call guide entry. Kept this explicitly listed as a remaining dependency in the PR description.


AI-generated. Review for accuracy.

summary: "HostedCluster {{ $labels.cluster }}/{{ $labels.namespace }}/{{ $labels.name }} continuously observed deleting for 48h ({{ $labels._id }}, {{ $labels.subscription_id }}, {{ $labels.resource_id }})"
description: "Resource {{ $labels.resource_id }} (cluster ID {{ $labels._id }}, subscription {{ $labels.subscription_id }}) has been continuously observed with a non-empty deletion timestamp for 48h. This measures observation time, not timestamp age. Check deletion progress and telemetry before concluding deletion succeeded."
runbook_url: https://aka.ms/cluster-deletion-tsg
correlationId: "HostedClusterDeletionStuck/{{ $labels.cluster }}/{{ $labels.namespace }}/{{ $labels.name }}/{{ $labels._id }}/{{ $labels.subscription_id }}/{{ $labels.resource_id }}"

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.

The correlationId should drop resource_id and match the sibling stuck-operation alert with {alertName}/{{ $labels.cluster }}/{{ $labels.subscription_id }}, which keeps hcp-suppress scoped to one customer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 5baf037: correlation is now userJourneyClusterDeletionStuck/{{ $labels.cluster }}/{{ $labels.subscription_id }}. Removed resource_id from the correlation key while retaining it in per-HostedCluster grouping and diagnostic details. Generated output and expected annotations were updated and validated.


AI-generated. Review for accuracy.

- alert: HostedClusterDeletionStuck
expr: |
max by (name, namespace, _id, subscription_id, resource_id, cluster, region) (
hostedClusterAPI_deleting{deletion_timestamp!=""}

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.

There's no alert-tester report on this yet, and since the series doesn't exist in any environment, this needs an alert-tester run (docs/alert-verification.md) against int or stage once the KSM change rolls out, showing the new series with the expected identity labels and how many HostedClusters per region would fire, so we know the alert isn't silent and what Sev4 volume to expect in prod.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Still outstanding: no int/stage deployment or live alert-tester run has been performed. Local rules, generated templates, and the KSM conversion probe passed, but they do not prove live series availability, identity labels, or matching counts per region. The PR description explicitly requires that report after an authorized metric rollout, distinguishing missing metrics from zero matching stuck clusters.


AI-generated. Review for accuracy.

path: [status, conditions, "[type=ValidAzureKMSConfig]", status]
labelName: status
list: ["True", "False", "Unknown"]
- name: "deleting"

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.

This repeats the deleting metric from #7237, so this PR needs to merge with or before #7237 (or be folded into it) to avoid a conflict and to keep stuck-delete detection in place once the KAS suppression lands.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Updated this PR only in 5baf037: the copied deleting Info declaration is replaced by the numeric timestamp Gauge. #7237 is unchanged and will need its deletion-suppression consumers updated to use the new metric. The PR description retains the rollout dependency: dedicated stuck-deletion detection must be deployed and verified before relying on KAS suppression. No environment deployment was performed.


AI-generated. Review for accuracy.

@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

Thanks for the review. The proposed timestamp Gauge changes the behavior currently documented in this PR: actual deletion age over 48 hours with a short pending period, rather than 48 hours of continuous observation of the Info metric. I’m pausing implementation pending confirmation of that semantic change; I have not switched the metric or threshold behavior yet.

The remaining review items are recorded for the same batch:

  • Use the userJourney alert naming convention.
  • Remove the cluster label from the summary and align the correlation ID with the sibling stuck-operation alert.
  • Add the dedicated Alert Triage entry to the linked cluster-deletion TSG, including diagnosis and escalation.
  • Obtain an int/stage alert-tester report after the metric is deployed, covering identity labels and firing counts by region. Local rule tests do not establish those live results.
  • Coordinate the shared metric and merge/deployment ordering with fix: suppress HCPKASAvailableBurn alerts for clusters with non-empty deletionTimestamp #7237; neither PR has been combined or rebased by me.

The existing e2e-parallel failure is still unresolved; its relationship to this change has not been established.


AI-generated. Review for accuracy.

@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

Published the validated rebase onto main (d6ad305f5efd892da686edd21c169159be5c45c0); the new head is d603770a6b844d210631979c3c2b3d20be00f958.

Resolved duration-converter conflicts while retaining upstream validation fixes and regression coverage. All alert queues, generator tests/lint, chart checks, Bicep validation, and uncached alert-diagnostics corpus tests passed locally. Generated KAS rules match the new base unchanged.

The current Info metric / continuous 48-hour observation behavior remains unchanged. The proposed actual-deletion-age change and other review items remain outstanding, as does live environment validation. New-head CI results have not yet been verified.


AI-generated. Review for accuracy.

Copilot AI 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.

🔵 Needs a closer look

Monitoring owners must validate Azure’s acceptance and runtime behavior of the PT48H firing timeout and confirm production identity labels before rollout.

No open issues 🎉

Review effort: Balanced

@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

Investigated the new config-change-detection failure on d603770a6b844d210631979c3c2b3d20be00f958 (run). Building tooling/templatize failed while fetching multiple module ZIPs from proxy.golang.org, with INTERNAL_ERROR; received from peer HTTP/2 stream errors. The missing templatize-x86_64 prerequisite is downstream of that build failure; configuration validation did not complete.

This PR does not modify the affected module manifests or the templatize build system. The evidence supports a dependency-download failure, not a reported configuration mismatch; I have not made speculative code changes or confirmed that the download issue has recovered. A targeted rerun of this check is the next verification step.

The e2e failure listed in the same bot comment belongs to the older 003fbd9 revision. Current-head e2e remains pending; this does not resolve the older failure’s cause.


AI-generated. Review for accuracy.

Add an independent severity 4 alert after 48 hours of observed deleting state, preserving HostedCluster identity across scrape replicas. Reuse the Info metric contract proposed in public PR Azure#7237 without changing KAS alerts or SLOs.

Encode multi-day Prometheus durations as valid ISO time durations for Azure rule groups and cover observation boundaries, telemetry gaps, replica churn, and independent cluster identities.
@redhat-chai-bot
Chai-bot (redhat-chai-bot) force-pushed the alert-hostedcluster-deletion-stuck branch from d603770 to de0b957 Compare October 29, 2026 00:21
Copilot AI balanced review requested due to automatic review settings October 29, 2026 00:21
@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

Published the rebase onto 5c2cbef77cbab88d2c27b514703ac3990ac18e4e; the new head is de0b957c531900c136f96af2d0e05f64e78168ba.

The only conflict was the generated alert-diagnostics corpus fixture. Regenerated it through its supported consumer, preserving upstream alerts and adding only the expected 37 lines for this alert. Post-rebase diff review, uncached corpus tests, scoped lint, Helm fixtures/scheduling, formatting, and Bicep build/lint passed. Generated KAS rules match the new base unchanged.

The Info metric, severity 4, and continuous 48-hour observation behavior remain unchanged. Review items remain outstanding; this rebase does not implement the proposed actual-deletion-age change. New-head CI and live Azure acceptance have not yet been verified.


AI-generated. Review for accuracy.

Copilot AI 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.

🔵 Needs a closer look

Monitoring-owner validation is needed for Azure’s acceptance of the 48-hour firing timeout and the collected metric’s identity labels, neither of which local tests or Bicep compilation verify.

No open issues 🎉

Review effort: Balanced

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

Copilot AI balanced review requested due to automatic review settings October 29, 2026 02:07
@openshift-ci

openshift-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: redhat-chai-bot
Once this PR has been reviewed and has the lgtm label, please assign janboll for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copilot AI 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.

🟡 Changes recommended

The PR description and validation claims need correction to match the alert’s timestamp gauge, >48-hour deletion-age threshold, and 15-minute pending period.

1 open issue

Review effort: Balanced

Comment on lines +14 to +17
time() - max by (name, namespace, _id, subscription_id, resource_id, cluster, region) (
hostedClusterAPI_deletion_timestamp_seconds > 0
) > 172800
for: 15m

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Rechecked the live PR description: it now specifies hostedClusterAPI_deletion_timestamp_seconds, actual deletion age >48 hours, for: 15m, and the compiled PT15M artifact. The validation section also distinguishes local checks from the still-outstanding external TSG update and live int/stage verification. The description was updated alongside the Gauge publication; no further code change is needed for this mismatch.


AI-generated. Review for accuracy.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

@openshift-ci

openshift-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Chai-bot (@redhat-chai-bot): The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-parallel 5baf037 link true /test e2e-parallel

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@redhat-chai-bot

Copy link
Copy Markdown
Collaborator Author

Investigated the e2e-parallel failure on 5baf037.

  • No e2e tests ran: environment provisioning failed before the test phase.
  • The provisioning JUnit report records a 608-second ClusterService Helm rollout timeout: Deployment/clusters-service/clusters-service remained Available: 0/3, followed by context deadline exceeded.
  • The observability post step also failed: alert JUnit reports KubePodNotReady for three clusters-service pods and one sessiongate pod.

This PR does not change ClusterService application or chart files. However, the available artifacts do not establish why its pods were not ready, so I cannot yet classify this as a transient flake or definitively exclude an indirect relationship. The top-level and provisioning build logs have been removed, and the remaining artifacts lack the relevant application pod logs/events.

Next diagnostic evidence needed: clusters-service startup/readiness logs and Kubernetes events for the svc cluster around 03:17–03:28 UTC on October 29. No code changes or retest triggered.


AI-generated. Review for accuracy.

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

Labels

area/docs Automatically applied by owners-label for area/docs area/infrastructure Deployment/pipeline infrastructure config area/observability Automatically applied by owners-label for area/observability area/test Automatically applied by owners-label for area/test area/tooling Automatically applied by owners-label for area/tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants