Noufal Rijal created SPARK-58893:
------------------------------------

             Summary: Spark UI generates root-relative links in multi-cluster 
standalone deployments with path-based reverse proxy
                 Key: SPARK-58893
                 URL: https://issues.apache.org/jira/browse/SPARK-58893
             Project: Spark
          Issue Type: Bug
          Components: Spark Core, Web UI
    Affects Versions: 4.1.2, 4.2.0, 4.0.0
            Reporter: Noufal Rijal


h3. Problem

When multiple Spark standalone clusters are deployed behind a single reverse 
proxy using path-based routing (e.g., {{{}/spark-ui/\{cluster-name}/{}}}), the 
Spark UI is fully functional only for the first cluster. All other clusters 
produce 403 errors on tab navigation and lose CSS styling.

This regression exists even after SPARK-58521 (PR #57549) which added 
{{X-Forwarded-Context}} header forwarding.

*Configuration:*

{{spark.ui.reverseProxy=true
spark.ui.reverseProxyUrl=https://proxy.example.com/spark-ui/cluster-a}}
*Reverse proxy routing:*

{{/spark-ui/cluster-a/  →  cluster-a master:8080
/spark-ui/cluster-b/  →  cluster-b master:8080}}
*Observed behavior:*
 # Navigating to 
{{https://proxy.example.com/spark-ui/cluster-b/proxy/app-xxx/}} *redirects* to 
{{https://proxy.example.com/proxy/app-xxx/jobs/}} — missing the cluster prefix. 
The proxy cannot route this URL.

 # After the redirect, clicking any tab (SQL, Stages, Executors) generates 
links like {{href="/proxy/app-xxx/sql/"}} — root-relative, unroutable through 
path-based ingress.

h3. Root Cause (three separate bugs)

*Bug 1 — {{Master.createDriver}} does not propagate {{reverseProxyUrl}} to 
cluster-mode driver JVM*

In cluster deploy mode, the worker starts the driver as a subprocess (new JVM). 
{{SparkContext}} (line ~640) computes {{{}spark.ui.proxyBase = reverseProxyUrl 
+ "/proxy/" + appId{}}}. However, {{reverseProxyUrl}} is read from the driver's 
{{{}SparkConf{}}}, which does not contain it — the config only exists in the 
master/worker JVM, not in the submitted application's conf. As a result 
{{proxyBase}} is computed as {{/proxy/\{appId}}} (root-relative), and all 
driver UI links are root-relative.

*Bug 2 — {{JettyUtils.createProxyLocationHeader}} strips the cluster prefix 
from redirect {{Location}} headers*

When the browser first opens the driver UI root ({{{}/proxy/\{appId}{}}}), the 
driver returns a {{302}} to {{{}/jobs/{}}}. The master's 
{{filterServerResponseHeader}} rewrites this via {{createProxyLocationHeader}} 
to {{https://proxy.example.com/proxy/\{appId}/jobs/}} — which is correct for a 
single-cluster deployment but omits the {{/spark-ui/cluster-b/}} prefix in a 
multi-cluster path-routed setup. The browser follows the root-relative redirect 
and subsequent navigation is broken.

*Bug 3 — {{JettyUtils.createProxyHandler}} does not include {{reverseProxyUrl}} 
in {{X-Forwarded-Context}}*

SPARK-58521 added {{X-Forwarded-Context}} forwarding, but the header value is 
{{contextPath + prefix}} (e.g., {{{}/proxy/app-xxx{}}}) — a root-relative path. 
For the driver to generate correct absolute links via 
{{{}UIUtils.uiRoot(request){}}}, the header must contain the full URL including 
the cluster prefix: 
{{{}https://proxy.example.com/spark-ui/cluster-b/proxy/app-xxx{}}}. This 
matters for client-mode drivers that cannot receive the fix via 
{{{}javaOpts{}}}.
h3. Steps to Reproduce
 # Start two Spark standalone clusters with {{spark.ui.reverseProxy=true}} and 
distinct {{spark.ui.reverseProxyUrl}} values
 # Configure path-based routing so {{/spark-ui/cluster-a/}} and 
{{/spark-ui/cluster-b/}} route to their respective masters
 # Submit a streaming application to cluster-b in cluster deploy mode
 # Open the Spark master UI and click the driver application link
 # Observe the redirect URL loses the {{/spark-ui/cluster-b/}} prefix
 # Click any UI tab — observe root-relative URLs causing 403 errors



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to