Error message
Unable to connect to the server: tls: failed to verify certificate: x509: certificate signed by unknown authority
Before this line, kubectl 1.37 also logs the failed API discovery request as an error-level line containing "Couldn't get current server API group list" and the same TLS error. When the kubeconfig's CA has the same name as the real one, the text continues with "(possibly because of … while trying to verify candidate authority certificate \"kubernetes\")".
kubectl (client-go) — the API server's certificate does not chain to the kubeconfig's certificate-authority-data
What it means
kubectl verifies the API server's certificate against the cluster CA stored in your kubeconfig (certificate-authority or certificate-authority-data), not against the system's public roots. "Unknown authority" means the served certificate does not chain to that CA: the kubeconfig has no CA or a CA of another cluster, or something between you and the API server presents its own certificate.
Why it happens
The kubeconfig lacks the cluster's CA or has another cluster's
commonHand-edited kubeconfigs, merged contexts pointing at the wrong cluster entry, or a server URL changed to a load balancer that serves a different certificate.
A TLS-inspecting proxy re-signs the API server connection
commonkubectl uses HTTPS_PROXY; corporate proxies present their own certificate, which the cluster CA did not issue.
A managed cluster endpoint changed
occasionalRecreated EKS, GKE or AKS clusters (or rotated cluster CAs) leave old kubeconfig entries with a CA that no longer matches.
How to fix it
- 1.
Look at the CA and server in your kubeconfig
Decode certificate-authority-data and compare its subject and dates with the issuer of the API server's certificate.
bash kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \ | base64 -d | openssl x509 -noout -subject -enddate kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' - 2.
Embed the right cluster CA
Set the cluster entry with the cluster's CA (for kubeadm, /etc/kubernetes/pki/ca.crt) and embed it into the kubeconfig.
bash # kubeadm clusters: the cluster CA is /etc/kubernetes/pki/ca.crt on a control-plane node kubectl config set-cluster my-cluster --server=https://k8s.example.com:6443 \ --certificate-authority=ca.crt --embed-certs=true - 3.
Regenerate kubeconfig for managed clusters
The cloud CLIs write a fresh cluster entry with the current endpoint and CA.
bash # Managed clusters: regenerate the kubeconfig entry from the provider aws eks update-kubeconfig --name my-cluster --region eu-central-1 gcloud container clusters get-credentials my-cluster --region europe-west1 az aks get-credentials --resource-group rg --name my-cluster - 4.
Bypass the proxy for the API server
Add the API server's host or network to NO_PROXY instead of disabling TLS verification (insecure-skip-tls-verify).
bash # kubectl honours HTTPS_PROXY; exclude the API server so a TLS-inspecting proxy is bypassed export NO_PROXY=k8s.example.com,10.0.0.0/8
Related errors
x509: certificate signed by unknown authority (possibly because of "crypto/rsa:…kubectl and other Go clientsUnable to connect to the server: tls: failed to verify certificate: x509: certi…kubectl (client-go)x509: certificate signed by unknown authorityGo crypto/x509Error response from daemon: Get "https://registry.example.com:5000/v2/": tls: f…Docker Engine (dockerd)