Parth Chandra created SPARK-58438:
-------------------------------------

             Summary: HadoopDelegationTokenManager leaks FileSystem cache 
entries on every token renewal
                 Key: SPARK-58438
                 URL: https://issues.apache.org/jira/browse/SPARK-58438
             Project: Spark
          Issue Type: Bug
          Components: Spark Core
    Affects Versions: 4.2.0
            Reporter: Parth Chandra


{{{}HadoopDelegationTokenManager{}}}'s periodic token-renewal path creates a 
fresh
{{UserGroupInformation}} (UGI) on every renewal cycle but never releases the
{{FileSystem}} instances cached for that UGI, so entries accumulate in the 
static
{{FileSystem.CACHE}} for the lifetime of the driver JVM.
h4. Details

On each renewal cycle {{updateTokensTask()}} calls {{{}doLogin(){}}}, which 
returns a
*new* UGI in the two credential modes:
 * keytab: {{UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, 
keytab)}}
 * ccache: {{UserGroupInformation.getUGIFromTicketCache(ccache, user)}}

Providers invoked inside {{freshUGI.doAs

{ ... }

}} call {{{}FileSystem.get(...){}}}, which
caches {{FileSystem}} instances in {{FileSystem.CACHE}} keyed (in part) by the 
UGI.
Cache entries are only evicted by {{FileSystem.close}} / 
{{{}FileSystem.closeAllForUGI{}}}.
The renewal path never calls either, so each cycle leaves behind {{FileSystem}}
instances for a throwaway UGI that is never used again.

The one-shot path {{obtainDelegationTokens(creds)}} already cleans up correctly:
{code:scala}
  if (!currentUser.equals(freshUGI)) {
    FileSystem.closeAllForUGI(freshUGI)
  }
  {code}
but the equivalent cleanup is missing from {{obtainTokensAndScheduleRenewal}} /
{{{}updateTokensTask{}}}.
h4. Impact

Long-running applications that renew delegation tokens (keytab, or ccache-based
renewal) accumulate one UGI's worth of cached {{FileSystem}} handles per renewal
interval. With default settings the renewal interval is on the order of hours, 
so the
growth is slow, but it is unbounded and can lead to gradually increasing memory 
and
open file/connection usage (and eventually resource exhaustion) over the 
lifetime of a
driver that runs for days or weeks.

The proxy-user branch of {{doLogin()}} returns the shared {{getCurrentUser()}} 
and must
NOT be closed; the guard {{!currentUser.equals(freshUGI)}} correctly excludes 
it.
h4. Suggested fix

Mirror the one-shot path: after the renewal {{doAs}} completes, close the fresh 
UGI's
cached filesystems, guarded by {{!currentUser.equals(freshUGI)}} so the shared
current/proxy user is never closed.

Notes

Discovered during review of SPARK-38954 (PR #57285); it is a pre-existing issue 
in the
Kerberos renewal path and is being tracked separately per reviewer request so 
that
SPARK-38954 keeps the Kerberos paths unchanged.



--
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