apache/druid · error · RuntimeException
Failed to create K8s ApiClient instance
Error message
Failed to create K8s ApiClient instance
What it means
A plain RuntimeException thrown from the Guice module's provider when io.kubernetes.client.openapi.Config.defaultClient() cannot build the default ApiClient — i.e. the in-cluster or kubeconfig configuration could not be loaded/initialized (IOException). This happens at first injection of the ApiClient (lazy singleton), typically at Druid startup with k8s discovery enabled.
Source
Thrown at extensions-core/kubernetes-extensions/src/main/java/org/apache/druid/k8s/discovery/K8sDiscoveryModule.java:65
{
return Collections.emptyList();
}
@Override
public void configure(Binder binder)
{
JsonConfigProvider.bind(binder, "druid.discovery.k8s", K8sDiscoveryConfig.class);
binder.bind(ApiClient.class)
.toProvider(
() -> {
try {
// Note: we can probably improve things here about figuring out how to find the K8S API server,
// HTTP client timeouts etc.
return Config.defaultClient();
}
catch (IOException ex) {
throw new RuntimeException("Failed to create K8s ApiClient instance", ex);
}
}
)
.in(LazySingleton.class);
binder.bind(K8sApiClient.class).to(DefaultK8sApiClient.class).in(LazySingleton.class);
binder.bind(K8sLeaderElectorFactory.class).to(DefaultK8sLeaderElectorFactory.class).in(LazySingleton.class);
PolyBind.optionBinder(binder, Key.get(DruidNodeDiscoveryProvider.class))
.addBinding(K8S_KEY)
.to(K8sDruidNodeDiscoveryProvider.class)
.in(LazySingleton.class);
PolyBind.optionBinder(binder, Key.get(DruidNodeAnnouncer.class))
.addBinding(K8S_KEY)
.to(K8sDruidNodeAnnouncer.class)
.in(LazySingleton.class);
View on GitHub (pinned to 9b90983fd2)
Solutions
- Run the Druid process inside the Kubernetes cluster, or set KUBERNETES_SERVICE_HOST/PORT and provide a valid service-account token.
- If using a kubeconfig, ensure the KUBECONFIG path is correct and the file is readable.
- Check /var/run/secrets/kubernetes.io/serviceaccount/ exists and contains token/ca.crt.
- Disable k8s discovery/announcer config if not deploying on Kubernetes.
Example fix
// before: running locally with druid_discovery_k8s=true and no cluster access // after export KUBERNETES_SERVICE_HOST=127.0.0.1 export KUBERNETES_SERVICE_PORT=6443 export KUBECONFIG=$HOME/.kube/config # or run in-cluster with mounted SA token
Defensive patterns
Strategy: validation
Validate before calling
// enable k8s discovery only when in-cluster or kubeconfig present
boolean inCluster = System.getenv("KUBERNETES_SERVICE_HOST") != null && System.getenv("KUBERNETES_SERVICE_PORT") != null;
boolean hasKubeconfig = System.getenv("KUBECONFIG") != null || new File(System.getProperty("user.home", "/root") + "/.kube/config").exists();
boolean hasSaToken = new File("/var/run/secrets/kubernetes.io/serviceaccount/token").exists();
if (!(inCluster && hasSaToken) && !hasKubeconfig) throw new IllegalStateException("K8s client config unavailable; disable k8s discovery or fix credentials"); Try / catch
try {
ApiClient client = injector.getInstance(ApiClient.class);
} catch (CreationException e) {
LOG.error(e, "K8s ApiClient init failed; check KUBERNETES_SERVICE_HOST and SA token");
throw e;
} Prevention
- Only enable druid k8s discovery/announcer when deploying inside Kubernetes.
- Ensure the service-account token and ca.crt are mounted at /var/run/secrets/kubernetes.io/serviceaccount.
- Set KUBECONFIG explicitly for out-of-cluster development.
- Fail fast at startup with a config check instead of a lazy-init surprise.
When it happens
Trigger: Config.defaultClient() throws IOException because the pod is not running inside Kubernetes (no KUBERNETES_SERVICE_HOST/PORT, missing /var/run/secrets/kubernetes.io/serviceaccount token) or the kubeconfig file is unreadable/invalid.
Common situations: Running Druid locally/in Docker outside a cluster with k8s discovery enabled; missing service-account token mount; RBAC-independent config loading failure; mispointed KUBECONFIG.
Related errors
- Invalid pod adapter [%s], only pod adapter [%s] can be speci
- At least one task runner must be enabled
- Invalid pod adapter [%s], only pod adapter [%s] can be speci
- Pod adapter [%s] requires the local Overlord pod namespace f
- Pod template task adapter requires a base pod template to be
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/7100ebcb03bd6415.
Report an issue: GitHub.