我正在尝试在 Kubernetes 上运行 Spark,目的是处理来自 Kerberized Hadoop 集群的数据。我的应用程序由简单的 SparkSQL 转换组成。虽然我能够在单个驱动程序 Pod 上成功运行该进程,但在尝试使用任何执行程序时却无法执行此操作。相反,我得到:
org.apache.hadoop.security.AccessControlException:简单
未启用身份验证。可用:[令牌、KERBEROS]
由于 Hadoop 环境是 Kerberized,因此我提供了有效的密钥表,以及 core-site.xml、hive-site.xml、hadoop-site.xml、mapred-site.xml 和yarn-site.xml,以及docker 镜像内的 krb5.conf 文件。
我使用以下方法设置环境设置:
trait EnvironmentConfiguration {
def configureEnvironment(): Unit = {
val conf = new Configuration
conf.set("hadoop.security.authentication", "kerberos")
conf.set("hadoop.security.authorization", "true")
conf.set("com.sun.security.auth.module.Krb5LoginModule", "required")
System.setProperty("java.security.krb5.conf", ConfigurationProperties.kerberosConfLocation)
UserGroupInformation.loginUserFromKeytab(ConfigurationProperties.keytabUser, ConfigurationProperties.keytabLocation)
UserGroupInformation.setConfiguration(conf)
}
我还通过以下方法传递 *-site.xml 文件:
trait SparkConfiguration {
def createSparkSession(): SparkSession = {
val spark = SparkSession.builder
.appName("MiniSparkK8")
.enableHiveSupport()
.master("local[*]")
.config("spark.sql.hive.metastore.version", ConfigurationProperties.hiveMetastoreVersion)
.config("spark.executor.memory", ConfigurationProperties.sparkExecutorMemory)
.config("spark.sql.hive.version", ConfigurationProperties.hiveVersion)
.config("spark.sql.hive.metastore.jars",ConfigurationProperties.hiveMetastoreJars)
spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.coreSiteLocation))
spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.hiveSiteLocation))
spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.hdfsSiteLocation))
spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.yarnSiteLocation))
spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.mapredSiteLocation))
}
}
我使用以下 Spark-submit 命令运行整个过程:
spark-submit ^
--master k8s://https://kubernetes.example.environment.url:8443 ^
--deploy-mode cluster ^
--name mini-spark-k8 ^
--class org.spark.Driver ^
--conf spark.executor.instances=2 ^
--conf spark.kubernetes.namespace=<company-openshift-namespace> ^
--conf spark.kubernetes.container.image=<company_image_registry.image> ^
--conf spark.kubernetes.driver.pod.name=minisparkk8-cluster ^
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark ^
local:///opt/spark/examples/target/MiniSparkK8-1.0-SNAPSHOT.jar ^
/opt/spark/mini-spark-conf.properties
上述配置足以让我的 Spark 应用程序运行并成功连接到 Kerberized Hadoop 集群。尽管 Spark Submit 命令声明创建了两个执行器 Pod,但这并没有发生,因为我已将 master 设置为local[*]
。因此,只创建了一个 pod,它能够连接到 Kerberized Hadoop 集群并成功在 Hive 表上运行我的 Spark 转换。
但是,当我删除.master(local[*])
,创建了两个执行器 Pod。从日志中可以看到这些执行器已成功连接到驱动程序 Pod,并且它们被分配了任务。此后不久,它们都会因上述错误而失败,导致失败的执行器 Pod 被终止。
尽管执行者已经拥有所有必要的文件来创建与其映像内的 Kerberized Hadoop 的成功连接。我相信执行者没有使用密钥表,如果他们运行 JAR,他们就会这样做。相反,他们正在运行驱动程序分配给他们的任务。
我可以从日志中看到驱动程序设法使用用户的密钥表正确地验证自身,USER123
:
信息 SecurityManager:54 - SecurityManager: 身份验证已禁用;
ui acl 已禁用;具有查看权限的用户:Set(spark, USER123);
具有查看权限的组:Set();具有修改权限的用户:
设置(火花,USER123);具有修改权限的组:Set()
另一方面,您从执行程序的日志中得到以下内容,您可以看到该用户 USER123 未经过身份验证:
信息 SecurityManager:54 - SecurityManager: 身份验证已禁用;
ui acl 已禁用;具有查看权限的用户:Set(spark);团体
具有查看权限:Set();具有修改权限的用户:
设置(火花);具有修改权限的组:Set()
我查看了各种来源,包括here。它提到HIVE_CONF_DIR
需要定义,但我可以从我的程序(打印环境变量)中看到该变量不存在,包括当驱动程序 Pod 设法对自身进行身份验证并正常运行 Spark 进程时。
我尝试在之前的 Spark-submit 命令中添加以下内容来运行:
--conf spark.kubernetes.kerberos.enabled=true ^
--conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf ^
--conf spark.kubernetes.kerberos.keytab=/var/keytabs/USER123.keytab ^
--conf spark.kubernetes.kerberos.principal=USER123@REALM ^
但这没有什么区别。
我的问题是:如何让执行者使用图像中的密钥表对自己进行身份验证?我希望这将使他们能够执行委托的任务。