[SPARK-58967][K8S] Use FQDN with configurable cluster domain for driver hostname - #58283
[SPARK-58967][K8S] Use FQDN with configurable cluster domain for driver hostname#58283shazebkhan1 wants to merge 1 commit into
Conversation
…or driver hostname On Kubernetes clusters where the cluster domain is not the default 'cluster.local', or where pod DNS search domains are restricted, Spark pipeline submission fails because executors cannot resolve the partial driver hostname '<service>.<namespace>.svc'. This change introduces spark.kubernetes.clusterDomain (default: 'cluster.local') and sets spark.driver.host to the fully-qualified domain name '<service>.<namespace>.svc.<clusterDomain>.' with a trailing dot to force absolute DNS resolution, eliminating search domain traversal ambiguity. Generated with Devin (https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
d126cf6 to
0c64784
Compare
|
Thank you for the PR, and for the detailed description of the I have a concern about the default value being a silent behavior change.
Note also that Could we make this opt-in instead? For example, val driverHostname = kubernetesConf.get(KUBERNETES_CLUSTER_DOMAIN)
.map(d => s"$resolvedServiceName.${kubernetesConf.namespace}.svc.$d.")
.getOrElse(s"$resolvedServiceName.${kubernetesConf.namespace}.svc")If we want to keep |
|
One more note on the motivation section, which no longer matches As I mentioned in dev mailing list, So "each executor startup generates these spurious failed lookups" is not accurate for the default configuration on and those lookups are additionally subject to the JVM DNS cache. Could you update the description to describe the paths that still resolve the name on |
|
Hi @dongjoon-hyun, We wanted to share our experience with SPARK-53944 and also report a related issue we discovered during testing. SPARK-53944 — Backported and validated on Spark 3.5.2 We cherry-picked the changes from PRs #52650, #52923, and #52954 (
The fix works as expected. Thank you for the work on this. Separate issue — API server NXDOMAIN queries from the driver pod After resolving the executor-to-driver DNS issue, we observed a different set of NXDOMAIN queries in CoreDNS originating from the driver pod itself on every Kubernetes API server call: This is the ndots:5 search-domain expansion: Root cause
We confirmed this is present in Spark 3.5.x, branch-4.1, and current master (5.0-SNAPSHOT). This is orthogonal to SPARK-53944 — that fix addresses executor-to-driver connectivity; this affects driver-to-API-server connectivity. Proposed fix A minimal, single-file change to val baseConfig = new ConfigBuilder(autoConfigure(kubeContext.orNull))
.withApiVersion("v1")
// For the submission client, always use the configured spark.master as-is.
// This is important for both same-cluster and cross-cluster submissions.
//
// For the driver running inside Kubernetes, use the API server IP and port
// injected by Kubernetes via KUBERNETES_SERVICE_HOST / KUBERNETES_SERVICE_PORT.
// This avoids DNS resolution of kubernetes.default.svc and the associated
// ndots:5 search-domain lookups that cause NXDOMAIN responses on every API call.
//
// This only applies when spark.kubernetes.driver.master is not explicitly set.
// If the user has configured it, that value is respected as-is (existing behaviour).
val driverMasterExplicitlySet = sparkConf.contains(KUBERNETES_DRIVER_MASTER_URL.key)
val configWithMaster =
if (clientType == ClientType.Driver &&
sys.env.contains("KUBERNETES_SERVICE_HOST") &&
sys.env.contains("KUBERNETES_SERVICE_PORT") &&
!driverMasterExplicitlySet) {
val host = sys.env("KUBERNETES_SERVICE_HOST")
val port = sys.env("KUBERNETES_SERVICE_PORT")
val inClusterApiServer = s"https://$host:$port"
logInfo(
s"Running in-cluster driver; using Kubernetes API server $inClusterApiServer " +
"for Driver-to-API-server communication."
)
baseConfig.withMasterUrl(inClusterApiServer)
} else {
baseConfig.withMasterUrl(master)
}
val config = configWithMaster
.withRequestTimeout(...) // rest unchangedCompatibility All four conditions must be true for the fix to activate. If any one is false the code falls through to
Would the team be open to a PR for this against Best regards, |
What changes were proposed in this pull request?
Introduces a new config
spark.kubernetes.clusterDomain(default:cluster.local) and changesthe driver hostname constructed in
DriverServiceFeatureStepfrom a partial DNS name to afully-qualified domain name (FQDN) with a trailing dot:
Before:
After:
The trailing dot tells the DNS resolver to treat the name as absolute, bypassing the pod's
configured search domain list entirely.
Why are the changes needed?
When executors resolve
spark.driver.host, the standard Kubernetes pod DNS configuration usesndots:5with search domains:The existing partial hostname
<service>.<namespace>.svccontains only 2 dots, which is belowthe
ndots:5threshold. The resolver therefore attempts to resolve it by appending each searchdomain in turn, producing two NXDOMAIN responses before arriving at the correct address:
In production environments running many concurrent Spark pipelines, each executor startup
generates these spurious failed lookups. This adds unnecessary NXDOMAIN traffic to CoreDNS
(a shared cluster-wide component) and can contribute to delays during executor-to-driver
connection establishment.
Using a trailing-dot FQDN forces the resolver to issue a single absolute lookup, eliminating
all NXDOMAIN responses. The new
spark.kubernetes.clusterDomainconfig accommodates clustersthat use a non-default domain (i.e., something other than
cluster.local).Does this PR introduce any user-facing change?
Yes.
spark.driver.hostis now set to<service>.<namespace>.svc.cluster.local.by defaultinstead of
<service>.<namespace>.svc. This is backward compatible for standard clusters.Users on clusters with a non-default domain can configure
spark.kubernetes.clusterDomain.How was this patch tested?
The fix was validated by manually patching the jar and testing it in a local Kubernetes
development environment. The following scenarios were verified:
cluster.localdomain.