Spark通过Kerberos连接MSSQL报错:无法找到Kerberos TGT
Spark连接MSSQL Kerberos认证失败问题排查与解决
问题场景
已通过keytab和principal在简单Java项目中成功建立MSSQL的Kerberos认证连接,但集成到Spark后出现认证失败,报错如下:
Caused by: java.security.PrivilegedActionException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:422) at com.microsoft.sqlserver.jdbc.KerbAuthentication.getClientCredential(KerbAuthentication.java:179) at com.microsoft.sqlserver.jdbc.KerbAuthentication.initAuthInit(KerbAuthentication.java:139) ... 47 more Caused by: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
现有配置与代码
jaas.conf配置
SQLJDBCDriver { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/home/spark/apacheservacc.keytab" storeKey=true useTicketCache=false principal="apacheservacc/xxx:1433@xxx" debug=true; };
spark-submit提交命令
spark-submit --driver-class-path /home/spark/mssql-jdbc-12.8.1.jre8.jar --jars /home/spark/mssql-jdbc-12.8.1.jre8.jar --conf "spark.driver.extraJavaOptions=-Djava.security.auth.login.config=/etc/jaas.conf" --conf "spark.executor.extraJavaOptions=-Djava.security.auth.login.config=/etc/jaas.conf" spark_kerberos_v2.py
PySpark代码
SparkSession创建
def create_spark_session(): spark = SparkSession.builder \ .appName("MSSQL Kerberos Connection") \ .master("yarn") \ .config("spark.submit.deployMode", "client") \ .config("spark.executor.instances", 4) \ .config("spark.default.parallelism", 8) \ .config("spark.jars", "/home/spark/mssql-jdbc-12.8.1.jre8.jar") \ .config("spark.executor.extraJavaOptions", "-Djava.security.auth.login.config=/etc/jaas.conf " "-Djava.security.krb5.conf=/etc/krb5.conf " "-Dsun.security.krb5.debug=true") \ .config("spark.driver.extraJavaOptions", "-Djava.security.auth.login.config=/etc/jaas.conf " "-Djava.security.krb5.conf=/etc/krb5.conf " "-Dsun.security.krb5.debug=true") \ .getOrCreate()
MSSQL连接函数
def connect_mssql_with_spark(spark, server, database, keytab_path, principal): jdbc_url = f"jdbc:sqlserver://{server}:1433;databaseName={database};encrypt=false;integratedSecurity=true;authenticationScheme=JavaKerberos" # Connection properties connection_properties = { "driver": "com.microsoft.sqlserver.jdbc.SQLServerDriver", "keytab": "/home/spark/apacheservacc.keytab", "principal": "apacheservacc/xxx:1433@xxx" } print(jdbc_url)
问题原因分析
- JAAS配置条目不匹配:MSSQL JDBC驱动默认使用的JAAS配置条目为
com.sun.security.jgss.krb5.initiate,当前配置的SQLJDBCDriver无法被驱动识别,导致无法加载正确的登录凭证。 - 配置重复与分发问题:SparkSession和spark-submit命令重复配置Java参数,可能引发冲突;同时未将JAAS、krb5配置文件分发到所有executor节点,导致executor无法读取配置。
- Principal格式错误:客户端principal不应携带端口,端口是MSSQL服务端SPN(
MSSQLSvc/[server]:1433@REALM)的组成部分,当前格式会导致凭证无法匹配服务端。 - Keytab文件可用性问题:executor节点上的keytab文件可能不存在或权限不足,导致无法读取凭证。
解决方案
1. 修正JAAS配置文件
将配置条目改为驱动默认的名称,同时修正客户端principal格式:
com.sun.security.jgss.krb5.initiate { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/home/spark/apacheservacc.keytab" storeKey=true useTicketCache=false principal="apacheservacc@xxx" debug=true; };
2. 统一Spark配置并分发文件
移除SparkSession代码中的Java参数配置,在spark-submit命令中统一指定,并添加文件分发配置:
spark-submit \ --driver-class-path /home/spark/mssql-jdbc-12.8.1.jre8.jar \ --jars /home/spark/mssql-jdbc-12.8.1.jre8.jar \ --conf "spark.driver.extraJavaOptions=-Djava.security.auth.login.config=/etc/jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true" \ --conf "spark.executor.extraJavaOptions=-Djava.security.auth.login.config=/etc/jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true" \ --conf "spark.yarn.dist.files=/etc/jaas.conf,/etc/krb5.conf,/home/spark/apacheservacc.keytab" \ spark_kerberos_v2.py
spark.yarn.dist.files会将指定文件分发到所有executor节点的工作目录,此时代码中路径需改为相对路径,或使用Spark提供的分布式路径变量。
3. 修正JDBC连接配置
移除URL中冗余参数,同时不再重复指定keytab和principal(由JAAS配置自动加载):
def connect_mssql_with_spark(spark, server, database): jdbc_url = f"jdbc:sqlserver://{server}:1433;databaseName={database};encrypt=false;authenticationScheme=JavaKerberos" connection_properties = { "driver": "com.microsoft.sqlserver.jdbc.SQLServerDriver" } # 执行读取示例 df = spark.read.jdbc(url=jdbc_url, table="your_target_table", properties=connection_properties) df.show()
4. 验证Kerberos基础环境
在Spark节点执行以下命令,确保凭证能正常获取:
# 使用keytab获取TGT kinit -kt /home/spark/apacheservacc.keytab apacheservacc@xxx # 查看凭证 klist
内容的提问来源于stack exchange,提问作者Bilge Kaan Gençdoğan
相关产品推荐
相关产品推荐

