| title | Failed Calling Webhook | |||||
|---|---|---|---|---|---|---|
| error_message | failed calling webhook "<name>": connection refused | |||||
| category | api-server | |||||
| severity | High | |||||
| recovery_time | 5–30 min | |||||
| k8s_versions | 1.20+ | |||||
| tags |
|
|||||
| related |
|
Severity: High · Typical recovery time: 5–30 min · Affected versions: 1.20+
Internal error occurred: failed calling webhook "vpod.example.com":
failed to call webhook: Post "https://webhook-svc.ns.svc:443/validate":
dial tcp 10.96.0.5:443: connect: connection refused
Admission webhooks (validating/mutating) intercept API requests before they are
persisted. When the apiserver cannot reach the webhook endpoint, requests for the
objects that webhook matches fail. With failurePolicy: Fail (the safe default
for security webhooks) this blocks creates/updates cluster-wide for the matched
resources — a classic self-inflicted outage when the webhook backend is down or
its Service/network is broken.
Applies to 1.20+. admissionregistration.k8s.io/v1 is stable across these
versions; behaviour depends on failurePolicy, timeoutSeconds, and
namespaceSelector/objectSelector scoping.
- Webhook backend pods are down, crash-looping, or scaled to zero
- Service selector/endpoints don't match the webhook pods (no endpoints)
- NetworkPolicy or CNI blocking apiserver-to-webhook traffic
- Webhook scoped too broadly so it intercepts its own dependencies
- TLS cert/
caBundlemismatch causing the call to be rejected
flowchart TD
A[failed calling webhook] --> B{Webhook backend healthy?}
B -- No --> C[Fix/scale webhook pods]
B -- Yes --> D{Service has endpoints?}
D -- No --> E[Fix selector/labels]
D -- Yes --> F{NetworkPolicy blocking?}
F -- Yes --> G[Allow apiserver egress]
F -- No --> H[Check caBundle/TLS]
Confirm which webhook is failing, its failurePolicy, and whether its backing
Service has ready endpoints.
kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations
kubectl get validatingwebhookconfiguration <name> -o yaml | grep -E 'failurePolicy|service:|namespace:|name:|timeoutSeconds'
kubectl get endpoints -n <ns> <webhook-svc>
kubectl get pods -n <ns> -l <webhook-selector>
kubectl logs -n <ns> deploy/<webhook> --tail=50
kubectl get events -A --sort-by=.lastTimestamp | grep -i webhook$ kubectl get endpoints -n ns webhook-svc
NAME ENDPOINTS AGE
webhook-svc <none> 6d # no ready backends
$ kubectl apply -f deploy.yaml
Error from server: failed calling webhook "vpod.example.com": connection refused
- Restore the webhook backend (scale up, fix crash loop, repair the Deployment).
- Fix the Service selector/labels so endpoints populate.
- Add a NetworkPolicy rule allowing apiserver traffic to the webhook port.
- Correct the
caBundle/serving cert if the failure is a TLS rejection.
- Identify the offending webhook from the error and its
failurePolicy. - Disruptive (emergency): if a
failurePolicy: Failwebhook is wedging the cluster and its backend cannot be restored, temporarily delete or scope down theValidatingWebhookConfiguration/MutatingWebhookConfiguration. Blast radius: admission checks for those resources are skipped until restored — a security/policy gap, so re-enable as soon as the backend is healthy. - Scope future webhooks with
namespaceSelectorexcludingkube-system.
The previously failing kubectl apply/create succeeds and the webhook Service
shows ready endpoints again.
Run webhook backends HA with PodDisruptionBudgets, set sensible timeoutSeconds,
exclude system namespaces, monitor endpoint readiness, and reserve
failurePolicy: Ignore for non-critical webhooks.