问题概述
使用 Doris Hive Catalog 通过 Kerberos 访问 HDFS。BE 重启后查询可以正常运行,但运行超过 Kerberos TGT 的 24 小时有效期后,多个 BE 会陆续或同时无法读取 HDFS 文件,并出现以下错误链:
GSSException: No valid credentials provided
(Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))
javax.security.auth.login.LoginException: Cannot read from System.in
at com.sun.security.auth.module.Krb5LoginModule.promptForName(...)
此时在同一节点上使用同一个 principal 和 keytab 手工执行 kinit -kt 可以成功。滚动重启 BE 后,HDFS 查询立即恢复;再次运行超过约 24 小时后可能复现。
初步怀疑:Doris 4.1.2 的 BE/libhdfs 没有成功续期或重新获取 TGT,同时 HdfsMgr 持续复用已经失去有效 Kerberos 凭据的 HDFS Handler。
环境信息
| 项目 | 信息 |
|---|---|
| Doris | doris-4.1.2-rc01-aec169d2025 |
| 部署形态 | 多 FE、多 BE;多个 BE 均可复现 |
| BE JDK | JDK 17,JAVA_HOME=/opt/jdk17/ |
| Catalog | HMS/Hive Catalog |
| Hive Catalog 兼容版本 | hive.version=1.2.0 |
| HDFS | Kerberos + HA,fs.defaultFS=hdfs://<nameservice> |
| Hadoop/HDP 服务端版本 | 例如 HDP 2.6.5 / Hadoop 2.7.x |
| 操作系统 | CentOS7.9 |
| Kerberos principal | doris@<REALM> |
| keytab | /etc/security/keytabs/doris.keytab,所有参与查询的 BE 上路径一致且 BE 进程用户可读 |
| TGT 生命周期 | 24 小时 |
| renewable 生命周期 | 7 天 |
BE 使用的相关 JVM 参数:
-Djavax.security.auth.useSubjectCredsOnly=false
-Dsun.security.krb5.debug=true
Catalog 关键配置(已脱敏)
CREATE CATALOG `ctl_hive` PROPERTIES (
"type" = "hms",
"hive.version" = "1.2.0",
"hive.metastore.uris" = "thrift://<hms1>:9083,thrift://<hms2>:9083",
"hive.metastore.service.principal" = "hive/_HOST@<REALM>",
"hive.metastore.client.principal" = "doris@<REALM>",
"hive.metastore.client.keytab" = "/etc/security/keytabs/doris.keytab",
"hive.metastore.authentication.type" = "kerberos",
"hive.conf.resources" = "<resource-dir>/hive-site.xml",
"hdfs.authentication.type" = "kerberos",
"hdfs.authentication.kerberos.principal" = "doris@<REALM>",
"hdfs.authentication.kerberos.keytab" = "/etc/security/keytabs/doris.keytab",
"hadoop.config.resources" = "<resource-dir>/core-site.xml,<resource-dir>/hdfs-site.xml",
"fs.defaultFS" = "hdfs://<nameservice>"
);
/etc/krb5.conf 中相关配置:
[libdefaults]
ticket_lifetime = 24h
renew_lifetime = 7d
复现步骤
- 在所有可能参与外表扫描的 BE 上放置同一 principal 对应的 keytab,并确保 BE 进程用户可读。
- 创建上述 Kerberos Hive Catalog。
- 重启 BE,随后执行 Hive 外表查询,确认可以正常读取 HDFS。
- 持续或间歇执行查询,使 HDFS Handler 被创建并重复使用。
- 保持 BE 不重启,等待超过 TGT 的 24 小时有效期。
- 再次查询 Hive 外表。
实际生产时间线中的一次复现:
2026-10-13 22:00 多个 BE 完成滚动重启,查询正常
2026-10-14 22:00 按 24 小时有效期推算,重启时获取的 TGT 到期
2026-10-15 04:52 多个 BE 查询 HDFS 失败,出现 No valid credentials / Cannot read from System.in
实际结果
典型 BE 日志如下(主机名和 HDFS 路径已脱敏):
Reuse existing HDFS handler, is_kerberos=1,
principal=doris@<REALM>, fs_name=hdfs://<nameservice>
java.io.IOException: Failed on local exception:
javax.security.sasl.SaslException: GSS initiate failed
[Caused by GSSException: No valid credentials provided
(Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))]
Caused by: javax.security.auth.login.LoginException: Cannot read from System.in
at jdk.security.auth/com.sun.security.auth.module.Krb5LoginModule.promptForName(...)
at jdk.security.auth/com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(...)
对用户可见的查询错误:
[INTERNAL_ERROR] failed to open /<hdfs-path>/<file>: (255),
reason: LoginException: Cannot read from System.in
期望结果
Catalog 已显式配置 principal 和 keytab,BE 应当在 TGT 到期前:
- 使用 keytab 自动续期或重新登录并获取新 TGT;或者
- 在凭据失效时让旧 HDFS Handler 失效并重新创建;或者
- 至少返回明确的 Kerberos 续票/重新登录失败原因,而不是退化为交互式读取
System.in。
不应要求定期重启 BE 才能长期访问 Kerberos HDFS。
keytab、KDC 与 TGT 生命周期验证
故障期间/故障后,在受影响 BE 上使用相同 keytab 独立申请 TGT 成功:
CCACHE=/tmp/doris_tgt_check_$$
KRB5CCNAME=FILE:$CCACHE \
kinit -V -kt /etc/security/keytabs/doris.keytab 'doris@<REALM>'
KRB5CCNAME=FILE:$CCACHE klist -ef
KRB5CCNAME=FILE:$CCACHE kdestroy
实际签发结果:
Valid starting Expires Service principal
2026-10-15 09:45:38 2026-10-16 09:45:39 krbtgt/<REALM>@<REALM>
renew until 2026-10-22 09:45:39, Flags: FRI
因此可以确认:
- keytab 在故障时仍然有效;
- KDC 可以正常签发票据;
- 实际 TGT 有效期为 24 小时、renewable 窗口为 7 天;
- 独立
kinit只验证 keytab/KDC,不代表 BE 进程内部的凭据已刷新。
恢复与重复性
- 不修改 Catalog、不替换 keytab,仅滚动重启 BE 即可恢复。
- 多个 BE 均出现过同类错误,不是单节点磁盘或单文件损坏。
- 错误发生在不同 HDFS 文件/分区上,不是特定数据文件问题。
- 重启后的恢复具有重复性,因此当前只能通过小于 24 小时的周期性滚动重启规避。
4.1.2 源码中的可疑点
以下内容是基于 doris-4.1.2 源码的初步分析,尚不能单独证明根因,请社区协助确认设计意图。
1. 已设置 keytab 和自动续票开关,但 Doris 自有 ticket-cache 路径被注释
文件:be/src/io/hdfs_builder.cpp
hdfsBuilderSetPrincipal(builder->get(), builder->hdfs_kerberos_principal.c_str());
hdfsBuilderSetKerb5Conf(builder->get(), doris::config::kerberos_krb5_conf_path.c_str());
hdfsBuilderSetKeyTabFile(builder->get(), builder->hdfs_kerberos_keytab.c_str());
hdfsBuilderConfSetStr(builder->get(),
"hadoop.kerberos.keytab.login.autorenewal.enabled",
"true");
// RETURN_IF_ERROR(builder->set_kerberos_ticket_cache());
同文件中的 HDFSCommonBuilder::set_kerberos_ticket_cache() 实现主体也已整体注释,并标记为 deprecated。
希望确认:当前 Doris 构建使用的 libhdfs 是否确实支持并执行 hadoop.kerberos.keytab.login.autorenewal.enabled=true?续期失败时是否有可观测日志?
2. HDFS Handler 被持续复用,按 Kerberos 生命周期淘汰的代码被注释
文件:be/src/io/fs/hdfs/hdfs_mgr.cpp
bool is_expired = current\_time - entry.second->last_access_time >=
_instance_timeout_seconds;
// bool is_krb_expired =
// entry.second->is_kerberos_auth &&
// (current_time - entry.second->create_time >=
// entry.second->ticket_cache->get_ticket_lifetime_sec() / 2);
复用 Handler 时还会更新 last_access_time:
if (it != _fs_handlers.end()) {
it->second->update_access_time();
*fs_handler = it->second;
return Status::OK();
}
对于持续有查询的 Catalog,Handler 可能长期不会因为空闲超时被淘汰。如果其内部 Subject/TGT 没有更新,可能一直复用过期凭据。
当前结论边界
已确认
- 错误的直接原因是 BE 发起 HDFS Kerberos/GSS 认证时没有有效凭据。
- Java 随后尝试交互式登录并读取
System.in,后台 BE 无法提供输入,所以出现Cannot read from System.in。 - TGT 实际有效期为 24 小时、renewable 窗口为 7 天。
- 相同 keytab 可以独立成功执行
kinit -kt。 - 多个 BE 可复现,滚动重启 BE 可以恢复。
- 日志显示出错时正在
Reuse existing HDFS handler。
高度怀疑但尚未完全证实
- BE/libhdfs 没有成功执行 TGT 自动续期或 keytab 重新登录。
- 已缓存的 HDFS Handler/Java Subject 没有加载更新后的凭据。
hdfs_builder.cpp和hdfs_mgr.cpp中被注释的 ticket-cache/过期 Handler 逻辑与该现象有关。
尚缺少的证据
- 自动续票线程是否启动、何时执行、失败原因是什么。
- BE 内部实际使用的 ccache/Subject 与日志中显示的 cache path 的对应关系。
backend_kerberos_ticket_cache在该 HDFS Catalog 路径下是否应有记录。
当前临时规避方案
由于生产 TGT 只有 24 小时,目前使用带安全门禁的 BE 滚动重启:
- 每 30 分钟检查一次;
- 距离上次完整成功满 18 小时才实际滚动重启;
- Tablet 健康检查不通过时不使用
--force-health,保留安全门禁并在下次调度重试; - 仅全部 BE 重启成功后才更新成功时间。
该方案会带来运维复杂度和周期性服务扰动,只是临时规避,不是问题修复。
希望社区协助确认的问题
- Doris 4.1.2 中 Hive Catalog/HDFS Kerberos 的预期自动续票机制是什么?
hadoop.kerberos.keytab.login.autorenewal.enabled=true在 Doris 自带的 libhdfs/JDK 17 路径中是否有效?set_kerberos_ticket_cache()及按 ticket 生命周期淘汰 HDFS Handler 的代码为什么被注释?这是暂未完成的功能、已废弃方案,还是由其他机制替代?- 是否存在已知 Issue、修复 PR 或包含修复的版本?
- 能否在 GSS
No valid credentials后使当前 HDFS Handler 失效,并使用 Catalog 中的 keytab 重新创建连接? - 社区还需要哪些日志或诊断参数来确认自动续票是否执行?