zhisheng17/flink-learning · error · FlinkException
Could not kill Kubernetes cluster ${clusterId}
Error message
Could not kill Kubernetes cluster ${clusterId} What it means
Thrown by killCluster when client.stopAndCleanupCluster(clusterId) throws while deleting the cluster's Kubernetes resources. handleException is invoked for richer diagnostics, and the original cause is not attached to the FlinkException, so check the logs/client for the underlying reason.
Source
Thrown at flink-learning-k8s/flink-k8s/src/main/java/org/apache/flink/kubernetes/KubernetesClusterDescriptor.java:268
return createClusterClientProvider(clusterId);
} catch (Exception e) {
try {
LOG.warn("Failed to create the Kubernetes cluster \"{}\", try to clean up the residual resources.", clusterId);
client.stopAndCleanupCluster(clusterId);
} catch (Exception e1) {
LOG.info("Failed to stop and clean up the Kubernetes cluster \"{}\".", clusterId, e1);
}
throw new ClusterDeploymentException("Could not create Kubernetes cluster \"" + clusterId + "\".", e);
}
}
@Override
public void killCluster(String clusterId) throws FlinkException {
try {
client.stopAndCleanupCluster(clusterId);
} catch (Exception e) {
client.handleException(e);
throw new FlinkException("Could not kill Kubernetes cluster " + clusterId);
}
}
@Override
public void close() {
try {
client.close();
} catch (Exception e) {
client.handleException(e);
LOG.error("failed to close client, exception {}", e.toString());
}
}
}
View on GitHub (pinned to d731cee761)
Solutions
- Check the logged cause (handleException output) for RBAC vs connectivity vs not-found errors.
- If resources are already gone, the cluster is effectively killed — verify with kubectl get deploy,svc | grep <clusterId> and ignore the failure.
- Grant the service account delete permissions (deployments, services, configmaps, pods) in the namespace.
- Retry once the Kubernetes API is reachable if the cause was transient connectivity.
- If the namespace is terminating, wait for termination; objects cannot be deleted meanwhile.
Example fix
// before
try {
descriptor.killCluster(clusterId);
} catch (FlinkException e) {
throw e; // cause lost
}
// after
descriptor.killCluster(clusterId); // then verify cleanup
kubectl get all -l app=<clusterId> # confirm nothing residual remains Defensive patterns
Strategy: try-catch
Validate before calling
boolean stillThere = kubeClient.getService(KubernetesService.ServiceType.REST_SERVICE, clusterId).isPresent();
if (!stillThere) { return; /* nothing to kill */ } Try / catch
try {
descriptor.killCluster(clusterId);
} catch (FlinkException e) {
LOG.warn("Kill failed for {}", clusterId, e); // check RBAC vs already-deleted
} Prevention
- Grant delete RBAC on deployments/services/configmaps/pods
- Handle double-kill idempotently
- Verify namespace is not terminating before cleanup
- Keep the client's handleException diagnostics in logs
When it happens
Trigger: Calling killCluster(clusterId) when Kubernetes API delete calls fail — RBAC denial on delete, API server unreachable, or resources already gone/deleted concurrently.
Common situations: Deleting a cluster that was already removed; a service account lacking delete permissions on deployments/services/configmaps; network partition to the Kubernetes API; namespace already terminating (deletes rejected).
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- Could not get the rest endpoint of ${clusterId}
- Could not create the RestClusterClient.
- The Flink cluster ${clusterId} already exists.
- Couldn't deploy Kubernetes Application Cluster. Expected dep
- Per-Job Mode not supported by Active Kubernetes deployments.
AI-assisted analysis of zhisheng17/flink-learning@d731cee761 (2026-09-06).
Data as JSON: /api/errors/5681ebbcfcff7763.
Report an issue: GitHub.