x509: certificate signed by unknown authority: The client does not trust the certificate the server presented
This TLS error means the certificate chain the server offered was not signed by any authority the client trusts. It happens with the API server, with webhooks, and with registries, and the fix is always to establish trust properly rather than to disable it.
Applies to: All Kubernetes versions
What it means
TLS verification requires the client to trace the server's certificate to a certificate authority it already trusts. x509: certificate signed by unknown authority means that trace failed. In Kubernetes this appears in three distinct places, each with its own remedy: a client connecting to the API server, where the kubeconfig's embedded CA data is wrong or missing; the API server connecting to an admission webhook, where the webhook configuration's caBundle is wrong or stale; and the kubelet pulling from a registry, where the node does not trust the registry's CA. The wording is identical in all three, so identifying which side is complaining is the first step.
Most common causes
- The kubeconfig's
certificate-authority-datais missing, truncated, or from a different cluster. - The cluster's CA was rotated and clients still hold the old one.
- A webhook's
caBundlein its configuration object does not match the certificate the webhook serves. - A certificate manager reissued a webhook's certificate without updating the bundle that references it.
- A private registry using an internal CA that the nodes do not trust.
- A TLS-intercepting proxy in the path presenting its own certificate.
- An incomplete chain — the server sends a leaf certificate without the intermediate that links it to the root.
How to diagnose it
- Identify which client is failing. The error text alone is ambiguous; the context around it is not.
- For kubectl, inspect the CA in the kubeconfig:
kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}', decode it, and compare against the cluster's actual CA. - For a webhook, compare its configuration's
caBundleagainst the certificate the webhook serves:kubectl get validatingwebhookconfiguration NAME -o yaml. - For a registry, test from the node:
openssl s_client -connect REGISTRY:443 -showcertsand check the chain. - Check for a corporate TLS-intercepting proxy, which is common on managed networks and produces this on every outbound connection.
How to fix it
- Update the client's trusted CA to the cluster's current one.
- Update a webhook's
caBundlewhenever its certificate is reissued. A certificate manager with a CA injection annotation automates this and is worth using. - Install the registry's CA into the node's trust store, or into the container runtime's registry configuration.
- Serve the full certificate chain from the server, including intermediates.
- Do not disable verification with
--insecure-skip-tls-verifyor an equivalent as a fix. It makes the error disappear and removes the protection the error exists to provide, on exactly the connection that carries cluster credentials.
Notes
A stale webhook caBundle is particularly disruptive because a failing webhook with failurePolicy: Fail blocks every request it intercepts. Certificate rotation on a webhook that gates pod creation can take a whole cluster down.
Related
- admission webhook denied the request — An admission webhook rejected the object
- Unauthorized — The request was not authenticated
Sources
- Kubernetes documentation — Authenticating
- Kubernetes documentation — Dynamic Admission Control
- Kubernetes documentation — Certificate Signing Requests