HwangDongJun commented on code in PR #58187:
URL: https://github.com/apache/spark/pull/58187#discussion_r3858987373


##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/submit/KubernetesClientApplication.scala:
##########
@@ -136,7 +136,10 @@ private[spark] class Client(
     val driverPodName = resolvedDriverPod.getMetadata.getName
 
     // setup resources before pod creation
-    val preKubernetesResources = 
resolvedDriverSpec.driverPreKubernetesResources
+    // SPARK-38079: the driver's own base config map (mounted as 
SPARK_CONF_VOLUME_DRIVER
+    // above) must also be created before the pod itself, to avoid a 
"configmap ... not
+    // found" mount race between the driver pod and the config map it depends 
on.
+    val preKubernetesResources = 
resolvedDriverSpec.driverPreKubernetesResources ++ Seq(configMap)

Review Comment:
   Thanks for the detailed writeup, @LuciferYang -- you're right, and I've 
implemented the shutdown hook you outlined.
   
   Summary of the change in `Client.run()`:
   - A shutdown hook is registered (via `ShutdownHookManager`, per scalastyle 
-- not `Runtime.getRuntime` directly) right before the pre-resources are 
applied, tracking two flags (`preResourcesApplied`, `podCreatedByUs`) for how 
far `run()` got.
   - It builds its own fresh `KubernetesClient` rather than reusing the 
injected one, since that one may already be closed or concurrently in use by 
the time the hook runs, as you noted.
   - It deletes the pre-resources (and the pod, only if this submission created 
it) only if `preResourcesApplied` is true; otherwise it's a no-op.
   - The hook is removed entirely (not left as a no-op) in a `finally`, once 
the owner-reference refresh completes or one of the existing catch blocks has 
already cleaned up -- so Ctrl-C during `waitAppCompletion` keeps today's detach 
behavior.
   - Cleanup exceptions are caught and logged, never propagated.
   
   A couple of things worth calling out:
   - The fresh client reuses the same request/connection timeouts as the rest 
of `run()` (`SparkKubernetesClientFactory`/`ClientType.Submission`), so this 
can't hang indefinitely even against a slow API server.
   - I intentionally left this without a config flag to disable it -- it's a 
no-op outside that specific abrupt-termination window, so there's no 
steady-state behavior for a flag to protect against.
   
   Testing: the cleanup logic and the hook registration/removal wiring in 
`run()` are both covered by new unit tests with injected fakes (triggering a 
real JVM shutdown hook from a test isn't practical). I also reproduced your 
exact scenario against a real cluster -- killed the process (SIGTERM) between 
the pre-resource apply and the owner-reference refresh, both without and with 
this fix -- and confirmed the ConfigMap is left ownerless in the former case 
and cleaned up in the latter.
   
   As you noted, SIGKILL and in-flight API calls at the moment of a hard kill 
remain uncovered either way.
   
   Let me know if this looks right, or if you'd prefer a different approach.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to