Kubernetes Error Guide: 'x509: certificate is valid for ..., not <svc>.<ns>.svc' Admission Webhook Failure
Fix the admission webhook 'x509: certificate is valid for <names>, not <svc>.<ns>.svc' error: repair serving certificate SANs and the webhook caBundle so the API server can call it.
- #kubernetes
- #troubleshooting
- #errors
- #webhooks
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Exact Error Message
Error from server (InternalError): Internal error occurred: failed calling webhook
"vpod.kb.io": failed to call webhook: Post
"https://webhook-service.my-namespace.svc:443/validate?timeout=10s":
x509: certificate is valid for webhook-service, ingress.local, not
webhook-service.my-namespace.svc
The specific names before and after not vary, but the shape is always the same: the certificate the webhook presented is valid for one set of names, and the DNS name the API server dialed is not in that set.
Overview
When you create, update, or delete an object, the API server calls any matching validating or mutating admission webhook over HTTPS. The API server dials the webhook using the in-cluster service DNS name <service>.<namespace>.svc and verifies the TLS certificate the webhook presents against the CA in the webhook configuration’s caBundle. Crucially, it also checks that the certificate’s Subject Alternative Names (SANs) include the exact hostname it dialed.
This x509 error means the TLS chain verified fine, but the serving certificate’s SAN list does not contain <service>.<namespace>.svc. The webhook is presenting a certificate minted for the wrong DNS name, usually because the cert was generated with a hardcoded or stale name that does not match where the webhook actually runs.
Symptoms
- Creating or modifying resources that match the webhook fails with
x509: certificate is valid for ..., not <svc>.<ns>.svc. - The failure only happens for objects the webhook rule selects; unrelated objects apply fine.
kubectl applyof the workload the webhook guards is blocked, andfailurePolicy: Failwebhooks block a whole resource class.- The webhook pod itself is running and healthy; the problem is purely certificate identity.
Common Root Causes
1. Serving certificate SAN does not match the service DNS name
The certificate must list <service>.<namespace>.svc (and often <service>.<namespace>.svc.cluster.local) as SANs. A cert generated for just <service> or for a different namespace fails the check.
2. Namespace or service name changed after the cert was issued
Reinstalling the webhook into a different namespace, or renaming the Service, invalidates a certificate that hardcoded the old name.
3. cert-manager Certificate has the wrong dnsNames
When cert-manager issues the serving cert, its spec.dnsNames must include the full service FQDN. A missing or misspelled entry produces a valid cert for the wrong identity.
4. Manually rotated cert without updating SANs
Regenerating the serving secret with an ad-hoc openssl command that omitted the service SANs is a classic cause.
5. caBundle and serving cert are mismatched but SANs happen to differ
If the caBundle was updated but the serving cert was minted separately with different names, verification reaches the SAN check and fails there.
Diagnostic Workflow
Step 1: Read the exact names from the error
Note the value after valid for (what the cert has) and after not (what the API server dialed). The fix is to make the former contain the latter.
Step 2: Find the webhook service and namespace
kubectl get validatingwebhookconfiguration <name> \
-o jsonpath='{.webhooks[*].clientConfig.service}'
This shows the name and namespace the API server uses to build the DNS name.
Step 3: Inspect the serving certificate’s SANs
kubectl get secret <webhook-tls-secret> -n <ns> \
-o jsonpath='{.data.tls\.crt}' | base64 -d | \
openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
Confirm whether <service>.<namespace>.svc is listed.
Step 4: Verify the caBundle matches the issuing CA
kubectl get validatingwebhookconfiguration <name> \
-o jsonpath='{.webhooks[0].clientConfig.caBundle}' | base64 -d | \
openssl x509 -noout -subject
Step 5: If using cert-manager, check the Certificate resource
kubectl get certificate <name> -n <ns> -o jsonpath='{.spec.dnsNames}'
Step-by-Step Resolution
- Regenerate the serving certificate with the correct SANs. The certificate must include the full in-cluster names. With cert-manager, set:
spec:
dnsNames:
- webhook-service.my-namespace.svc
- webhook-service.my-namespace.svc.cluster.local
secretName: webhook-server-cert
issuerRef:
name: selfsigned-issuer
kind: Issuer
- If generating manually, include the SANs explicitly:
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
-keyout tls.key -out tls.crt \
-subj "/CN=webhook-service.my-namespace.svc" \
-addext "subjectAltName=DNS:webhook-service.my-namespace.svc,DNS:webhook-service.my-namespace.svc.cluster.local"
- Update the TLS secret the webhook pod mounts:
kubectl create secret tls webhook-server-cert \
--cert=tls.crt --key=tls.key -n my-namespace \
--dry-run=client -o yaml | kubectl apply -f -
- Sync the caBundle so the API server trusts the issuing CA. cert-manager’s CA injector does this automatically when the webhook config is annotated; otherwise patch it:
kubectl patch validatingwebhookconfiguration <name> --type='json' \
-p="[{'op':'replace','path':'/webhooks/0/clientConfig/caBundle','value':'$(base64 -w0 ca.crt)'}]"
- Restart the webhook pod so it reloads the new serving secret:
kubectl rollout restart deployment <webhook-deployment> -n my-namespace
- Confirm the webhook now accepts calls:
kubectl apply -f test-object.yaml
A successful apply means the SAN now matches the dialed name.
Prevention
- Always template the service FQDN into your certificate’s
dnsNames; never hardcode a bare service name. - Prefer cert-manager with the CA injector so
caBundleand serving cert are always issued together and rotated in sync. - Include both
<svc>.<ns>.svcand<svc>.<ns>.svc.cluster.localSANs to cover every form the API server may use. - Add a CI check that decodes the serving secret and asserts the expected SANs before rollout.
- When moving a webhook to a new namespace, treat the certificate as namespace-specific and reissue it.
Related Errors
x509: certificate signed by unknown authority— thecaBundledoes not match the issuing CA, a chain problem rather than a SAN mismatch.failed calling webhook: context deadline exceeded— the webhook service is unreachable or slow, not a cert issue.no endpoints available for service "webhook-service"— the webhook pods are not ready, so the Service has no backends.Internal error occurred: failed calling webhook: EOF— the webhook closed the TLS connection, often a serving-port or protocol mismatch.
Frequently Asked Questions
Which DNS name does the API server actually use? It uses the service.name and service.namespace from the webhook configuration to build <name>.<namespace>.svc. That exact string must appear in the certificate’s SAN list.
Do I need the .cluster.local suffix in the SAN? Including both <svc>.<ns>.svc and <svc>.<ns>.svc.cluster.local is the safest choice, since either form can be dialed depending on configuration. Adding both avoids surprises.
Why did this appear only after reinstalling the webhook? Reinstalling into a different namespace or renaming the Service changes the DNS name the API server dials, so a certificate minted for the old name no longer matches. Reissue the cert with the new names.
Can I fix this by updating just the caBundle? No. The caBundle controls CA trust; this error is a SAN mismatch on the serving certificate. You must reissue the serving cert with the correct dnsNames. Generating correct manifests is faster with the DevOps AI prompt library.
Should I use failurePolicy: Ignore to unblock production? Only as a deliberate, temporary measure while you fix the certificate, since Ignore lets non-compliant objects through and defeats the webhook’s purpose. Fix the SANs and restore Fail. For more, see the Kubernetes & Helm guides.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.