Skip to content

Add admission_webhook_outage_hotel_reservation problem - #758

Merged
Saadmrp1038 merged 3 commits into
SREGym:mainfrom
samiamjidkhan:admission-webhook-outage
May 20, 2026
Merged

Add admission_webhook_outage_hotel_reservation problem#758
Saadmrp1038 merged 3 commits into
SREGym:mainfrom
samiamjidkhan:admission-webhook-outage

Conversation

@samiamjidkhan

Copy link
Copy Markdown
Contributor

Add admission_webhook_outage_hotel_reservation problem

Adds a new problem simulating an admission-webhook outage — a well-attested production failure class not currently covered by the SREGym catalogue. Includes a minimal mcp-server RBAC expansion (9 lines of YAML) needed for agents to mitigate this class of failure; rationale below. The PR can be landed as one piece or split (the problem alone is still a legitimate benchmark result under the default RBAC; see Stratus Run 1).


1. The real-world failure story

When a ValidatingWebhookConfiguration with failurePolicy: Fail points at a backend whose endpoints are missing or unreachable, every admission request the webhook intercepts is rejected by the kube-apiserver. Because admission control sits in the request path for every matching CREATE, the cluster (or matching namespaceSelector scope) loses the ability to create pods even though deployments, images, and nodes are all healthy. Recovery requires an operator with cluster-scoped permissions on admissionregistration.k8s.io.

Three public postmortems anchor this simulation, all listed on k8s.af (the failure-story aggregator referenced in the SREGym evaluation task spec):

  • Jetstack, 2019"How a simple admission webhook lead to a cluster outage." A ValidatingWebhookConfiguration on a GKE cluster interacted badly with GKE node auto-repair, causing prolonged downtime and a failed master upgrade. (Original blog redirects through Venafi → CyberArk post-acquisition; k8s.af is the canonical pointer.)
  • Wyssmann Engineering, December 2022"OPA Gatekeeper and issue while doing a cluster restore". Both Gatekeeper webhook configurations blocked pod lifecycle operations across CoreDNS, Canal, metrics-server, and ingress. Resolution required literally kubectl delete ValidatingWebhookConfiguration plus the mutating counterpart — the same mitigation surface our problem expects.
  • Airbnb, 2020 KubeCon"10 More Weird Ways to Blow Up Your Kubernetes". Covers a MutatingAdmissionWebhook failure mode among other things.

Recurring upstream issues confirm the class is ongoing: kubernetes/kubernetes#80313 (dead-TCP-affected webhooks) and cert-manager/cert-manager#5870 (cert-manager webhook gateway timeouts).

2. How the failure is simulated on SREGym

New problem class at sregym/conductor/problems/admission_webhook_outage.py. inject_fault installs a cluster-scoped ValidatingWebhookConfiguration with failurePolicy: Fail and a namespaceSelector scoped to hotel-reservation, whose clientConfig.service points at a service in default/ that does not exist. It then deletes one pod from the recommendation deployment so the ReplicaSet's recreate attempt hits the broken webhook and is rejected. caBundle is intentionally omitted so the apiserver uses its system trust roots and the failure surfaces at the backend-lookup step (service not found), matching the documented narrative rather than a cert-parsing error.

The problem is registered as "admission_webhook_outage_hotel_reservation" in the DIRECT K8S API section of registry.py. The class is parameterised over app_name (hotel_reservation / social_network / astronomy_shop) so sibling variants are a one-line follow-up.

recover_fault is idempotent: if the agent already removed the webhook during mitigation, recovery logs already absent and exits cleanly. The conductor's existing baseline reconcile (validating_webhook_configs_deleted) verifies no leftovers either way. The generic MitigationOracle accepts all three valid mitigation paths — delete the webhook, patch failurePolicy to Ignore, or restore the backend service — since each results in pod health.

3. Problem runtime behaviour

Verified across 5 end-to-end runs on a 4-node ARM kind cluster (1 control-plane + 3 workers, 16 GiB Docker).

Phase Observation
inject_fault runtime ~2–3 s (webhook create + pod delete)
Symptom recommendation ReplicaSet at desired=1, current=0, ready=0; the other 18 hotel-reservation pods stay healthy
Diagnostic signal Warning FailedCreate ... failed calling webhook "sregym-admission-webhook-outage.sregym.io": failed to call webhook: Post "https://sregym-faulty-webhook-svc.default.svc:443/validate?timeout=5s": service "sregym-faulty-webhook-svc" not found
Cross-namespace blast radius None — namespaceSelector confines the fault to hotel-reservation
Cleanup recover_fault deletes the webhook; conductor reconcile reports validating_webhook_configs_deleted: []

A clean human-driven run (me, via the CLI) scored 100/100 on diagnosis (D1=D2=D3=1.0, all 9 judge checklist questions Yes), mitigation passed, TTL=181.7 s, TTM=228.9 s. Back-to-back start cycles work without manual intervention; the baseline reconcile handles even mid-mitigation abnormal exits.

4. Agent behaviour (Stratus, GPT-5)

Ran Stratus twice — both runs are informative.

Run RBAC Diagnosis TTL Mitigation outcome
1 default True, 0.89 (D1=1.0, D2=0.67, D3=1.0) 127.3 s TIMEOUT (1800 s). Agent lacked permission on validatingwebhookconfigurations; tried 14 increasingly creative workarounds (delete the Deployment; recreate with a new label to evade an imagined objectSelector; relabel an existing pod and kubectl exec the recommendation binary inside it; attempt RBAC self-escalation via clusterrolebinding) — all denied.
2 this PR True, 0.89 (same dimensions) 347.8 s Mitigation actions correct: kubectl patch ... failurePolicy=Ignorekubectl scale deploy/recommendation 0→1kubectl delete validatingwebhookconfiguration ... → verified 19/19 pods Running → submitted. Cluster genuinely healthy. But then TIMEOUT (900 s) because Stratus's internal ClusterStateOracle could not reach 127.0.0.1:16443 (Connection refused), the driver triggered a deterministic rollback that tried to re-create the deleted webhook (blocked by this PR's RBAC scope, which excludes create), and the agent retried until timeout.

The D2 nit in both runs is the judge preferring "present with no endpoints" over "not found" — both are technically true of this fault.

Run 1 is itself a research finding. It demonstrates that admission-webhook outages of this form cannot be self-mitigated by an agent restricted to namespace-scoped workload RBAC, mirroring the real-world property that on-call engineers typically need a break-glass admin kubeconfig to recover from these incidents.

Run 2 is a separate finding worth flagging to the Stratus team: when ClusterStateOracle cannot reach 127.0.0.1:16443 after a successful submit, the retry/rollback heuristic produces an outcome strictly worse than accepting the submission — it actively tries to undo correct mitigations. In our case the RBAC scope happened to prevent the rollback from succeeding, which was fortunate.

RBAC change rationale

mcp_server/k8s/clusterrole.yaml adds one rule:

- apiGroups: ["admissionregistration.k8s.io"]
  resources:
    - validatingwebhookconfigurations
    - mutatingwebhookconfigurations
  verbs: ["get", "list", "watch", "delete", "patch", "update"]

get/list/watch lets the agent discover that a webhook is the root cause; delete/patch/update lets it execute any of the three valid mitigations. create is deliberately excluded — the framework controls webhook installation via inject_fault, and an agent re-creating a faulty webhook to "undo" a correct mitigation is exactly the pathological behaviour Run 2 illustrated. This mirrors the least-privilege scope an on-call SRE would expect on a temporary elevated kubeconfig.

If the maintainers prefer to land the RBAC change separately, the problem file can ship as-is — Run 1's TIMEOUT is itself a legitimate benchmark floor.

Notes for reviewers

  • No new Python dependencies; uses the already-imported kubernetes client.
  • Follows the NetworkPolicyBlock style (dict-shaped resource bodies) to avoid version-skew on typed-class names across kubernetes-client releases.
  • Sibling variants for social_network / astronomy_shop are a one-line follow-up; happy to add in a separate PR if useful.
  • Open to feedback on whether the dual-Stratus-run detail belongs here or in a separate research artifact.

@HacksonClark

Copy link
Copy Markdown
Member

This looks awesome! Great work!

@tianyin

tianyin commented May 19, 2026

Copy link
Copy Markdown
Contributor

This is a one of the most thoughtful PR I've ever read. Thank you! This is incredibly interesting!

We will review soon. @Saadmrp1038

@yimingsu01

Copy link
Copy Markdown
Collaborator

Amazing PR @samiamjidkhan!

@HacksonClark

Copy link
Copy Markdown
Member

Amazing PR @samiamjidkhan!

Agreed!

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

@samiamjidkhan The PR looks great! Thanks for your effort.

I left some comments below. Please ping me when you have addressed them.


Feel free to ping us if you have any questions or confusions!

Comment thread sregym/conductor/problems/admission_webhook_outage.py Outdated
Comment thread sregym/conductor/problems/admission_webhook_outage.py Outdated
@Saadmrp1038 Saadmrp1038 added the problem Adding a new problem to the benchmark label May 20, 2026
@samiamjidkhan

Copy link
Copy Markdown
Contributor Author

@samiamjidkhan The PR looks great! Thanks for your effort.

I left some comments below. Please ping me when you have addressed them.

Feel free to ping us if you have any questions or confusions!

Thanks for the review @Saadmrp1038! Both points addressed in the latest commit:

Names: Webhook + backend service renamed to pod-policy.validation.k8s.io and policy-system/pod-policy-webhook (looks like a real Gatekeeper/Kyverno-style webhook, no sregym-faulty-* leakage in events)

MitigationOracle: Added DeploymentReadinessOracle that reads Deployment.status.ready_replicas directly, so the absent pod is correctly detected. Verified locally: empty submit()Mitigation: success=false with ❌ 0/1 replicas ready; real mitigation → success=true with ✅ 1/1 replicas ready.

@samiamjidkhan
samiamjidkhan requested a review from Saadmrp1038 May 20, 2026 12:44
@Saadmrp1038

Copy link
Copy Markdown
Collaborator

The changes look good. I ran and tested the problem multiple times. Everything seems to be working correctly now. Congrats on the first PR merged here @samiamjidkhan 🎉
Hopefully the first of many!

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

Labels

problem Adding a new problem to the benchmark

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants