diff --git a/core/src/main/scala/org/apache/spark/deploy/security/HadoopFSDelegationTokenProvider.scala b/core/src/main/scala/org/apache/spark/deploy/security/HadoopFSDelegationTokenProvider.scala index 0dc6aa1d7e..5c98762d41 100644 --- a/core/src/main/scala/org/apache/spark/deploy/security/HadoopFSDelegationTokenProvider.scala +++ b/core/src/main/scala/org/apache/spark/deploy/security/HadoopFSDelegationTokenProvider.scala @@ -48,7 +48,12 @@ private[deploy] class HadoopFSDelegationTokenProvider creds: Credentials): Option[Long] = { try { val fileSystems = HadoopFSDelegationTokenProvider.hadoopFSsToAccess(sparkConf, hadoopConf) - val fetchCreds = fetchDelegationTokens(getTokenRenewer(hadoopConf), fileSystems, creds) + // The hosts on which the file systems to be excluded from token renewal + val fsToExclude = sparkConf.get(YARN_KERBEROS_FILESYSTEM_RENEWAL_EXCLUDE) + .map(new Path(_).getFileSystem(hadoopConf).getUri.getHost) + .toSet + val fetchCreds = fetchDelegationTokens(getTokenRenewer(hadoopConf), fileSystems, creds, + fsToExclude) // Get the token renewal interval if it is not set. It will only be called once. if (tokenRenewalInterval == null) { @@ -99,11 +104,18 @@ private[deploy] class HadoopFSDelegationTokenProvider private def fetchDelegationTokens( renewer: String, filesystems: Set[FileSystem], - creds: Credentials): Credentials = { + creds: Credentials, + fsToExclude: Set[String]): Credentials = { filesystems.foreach { fs => - logInfo(s"getting token for: $fs with renewer $renewer") - fs.addDelegationTokens(renewer, creds) + if (fsToExclude.contains(fs.getUri.getHost)) { + // YARN RM skips renewing token with empty renewer + logInfo(s"getting token for: $fs with empty renewer to skip renewal") + fs.addDelegationTokens("", creds) + } else { + logInfo(s"getting token for: $fs with renewer $renewer") + fs.addDelegationTokens(renewer, creds) + } } creds @@ -119,7 +131,7 @@ private[deploy] class HadoopFSDelegationTokenProvider val renewer = UserGroupInformation.getCurrentUser().getUserName() val creds = new Credentials() - fetchDelegationTokens(renewer, filesystems, creds) + fetchDelegationTokens(renewer, filesystems, creds, Set.empty) val renewIntervals = creds.getAllTokens.asScala.filter { _.decodeIdentifier().isInstanceOf[AbstractDelegationTokenIdentifier] diff --git a/core/src/main/scala/org/apache/spark/internal/config/package.scala b/core/src/main/scala/org/apache/spark/internal/config/package.scala index 6b1e3d0c07..d988e522c3 100644 --- a/core/src/main/scala/org/apache/spark/internal/config/package.scala +++ b/core/src/main/scala/org/apache/spark/internal/config/package.scala @@ -716,6 +716,18 @@ package object config { .toSequence .createWithDefault(Nil) + private[spark] val YARN_KERBEROS_FILESYSTEM_RENEWAL_EXCLUDE = + ConfigBuilder("spark.yarn.kerberos.renewal.excludeHadoopFileSystems") + .doc("The list of Hadoop filesystem URLs whose hosts will be excluded from " + + "delegation token renewal at resource scheduler. Currently this is known to " + + "work under YARN, so YARN Resource Manager won't renew tokens for the application. " + + "Note that as resource scheduler does not renew token, so any application running " + + "longer than the original token expiration that tries to use that token will likely fail.") + .version("3.2.0") + .stringConf + .toSequence + .createWithDefault(Nil) + private[spark] val EXECUTOR_INSTANCES = ConfigBuilder("spark.executor.instances") .version("1.0.0") .intConf diff --git a/docs/running-on-yarn.md b/docs/running-on-yarn.md index 797d18a0d4..72df64b3ef 100644 --- a/docs/running-on-yarn.md +++ b/docs/running-on-yarn.md @@ -699,6 +699,18 @@ staging directory of the Spark application. 2.3.0 + + spark.yarn.kerberos.renewal.excludeHadoopFileSystems + (none) + + A comma-separated list of Hadoop filesystems for whose hosts will be excluded from from delegation + token renewal at resource scheduler. For example, spark.yarn.kerberos.renewal.excludeHadoopFileSystems=hdfs://nn1.com:8032, + hdfs://nn2.com:8032. This is known to work under YARN for now, so YARN Resource Manager won't renew tokens for the application. + Note that as resource scheduler does not renew token, so any application running longer than the original token expiration that tries + to use that token will likely fail. + + 3.2.0 + ## Troubleshooting Kerberos diff --git a/docs/security.md b/docs/security.md index aef6e69382..a4ede9f05b 100644 --- a/docs/security.md +++ b/docs/security.md @@ -840,6 +840,9 @@ The following options provides finer-grained control for this feature: +Users can exclude Kerberos delegation token renewal at resource scheduler. Currently it is only supported +on YARN. The configuration is covered in the [Running Spark on YARN](running-on-yarn.html#yarn-specific-kerberos-configuration) page. + ## Long-Running Applications Long-running applications may run into issues if their run time exceeds the maximum delegation