-
Notifications
You must be signed in to change notification settings - Fork 160
Improve snapshot analyze context for stuck deletion scenario #5989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
venkateshsredhat
wants to merge
8
commits into
main
Choose a base branch
from
deletion-stuck-skill
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+494
−3
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
c17c9b8
adding skills to analyze stuck deletion
venkateshsredhat 5e8f3b6
teach the ai analyze tooling to detect stuck deletion pattern
venkateshsredhat cb091c1
fix copilot review comments: path conventions and hardcoded count
venkateshsredhat 0af3d52
check
venkateshsredhat d816f84
refine based on reviews
venkateshsredhat 0d77bb4
fix the exemplar
ab5a91b
add the kql for acm
66019f3
add details of nodepool flow
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
228 changes: 228 additions & 0 deletions
228
.../exemplars/cluster-deletion-timeout-because-managedcluster-cr-deletion-stuck.md
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
tooling/hcpctl/pkg/snapshot/queries/acm/klusterletEvents/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # acm / klusterletEvents | ||
|
|
||
| ## Summary | ||
|
|
||
| Lists Kubernetes API events from the klusterlet namespace (`klusterlet-<cluster-id>`) for this cluster. | ||
| These are K8s Event objects ingested by the kube-events collector into `ServiceLogs.kubernetesEvents`. | ||
|
|
||
| ## What to Look For | ||
|
|
||
| - `Evicted` reason on addon pre-delete pods — indicates node resource pressure (MemoryPressure, | ||
| DiskPressure) evicted the pods before completion, blocking ManagedCluster deletion. | ||
| - `FailedScheduling` reason — the pod could not be placed on any node. | ||
| - `FailedMount`, `BackOff`, `Unhealthy` reasons — container-level failures that prevent | ||
| addon hooks from completing. | ||
|
|
||
| ## Where to Go Next | ||
|
|
||
| - If addon pre-delete pods are being evicted, check `logs/acm/klusterletLogs.md` for pod-level detail | ||
| (status reason, phase, node placement) and `conditions/acm/managedClusterConditions.md` to confirm | ||
| the ManagedCluster is stuck pending deletion. | ||
| - Review `logs/clustersService/logs.md` for the destruct chain state. | ||
| - See `docs/ops/cleanup-stuck-cluster-deletion.md`, Scenario 6, for manual remediation. |
14 changes: 14 additions & 0 deletions
14
tooling/hcpctl/pkg/snapshot/queries/acm/klusterletEvents/query.kql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| cluster('{{ .ClusterURI }}').database('{{ .ServiceDatabase }}').table('kubernetesEvents') | ||
| | where timestamp between ({{ kqlDatetime .PhaseStartTime }} .. {{ kqlDatetime .PhaseEndTime }}) | ||
| {{- if and .ServiceClusterName .ManagementClusterName }} | ||
| | where cluster in ('{{ .ServiceClusterName }}', '{{ .ManagementClusterName }}') | ||
| {{- end }} | ||
| | where eventNamespace == strcat('klusterlet-', '{{ .ClusterID }}') | ||
| | project | ||
| timestamp, | ||
| objectKind, | ||
| objectName, | ||
| reason, | ||
| message, | ||
| type | ||
| | order by timestamp asc |
24 changes: 24 additions & 0 deletions
24
tooling/hcpctl/pkg/snapshot/queries/acm/klusterletLogs/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # acm / klusterletLogs | ||
|
|
||
| ## Summary | ||
|
|
||
| Lists pod lifecycle events from the klusterlet namespace (`klusterlet-<cluster-id>`) as observed by the | ||
| mgmt-agent PodWatcher. These are container log entries (not K8s Event objects) from the `mgmt-agent` | ||
| namespace where `log.msg == 'pod event'`, providing pod-level detail including status reason, phase, | ||
| and node placement. | ||
|
|
||
| ## What to Look For | ||
|
|
||
| - Pods with `reason == 'Evicted'` and messages mentioning `MemoryPressure` or `DiskPressure` — | ||
| indicates node resource pressure evicted addon pods before they could complete. | ||
| - `phase == 'Failed'` on addon pre-delete hook pods — confirms the pod did not run to completion. | ||
| - Multiple eviction entries for the same ReplicaSet hash — suggests repeated reschedule-then-evict | ||
| cycles that exhaust the controller's retry budget. | ||
| - Evictions across different nodes — indicates cluster-wide resource pressure, not a single-node issue. | ||
|
|
||
| ## Where to Go Next | ||
|
|
||
| - Check `events/acm/klusterletEvents.md` for the corresponding K8s Event objects (Evicted, FailedScheduling). | ||
| - Check `conditions/acm/managedClusterConditions.md` to see if the ManagedCluster is stuck pending deletion. | ||
| - Review `logs/clustersService/logs.md` for the destruct chain state. | ||
| - See `docs/ops/cleanup-stuck-cluster-deletion.md`, Scenario 6, for manual remediation. |
16 changes: 16 additions & 0 deletions
16
tooling/hcpctl/pkg/snapshot/queries/acm/klusterletLogs/query.kql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| cluster('{{ .ClusterURI }}').database('{{ .ServiceDatabase }}').table('containerLogs') | ||
| | where timestamp between ({{ kqlDatetime .PhaseStartTime }} .. {{ kqlDatetime .PhaseEndTime }}) | ||
| {{- if and .ServiceClusterName .ManagementClusterName }} | ||
| | where cluster in ('{{ .ServiceClusterName }}', '{{ .ManagementClusterName }}') | ||
| {{- end }} | ||
| | where namespace_name == 'mgmt-agent' and log.msg == 'pod event' | ||
| | where log.namespace == strcat('klusterlet-', '{{ .ClusterID }}') | ||
| | project | ||
| timestamp, | ||
| pod_name = tostring(log.name), | ||
| event = tostring(log.event), | ||
| reason = tostring(log.object.status.reason), | ||
| message = tostring(log.object.status.message), | ||
| phase = tostring(log.object.status.phase), | ||
| node = tostring(log.object.spec.nodeName) | ||
| | order by timestamp asc |
33 changes: 33 additions & 0 deletions
33
tooling/hcpctl/pkg/snapshot/queries/acm/managedClusterConditions/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # acm / managedClusterConditions | ||
|
|
||
| ## Summary | ||
|
|
||
| Extracts a point-in-time snapshot of ManagedCluster conditions from the last mgmt-agent ResourceWatcher | ||
| emission within the current phase's time window. The ManagedCluster CR is cluster-scoped and named by the | ||
| CS cluster ID. | ||
|
|
||
| ## What to Look For | ||
|
|
||
| A healthy ManagedCluster should have: | ||
|
|
||
| | type | status | reason | | ||
| |-------------------------|--------|---------------------| | ||
| | HubAcceptedManagedCluster | True | HubClusterAdminAccepted | | ||
| | ManagedClusterConditionAvailable | True | ManagedClusterAvailable | | ||
| | ManagedClusterJoined | True | ManagedClusterJoined | | ||
|
|
||
| During deletion, watch for: | ||
|
|
||
| - `ManagedClusterConditionAvailable` changing to `Unknown` — indicates the klusterlet has lost contact, | ||
| which can prevent addon pre-delete hooks from executing. | ||
| - `ManagedClusterImportSucceeded` showing reason `ManagedClusterForceDetaching` — the hub is attempting | ||
| a forced detach, indicating the ManagedCluster is stuck pending deletion. | ||
|
|
||
| ## Where to Go Next | ||
|
|
||
| - If conditions show the cluster stuck pending deletion, check `logs/clustersService/logs.md` for repeated | ||
| `Not continuing to the next destructor` messages at the `hypershift-managed-cluster-destructor` step. | ||
| - Review `events/acm/klusterletEvents.md` for K8s events and `logs/acm/klusterletLogs.md` for pod-level | ||
| detail on evictions or scheduling failures in the klusterlet namespace. | ||
| - See `docs/ops/cleanup-stuck-cluster-deletion.md`, Scenario 6, for the manual fix (clearing | ||
| `ManagedClusterAddon` finalizers). |
13 changes: 13 additions & 0 deletions
13
tooling/hcpctl/pkg/snapshot/queries/acm/managedClusterConditions/query.kql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| cluster('{{ .ClusterURI }}').database('{{ .ServiceDatabase }}').table('containerLogs') | ||
| | where timestamp between ({{ kqlDatetime .PhaseStartTime }} .. {{ kqlDatetime .PhaseEndTime }}) | ||
| {{- if and .ServiceClusterName .ManagementClusterName }} | ||
| | where cluster in ('{{ .ServiceClusterName }}', '{{ .ManagementClusterName }}') | ||
| {{- end }} | ||
| | where container_name == 'mgmt-agent-controller' | ||
| | where tostring(log.msg) == 'resource event' | ||
| | where tostring(log.object.kind) == 'ManagedCluster' | ||
| | where tostring(log.name) == '{{ .ClusterID }}' | ||
| | summarize content=take_any(log.object), observedTime=take_any(timestamp) by event=tostring(log.event) | ||
| | top 1 by observedTime desc | ||
| | mv-expand condition = content.status.conditions | ||
| | project observedTime, type=tostring(condition.type), status=tostring(condition.status), reason=tostring(condition.reason), message=tostring(condition.message), lastTransitionTime=todatetime(condition.lastTransitionTime) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.