istio/istio · critical
KUBERNETES_SERVICE_HOST not set. Is this not running within
Error message
KUBERNETES_SERVICE_HOST not set. Is this not running within a pod?
What it means
istio-cni-node builds its kubeconfig from in-pod environment variables and found KUBERNETES_SERVICE_HOST empty. In Kubernetes, the kubelet always injects KUBERNETES_SERVICE_HOST/PORT into pods; the error text asks whether the process is running outside a pod. The value comes from cfg.K8sServiceHost, populated from the env var.
Source
Thrown at cni/pkg/install/kubeconfig.go:42
"k8s.io/client-go/tools/clientcmd/api/latest"
"sigs.k8s.io/yaml"
"istio.io/istio/cni/pkg/config"
"istio.io/istio/cni/pkg/constants"
"istio.io/istio/pilot/pkg/model"
"istio.io/istio/pkg/file"
)
type kubeconfig struct {
// The full kubeconfig
Full string
// Kubeconfig with confidential data redacted.
Redacted string
}
func createKubeConfig(cfg *config.InstallConfig) (kubeconfig, error) {
if len(cfg.K8sServiceHost) == 0 {
return kubeconfig{}, fmt.Errorf("KUBERNETES_SERVICE_HOST not set. Is this not running within a pod?")
}
if len(cfg.K8sServicePort) == 0 {
return kubeconfig{}, fmt.Errorf("KUBERNETES_SERVICE_PORT not set. Is this not running within a pod?")
}
protocol := model.GetOrDefault(cfg.K8sServiceProtocol, "https")
cluster := &api.Cluster{
Server: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(cfg.K8sServiceHost, cfg.K8sServicePort)),
}
if cfg.SkipTLSVerify {
// User explicitly opted into insecure.
cluster.InsecureSkipTLSVerify = true
} else {
caFile := model.GetOrDefault(cfg.KubeCAFile, cfg.K8sServiceAccountPath+"/ca.crt")
caContents, err := os.ReadFile(caFile)
if err != nil {View on GitHub (pinned to 8dc789c5cf)
Solutions
- If running in Kubernetes, check the pod spec was not modified to remove the service env vars and recreate the pod.
- If running outside a pod (debug/test), set KUBERNETES_SERVICE_HOST explicitly, e.g. KUBERNETES_SERVICE_HOST=<api-server-ip> ./install-cni.
- Set the host via the pod spec env block with an explicit value if the default link is missing (unusual setups with disabled service links).
- Verify with: kubectl -n istio-system exec istio-cni-node-xxxx -- env | grep KUBERNETES_SERVICE.
Example fix
# before $ ./install-cni # fails: KUBERNETES_SERVICE_HOST not set # after (manual run) $ KUBERNETES_SERVICE_HOST=10.96.0.1 KUBERNETES_SERVICE_PORT=443 ./install-cni
Defensive patterns
Strategy: validation
Validate before calling
# Verify before deploying the pod spec / running manually. kubectl -n istio-system exec ds/istio-cni-node -- sh -c 'test -n "$KUBERNETES_SERVICE_HOST" && echo ok || echo missing'
Prevention
- Run the CNI install binary only inside the daemonset pod, or export KUBERNETES_SERVICE_HOST manually.
- Do not strip Kubernetes service env vars in pod specs or base images.
- In tests, always set KUBERNETES_SERVICE_HOST/PORT explicitly.
When it happens
Trigger: createKubeConfig is called during install and cfg.K8sServiceHost is empty — i.e. KUBERNETES_SERVICE_HOST was not in the environment. Typical when running the install binary manually on a node, in docker without pod env, or when the env var is explicitly unset/emptied in the pod spec.
Common situations: Debugging the CNI binary by exec'ing it in a plain docker container; a mutated istio-cni-node pod spec that clears env vars; running install tests outside a pod without setting the variable explicitly; security scanners that strip service env vars.
Related errors
- KUBERNETES_SERVICE_PORT not set. Is this not running within
- not implemented on this platform
- primary CNI config name is not specified, cannot write CNI c
- no networks found in %s
- plugin type %v not a string
AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15).
Data as JSON: /api/errors/f4540f9ed4465da2.
Report an issue: GitHub.