跳转至

Vertica 与 Kerberos 认证集成原理 —— 从协议到配置到故障排查

作者:JiangChong | 撰写时间:2026-06-11

适用场景:你需要配置 Vertica 的 Kerberos 认证,或排查 Kerberos 相关的登录失败、HDFS 访问异常、Eon 数据库启动故障;或者你需要搞清楚「用户通过 Kerberos 登录后从 HDFS COPY 数据」这条最常见业务链路的完整认证流程。

关联文章:

  • Vertica集成Kerberos配置 — 完整配置步骤(某金融机构案例)
  • Kerberos故障排查方法论 — 13 条 Kerberos 故障排查方法论
  • FI环境Eon数据库Kerberos部署 — Eon + FI + Kerberos 完整流程

理解全文脉络:第 1 节用一次 vsql 登录讲清楚 Kerberos 协议的核心机制,第 2 节深入 Vertica 的集成架构——其中 §2.5 走读了「Kerberos 用户 COPY HDFS 数据」这条最常用业务链路的完整六阶段流程和全链路时序,第 3 节比对三种 Principal 的身份差异,第 4 节是配置全景,第 5 节按故障现象给出排查路径。如果你正在处理紧急故障,可以直接跳第 5 节按现象匹配;如果你想理清整体设计,建议按顺序读。


1. Kerberos 协议速览 —— 一次 vsql 登录的全过程

在理解 Vertica 如何集成 Kerberos 之前,需要先用最短路径搞懂 Kerberos 协议本身在做什么。

1.1 从一个问题开始

如果你用密码登录 Vertica:

$ vsql -h node1 -U bob -w mypassword

密码以哈希形式在网络上传送,数据库验证哈希后放行。这个方案的问题不是密码被窃听(可以用 TLS 加密传输),而是一个更根本的问题:bob 的密码要存储在哪里? 如果存在 Vertica 自己的系统表里,那就多了一个可以被攻击的密码库。如果每个外部系统(Vertica、Hadoop、Hive……)都自己存一份 bob 的密码,安全面就变成了安全漏洞面。

Kerberos 解决这个问题的思路是:bob 只在一个地方证明自己的身份(KDC),其他地方靠「门票」通行。就像你去机场,只在安检口出示一次身份证,之后登机牌就是你的临时凭证。

1.2 三个角色

Kerberos 协议涉及三方,必须先把角色认清楚,否则后面每一步都会混淆:

角色 是什么 在 Vertica 场景中对应谁
Client 请求访问服务的一方 执行 vsql 的用户 bob
KDC(Key Distribution Center) trusted third party,负责验明身份和发门票 MIT KDC / Active Directory / Huawei FI 中的 Kerberos 服务
Service Server 提供服务的一方 Vertica 数据库节点

KDC 内部又分两个子服务:

  • AS (Authentication Service):负责初始身份验证,发 TGT
  • TGS (Ticket Granting Service):负责根据 TGT 发 Service Ticket

你可以把 KDC 理解成一个同时兼办「入境身份审核」和「国内航班值机」的机构——AS 确认你是谁,TGS 给你办具体航班的登机牌。

1.3 三步认证

以下是一次 vsql -K node1.example.com -h node1 -U bob 的完整认证流程:

CLIENT (bob)                    KDC (AS + TGS)                   VERTICA (node1)
     │                                │                                │
     │──── KRB_AS_REQ ───────────────>│                                │
     │  "我是 bob@EXAMPLE.COM"         │                                │
     │<─── KRB_AS_REP ────────────────│                                │
     │  TGT + Session Key 1           │                                │
     │  (TGT 用 TGS 密钥加密)           │                                │
     │                                │                                │
     │──── KRB_TGS_REQ ──────────────>│                                │
     │  TGT + "我要访问 vertica/"      │                                │
     │         "node1.example.com"    │                                │
     │<─── KRB_TGS_REP ───────────────│                                │
     │  Service Ticket + Session Key 2│                                │
     │  (ST 用 vertica 密钥加密)        │                                │
     │                                │                                │
     │──── KRB_AP_REQ ────────────────────────────────────────────────>│
     │  Service Ticket + Authenticator                                 │
     │<─── KRB_AP_REP ─────────────────────────────────────────────────│
     │  确认消息                                                        │
     │                                                                 │
     │  ✅ 连接建立,开始执行 SQL                                         │

第 1 步:获取 TGT(AS Exchange)

Bob 执行 kinit bob@EXAMPLE.COM,输入密码。客户端用 bob 的密码派生出密钥,向 KDC 的 AS (Authentication Service) 发送 KRB_AS_REQ

KDC 验证 bob 的身份后,返回两样东西:

  • TGT:用 TGS 专用密钥加密的「临时身份证」,bob 自己读不了里面的内容
  • Session Key 1:用 bob 的密码密钥加密,bob 可以解密

bob 的密码全程没有在网络上传送。AS (Authentication Service) 能验证 bob,是因为它自己也存了一份 bob 的密码哈希,可以派生出相同的密钥。

第 2 步:获取 Service Ticket(TGS Exchange)

Bob 把读不了的 TGT 原样转发给 TGS,并附上一个用 Session Key 1 加密的 Authenticator(包含 bob 的身份和时间戳),告诉 TGS:「我要访问 vertica/node1.example.com@EXAMPLE.COM」。

TGS 用自己的密钥解密 TGT → 拿到 Session Key 1 → 解密 Authenticator → 确认 bob 就是 TGT 的合法持有者。然后生成:

  • Service Ticket:用 vertica 服务密钥加密(bob 读不了)
  • Session Key 2:用 Session Key 1 加密返回给 bob

第 3 步:向 Vertica 出示门票(AP Exchange)

Bob 把读不了的 Service Ticket 原样转发给 Vertica,附上新的 Authenticator(用 Session Key 2 加密)。

Vertica 用自己的 keytab 文件(存储了 vertica/node1.example.com@EXAMPLE.COM 的密钥)解密 Service Ticket → 拿到 Session Key 2 → 解密 Authenticator → 验证身份 → 返回确认。

三层密钥递进是 Kerberos 安全模型的核心

密钥 加密了什么 谁能解密
bob 的密码派生密钥 AS 返回的 Session Key 1 bob 和 KDC
TGS 专用密钥 TGT 只有 KDC 的 TGS
vertica 服务密钥(在 keytab 中) Service Ticket 只有 Vertica
Session Key 2(在 Service Ticket 中) bob 的 Authenticator Vertica(解密 ST 后获取)

来源:Kerberos 三阶段认证流程参考 kerberos.org 官方教程(kerberos.org/software/tutorial.html),已逐项对照验证;Vertica 集成的具体行为来自 Vertica 26.2 官方文档 Security & Authentication 章节。

1.4 Kerberos 解决的是什么问题

回到原来的场景:bob 不需要在 Vertica 里存密码。Vertica 不需要知道 bob 的密码是什么——它只需要知道 vertica/node1@EXAMPLE.COM 的密钥(存放在 keytab 文件里),能解密 Service Ticket 就行。bob 是谁、密码对不对,这些由 KDC 说了算。

这就是 Kerberos 的核心价值:把认证(你是谁)从服务(你能用我吗)中分离出来


2. Vertica 的集成架构

2.1 集成点:GSSAPI

Vertica 不是直接调用 Kerberos 协议的 C 库函数(krb5_*),而是通过 GSSAPI(Generic Security Services Application Programming Interface)这个标准接口。

GSSAPI 是一个安全编程接口标准(RFC 2743),它在应用程序和具体的安全机制(Kerberos、SPNEGO 等)之间插了一层抽象。应用程序只和 GSSAPI 对话,GSSAPI 再去调用底层的 Kerberos 库。

Vertica 进程
    ├── GSSAPI 层 (libgssapi_krb5)
    │       │
    │       ├── krb5 库 (libkrb5)
    │       │       │
    │       │       ├── 读 /etc/krb5.conf 获取 KDC 地址和 realm 配置
    │       │       ├── 读 KerberosKeytabFile 获取服务密钥
    │       │       └── 管理 ticket cache 文件
    │       │
    │       └── GSSAPI 协议消息 (KRB_AP_REQ / KRB_AP_REP)
    ├── 客户端连接处理
    └── 后台进程 (Tuple Mover, Eon 公共存储访问)

Vertica 用 CREATE AUTHENTICATION ... METHOD 'gss' 创建 GSS 认证记录:

CREATE AUTHENTICATION v_kerberos METHOD 'gss' HOST '0.0.0.0/0';
ALTER AUTHENTICATION v_kerberos ENABLE;
GRANT AUTHENTICATION v_kerberos TO bob;

来源:Vertica 26.2 文档 Security & Authentication > Client Authentication > Kerberos Authentication。

2.2 两种认证方向

Vertica 与 Kerberos 的交互不是只有「客户端连接数据库」这一个方向。实际上它有两类完全不同的场景:

方向 1:入站认证(Inbound)—— 客户端连接 Vertica

bob@client  →  KDC  →  bob 拿到 TGT  →  bob 请求 Service Ticket for "vertica/node1"
             →  bob 把 ST 发给 Vertica  →  Vertica 用 keytab 解密 ST  →  接受连接

这是标准的 Kerberos client-server 模式:Vertica 是 acceptor,被动接受客户端出示的 Service Ticket。

方向 2:出站认证(Outbound)—— Vertica 访问外部服务

Vertica (Tuple Mover)  →  用 keytab 中的 principal 向 KDC 获取 TGT
                       →  用 TGT 获取 HDFS 的 Service Ticket
                       →  用 ST 访问 HDFS(读写 ROS 数据、公共存储)

这是 Vertica 作为 initiator,主动去向 Hadoop/HDFS 证明自己的身份。

来源:Vertica 26.2 文档 Hadoop Integration > Using Kerberos with Vertica。

这两类场景使用同一个 keytab,但使用的场景不同。理解了这一点,才能明白为什么 keytab 配置不对会导致「客户端能登录,但 Tuple Mover 不工作」或反过来。

这两类场景在实际生产中通常是同一条业务链路的两个阶段——用户先通过入站认证登录,再执行 COPY/EXPORT 触发出站认证。完整走读见 §2.5。

2.3 接入与运行链路分离

一个关键的架构事实——也是许多故障的根因——Vertica 在 Kerberos 环境下的运行依赖两条独立的链路,当它们不一致时,会出现表象矛盾的问题:

链路 1:数据库接入链路(session 级别)
  vsql/ODBC/JDBC 客户端 → KDC → 客户端获取 TGT
                         → 请求 Service Ticket for "vertica/node"
                         → Vertica 用 keytab 解密 → 会话建立

链路 2:数据库运行链路(涉及 HDFS 的查询和后台操作)
  用户发起的操作(COPY/SELECT FROM 外表):
    客户端用户在会话建立时提供的 Kerberos ticket
      → Vertica 用它换取 Hadoop delegation token
        → 以用户身份访问 HDFS

  系统后台操作(Tuple Mover、Eon 公共存储、CREATE LOCATION):
    Vertica 用 keytab 向 KDC 获取 TGT
      → 用 keytab principal 换取 Hadoop token
        → 以 vertica/<hostname>@REALM 身份访问 HDFS

两条链路的关键差异不在于「用什么票据」——而在于「票据从哪里来」。链路 1 只涉及客户端 ↔ Vertica,链路 2 涉及 Vertica ↔ Hadoop,且链路 2 内部又根据「谁发起的操作」分为两种子路径:

接入链路 运行链路(用户操作) 运行链路(系统操作)
票据来源 客户端用户 kinit 的 ticket cache 客户端用户的 Kerberos ticket(会话建立时自动取走) keytab 内部 kinit 生成的 ticket cache
HDFS 上看到的身份 N/A 客户端用户(如 bob) keytab principal(如 vertica/node1)
失败表现 vsql 登录报 GSSAPI error 用户能登录但 COPY/SELECT FROM 外表报错 Tuple Mover 报错、Eon 启动卡住
配置依赖 CREATE AUTHENTICATION ... METHOD 'gss' + GRANT 客户端有有效 TGT + 用户对 HDFS 有权限 KerberosKeytabFile + KerberosServiceName + KerberosRealm

这个分离解释了最常见的「诡异现象」:客户端能正常 vsql 登录(链路 1 正常),但执行 SELECT * FROM hdfs_table 时报认证错误。可能的原因有二:① 客户端用户对 HDFS 没有权限(运行链路-用户操作子路径失败);② Tuple Mover 等系统进程报错(运行链路-系统操作子路径失败)。详见 §2.5 和 §5。

来源:此结论来自某通信运营商 2020-06-25 故障中观察到的现象——parallelexport() 到 HDFS 失败但 COPY FROM webhdfs 正常,根因在于运行链路中的用户操作子路径使用了节点上已失效的用户票据。见 HDFS导出数据失败案例分析。

2.4 内部 Ticket 管理机制

Vertica 不需要外部 crontab 来 kinit。官方文档明确说明(Vertica 26.2 文档 Hadoop Integration):

"After you configure the keytab file, the database uses the principal residing there to automatically obtain and maintain a Kerberos ticket, much as in the client scenario. In this case, the client does not interact with Kerberos."

具体行为,可以从 KERBEROS_CONFIG_CHECKEXTERNAL_CONFIG_CHECK 函数的输出中推断:

[INFO] KerberosCredentialCache [/tmp/vertica_D4/vertica450676899262134963.cc]

Vertica 在进程启动时:

  1. 读取配置参数 KerberosKeytabFile(如 /etc/krb5.keytab
  2. 读取 KerberosServiceName(如 vertica)和 KerberosRealm(如 EXAMPLE.COM
  3. keytab 中找到匹配 vertica/<hostname>@EXAMPLE.COM 的 principal
  4. 内部调用 kinit -k -t <keytab> <principal> 生成 ticket cache
  5. Ticket cache 存放在 /tmp/vertica_<随机后缀>/vertica<数字ID>.cc

Ticket cache 的路径是 Vertica 自动生成的,格式为 /tmp/vertica_XXXX/vertica<NUMBER>.cc。这意味着:

  • /tmp 目录的权限不能限制 dbadmin 用户创建子目录
  • ticket cache 生命周期与 Vertica 进程绑定
  • 进程重启时重新生成新的 cache 文件

本库真实案例:某金融机构某次重启后正常,是因为 /tmp 目录权限被修改导致 Vertica 无法创建 ticket cache 子目录,数据库票据凭证缓存没生成。来源:Kerberos故障排查方法论 第 9 条

关于 Ticket 刷新——关键区分

Vertica 有两类不同的 TGT,刷新能力完全不同:

keytab TGT(系统进程用) 用户 TGT(用户会话用)
生成方式 Vertica 启动时用 keytab 内部 kinit 用户 kinit(或 AD 登录时自动获取)
谁控制刷新 Vertica 可以自动续期 只有用户自己可以续期kinit -R 或重新 kinit
相关参数 KerberosTicketDuration 控制有效期 取决于用户 kinit 的参数或 KDC 配置
过期后果 Vertica 能自动续期 → 无影响 Hadoop token 刷新时发现用户 TGT 已过期 → 只能报错

Hadoop Token 层面是统一处理的:Vertica 用 HadoopFSTokenRefreshFrequency 控制自动刷新频率(单位:秒)。但刷新 token 时,如果用的是用户 TGT 路径而用户 TGT 已过期,刷新必然失败。这就是 §2.5 阶段 4 描述的 ETL 长任务中断的根因。

Delegation Token:如果是外部传入的 delegation token(HadoopImpersonationConfig 中的 token 字段),Vertica 不会也无法自动刷新——必须由外部调用方管理。

来源:Vertica 26.2 文档 Kerberos Parameters + Hadoop Integration > Token Expiration。

2.5 典型业务场景走读:Kerberos 用户从 HDFS 导入数据的全链路

前面 2.2 节区分了入站和出站两个独立的认证方向,但在实际生产中它们往往是同一次操作的两段。以下是最常见场景的完整走读:

场景:Bob 是 Kerberos 用户,通过 vsql 登录 Vertica,执行 COPY FROM webhdfs://... 从 Kerberized HDFS 加载数据。

阶段 1:Bob 获取 TGT(客户端本地操作)

$ kinit bob@EXAMPLE.COM
Password for bob@EXAMPLE.COM:

Bob 输入密码,KDC 返回 TGT,缓存在 Bob 本地的 ticket cache(默认 /tmp/krb5cc_<UID> 或由 KRB5CCNAME 环境变量指定)。

阶段 2:Bob 连接 Vertica(入站认证)

$ vsql -K node1.example.com -h node1 -U bob

发生 §1.3 描述的三步认证:

  1. Bob 向 KDC 请求 vertica/node1.example.com@EXAMPLE.COM 的 Service Ticket
  2. Bob 把 Service Ticket 发给 Vertica
  3. Vertica 用自己的 keytab 解密验证 → 会话建立

此时 Bob 在 Vertica 内有了一个 Kerberos 认证的会话。可以查询 sessions 表验证:

SELECT client_authentication_name, authentication_method FROM sessions;
-- 返回:v_kerberos | GSS-Kerberos

阶段 3:Bob 执行 COPY FROM HDFS(出站认证的关键转折)

COPY target_table FROM 'webhdfs://hacluster/data/source.parquet' PARQUET;

这是最容易产生理解偏差的地方。COPY 语句执行时,谁去 HDFS 读文件?

答案是:取决于是否启用了用户模拟(user impersonation)。有两种模式:

模式 A:用户模拟模式(默认,也是最常见的情况)

Vertica 在会话建立时自动取走了 Bob 的 Kerberos ticket(§2.2 方向 2 中描述的 User Authentication),用这张 ticket 向 Hadoop NameNode 换取一个 Hadoop Delegation Token

Bob 的 Kerberos TGT
  → Vertica 用 Bob 的身份向 NameNode 请求 delegation token
    → NameNode 返回 token(有效期通常数小时到数天)
      → Vertica 用这个 token 访问 HDFS 上的文件

来源:Vertica 26.2 文档:"At the beginning of a client session, the database automatically retrieves this ticket. The database then uses this ticket to get a Hadoop token, which Hadoop uses to grant access."

关键点:

  • HDFS 的审计日志中显示的访问者是 Bob(不是 vertica 也不是 dbadmin
  • HDFS 上的文件权限需要授权给 Bob 这个 principal
  • Token 过期后,Vertica 自动用 Bob 的 Kerberos ticket 续期(如果 ticket 还有效的话)

模式 B:数据库 keytab 模式(用于后台系统进程)

如果未启用用户模拟(或操作由 Tuple Mover、Eon 公共存储访问等后台进程触发),Vertica 使用 keytab 中的 vertica/<hostname>@REALM principal 去做认证:

Vertica 用 keytab principal 的 TGT
  → 向 NameNode 请求 delegation token(以 vertica/<hostname>@REALM 的身份)
    → 用这个 token 访问 HDFS

此时 HDFS 审计日志中的访问者是 vertica/<hostname>@REALM。这解释了为什么在 FI 环境中,数据库启动时需要把公共存储目录 chown 给 vertica 用户(见 FI环境Eon数据库Kerberos部署)。

两种模式的适用场景对比

用户模拟模式(User Authentication) 数据库 keytab 模式(Database Authentication)
触发条件 用户发起的查询、COPY、SELECT FROM 外部表 Tuple Mover、Eon 公共存储读写、CREATE LOCATION
HDFS 上看到的用户 客户端用户(如 bob) keytab principal(如 vertica/node1)
权限管理 按用户粒度授权(bob 能读哪些文件) 所有系统操作统一用同一个 principal
配置方式 自动(只要客户端有 Kerberos ticket) KerberosKeytabFile + KerberosServiceName + KerberosRealm
故障表现 用户能登录但 COPY 报错 → 用户对 HDFS 无权限 Tuple Mover 报错 → keytab 或 principal 配置问题

阶段 4:Token 过期与自动刷新

COPY 操作可能持续数小时。Hadoop delegation token 有自己的有效期(由 Hadoop 集群配置决定)。Vertica 的处理:

如果 token 年龄 > HadoopFSTokenRefreshFrequency
  → 在下次 HDFS 访问前自动请求新 token
    → 如果 Bob 的 Kerberos ticket 已过期
      → 刷新失败 → COPY 中断

这就是长期运行的 ETL 任务最常见的失败模式:Bob 的 Kerberos ticket 有效期只有 10 小时(Kerberos 默认值),但 ETL 任务跑了 12 小时。中途 Hadoop token 过期,Vertica 尝试续期时发现 Bob 的 ticket 也过期了,导致 COPY 中断。

阶段 5:EXPORT 的方向相同但认证链路略有差异

EXPORT TO webhdfs://... 是写操作,认证流程与 COPY(读)基本一致,但有一个额外的坑:

  • 读操作(COPY FROM / SELECT FROM 外表):只需要 HDFS 的 READ 权限
  • 写操作(EXPORT TO webhdfs / parallelexport()):需要 HDFS 的 WRITE 权限
  • 如果使用 parallelexport(),该函数内部调用 Hadoop fs -put,使用的是节点上当前有效的 ticket cache。如果运行链路的票据过期(比如因为外部 crontab 刷新失败),parallelexport() 直接失败

来源:某通信运营商 2020-06-25 故障中,parallelexport() 导出到 HDFS 失败但 COPY FROM webhdfs 正常,因为导出需要验证节点上的 USER_A 用户票据,而该票据因 dbadmin 口令过期导致 crontab 刷新失败而失效。同时远程 ETL 服务器上执行的 COPY FROM webhdfs 使用的是 ETL 服务器本地有效的票据文件,未受影响。见 HDFS导出数据失败案例分析。

阶段 6:HadoopConfDir 的决定性作用

整个阶段 3 能跑通的前提是 Vertica 知道 Hadoop 的配置。HadoopConfDir 参数指定了 Hadoop 配置文件(core-site.xmlhdfs-site.xml)的路径。这个参数容易踩的坑

  • 路径冲突:生产环境可能有两套 Hadoop 配置(一套普通、一套 Kerberized)。HadoopConfDir 如果只包含非 Kerberized 的路径,Vertica 会用非 Kerberos 方式访问 HDFS → 报 403
  • 复活陷阱:Eon 复活时,bootstrap_params.conf 中的 HadoopConfDir直接替换数据库的 HadoopConfDir 值。如果原来包含 Kerberized 路径,复活后只保留了 bootstrap 中的值,导致 Kerberos 配置丢失

来源:FI环境Eon数据库Kerberos部署 总结第 3 点。

全链路时序图

BOB_CLIENT              KDC                VERTICA              HADOOP_NAMENODE         HDFS_DATANODE
    │                    │                    │                       │                      │
    │── kinit ──────────>│                    │                       │                      │
    │<── TGT ────────────│                    │                       │                      │
    │                    │                    │                       │                      │
    │── KRB_TGS_REQ ────>│                    │                       │                      │
    │  "我要vertica/"     │                    │                       │                      │
    │   "node1.example"  │                    │                       │                      │
    │<── Service Ticket ─│                    │                       │                      │
    │                    │                    │                       │                      │
    │── vsql + ST ───────────────────────────>│                       │                      │
    │<── 会话建立 ─────────────────────────────│                       │                      │
    │                    │                    │                       │                      │
    │── COPY FROM webhdfs ───────────────────>│                       │                      │
    │                    │                    │                       │                      │
    │                    │                    │── 会话启动时已取走       │                      │
    │                    │                    │   Bob的TGT            │                      │
    │                    │                    │                       │                      │
    │                    │                    │── GETDELEGATIONTOKEN ─>│                     │
    │                    │                    │   (以Bob的身份)        │                      │
    │                    │                    │<── Delegation Token ──│                      │
    │                    │                    │                       │                      │
    │                    │                    │── 读数据(带DT) ───────────────────────────────>│
    │                    │                    │<── 数据块 ────────────────────────────────────│
    │                    │                    │                       │                      │
    │<── COPY完成 ─────────────────────────────│                       │                      │
    │                    │                    │                       │                      │
    │  [... 数小时后 token 即将过期 ...]         │                       │                      │
    │                    │                    │── 自动刷新DT ─────────>│                      │
    │                    │                    │<── 新DT ──────────────│                      │
    │                    │                    │   (如果Bob的TGT还有效)  │                      │

一句话总结这个场景

Vertica 是 Bob 和 HDFS 之间的「票据翻译官」——Bob 用 Kerberos 跟 Vertica 对话(彼此认可),Vertica 把 Bob 的 Kerberos 身份转换成 Hadoop 能理解的 Delegation Token,然后用这个 Token 替 Bob 去 HDFS 取数据。整个过程中 Bob 不需要自己去接触 KDC 以外的任何认证环节。


3. 关键对象与身份体系

3.1 三种 Principal

一个 Kerberized Vertica 集群涉及三种不同的 Kerberos principal,它们代表完全不同的身份:

Principal 类型 格式 用途 存储位置
服务 Principal vertica/hostname@REALM Vertica 作为服务的身份。客户端请求 Service Ticket 时指定此名称;后台进程用它访问 Hadoop keytab 文件
主机 Principal host/hostname@REALM 机器本身的 OS 级身份,用于 SSH、PAM 登录验证等系统级 GSSAPI 交互 keytab 文件
用户 Principal username@REALM 使用 Vertica 的终端用户身份 用户本地 ticket cache(通过 kinit 获取)

比喻:服务 principal 是你的「工牌」(证明你是公司员工),主机 principal 是你的「身份证」(证明你是这个国家的公民),用户 principal 是访客的「临时通行证」。

3.2 服务 Principal 与主机 Principal 的关系

官方文档(Vertica 26.2)在 Linux KDC 配置流程中只明确要求创建 vertica/ 服务 principal,但所有本库生产部署都同时创建两者并放入同一个 keytab:

# 服务票据(Vertica 应用身份)
addprinc vertica/node1.example.com@EXAMPLE.COM

# 主机票据(OS 级机器身份)
addprinc host/node1.example.com@EXAMPLE.COM

# 导出到同一个 keytab
xst -k /tmp/vertica.keytab \
    vertica/node1.example.com@EXAMPLE.COM \
    host/node1.example.com@EXAMPLE.COM

来源:Vertica集成Kerberos配置(某金融机构)、FI环境Eon数据库Kerberos部署(某通信运营商 FI)

为什么两者都要? 虽然没有官方文档明确解释,但从本库实践和 Kerberos 协议惯例可以推断:

理由 说明
安全隔离 vertica/ 的权限范围仅限于 Vertica 应用,host/ 等效于主机 root。只用一个 host/ 意味着 Vertica 获得了 OS 级权限,违反最小权限原则
委派控制 Active Directory 中可以单独为 vertica/ 开启 delegation(允许 Vertica 将用户凭证委派给 HDFS),不影响 host/ 的安全边界
Huawei FI 兼容 某通信运营商使用的 FusionInsight 环境,host/ 票据可能是 FI 内部认证链路的硬性要求
审计追查 Kerberos 日志中两条不同的身份记录,便于区分是 Vertica 应用还是 OS 层面的操作

3.3 keytab 文件

keytab(key table)是一个加密文件,包含一个或多个 Kerberos principal 的长期密钥。它是密码的等价物——持有 keytab 就等于持有这些 principal 的身份。

Vertica 对 keytab 的要求

  • 每个节点至少包含该节点的服务 principal(vertica/<hostname>@REALM
  • 文件路径由 KerberosKeytabFile 参数指定,默认 /etc/krb5.keytab
  • 所有节点的路径必须一致(即使是不同文件)
  • 权限必须为 0600,属主是运行 Vertica 进程的 OS 用户(通常 dbadmin
  • Kubernetes 环境下需通过 Secret 挂载,并设 KerberosEnableKeytabPermissionCheck=0

单文件 vs 多文件的 trade-off

策略 优点 缺点
单 keytab 含所有 principal 初始部署简单,所有节点文件一致 增加节点需更新所有节点;一个 principal 泄露影响全局
每节点独立 keytab 安全隔离好,增加节点只影响新节点 初始部署工作量大,需确保每节点文件路径一致

来源:Vertica 26.2 文档 Kerberos Authentication > Keytab Files。


4. 配置全景

4.1 配置目标分组

Vertica 的 Kerberos 配置不是一张平铺的参数表,而是围绕四个目标展开的。每个目标涉及一组参数,参数之间有依赖关系。

目标 1:让 Vertica 知道自己的 Kerberos 身份

这是最基础的一步。Vertica 需要三个信息来构造自己的服务 principal:

ALTER DATABASE DEFAULT SET KerberosKeytabFile = '/etc/krb5.keytab';
ALTER DATABASE DEFAULT SET KerberosServiceName = 'vertica';
ALTER DATABASE DEFAULT SET KerberosRealm = 'EXAMPLE.COM';

可选参数(官方不建议设置,因为会影响 vbr/admintools 的行为):

  • KerberosHostname:指定 principal 的主机名部分。不设时用 gethostname()如果设置了,所有节点的 principal 会变成同一个值,而每个节点的实际 hostname 不同,这会导致 vbr 备份等跨节点操作认证失败。

来源:Vertica 26.2 文档 Troubleshooting Kerberos Authentication > "unset the KerberosHostname parameter"。

KerberosTicketDuration:控制 kinit 时的票据有效期,设为 0 使用 Kerberos 默认值。

目标 2:让客户端能用 Kerberos 登录

-- 创建 GSS 认证方法
CREATE AUTHENTICATION v_kerberos METHOD 'gss' HOST '0.0.0.0/0';
ALTER AUTHENTICATION v_kerberos ENABLE;

-- 授权给用户
GRANT AUTHENTICATION v_kerberos TO bob;

-- 可选:多 realm 支持
ALTER AUTHENTICATION v_kerberos SET REALM = 'OTHERREALM.COM';

关键点:

  • METHOD 'gss' 只能用 HOST 类型,不能用 LOCAL(本地连接会绕过 Kerberos)
  • 可以创建多个 GSS 认证记录指向不同 realm,实现多 realm 共存
  • GSS 认证不支持 fallthrough(失败后不能回退到 hash/ldap 等其他认证方法)

目标 3:让 Vertica 后台进程能访问 Kerberized Hadoop/HDFS

这是最容易被忽视的配置。即使客户端能正常登录,Tuple Mover 和 Eon 公共存储访问还需要额外的 Hadoop 端配置:

-- 告诉 Vertica Hadoop 配置文件在哪
ALTER DATABASE DEFAULT SET HadoopConfDir = '/opt/hadoop/etc/hadoop/';

Hadoop 端:

  • vertica/<hostname>@REALM principal 授予 HDFS 目录的读写权限
  • 如果使用 HDFS storage location,创建 location 时用的是 keytab principal 而非客户端用户

目标 4:确保每个节点都能到达 KDC

/etc/krb5.conf 必须内容一致地存在于所有节点。最小配置:

[libdefaults]
    default_realm = EXAMPLE.COM

[realms]
    EXAMPLE.COM = {
        kdc = kdc.example.com:88
        admin_server = kdc.example.com:749
    }

[domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

[domain_realm] 小节极易遗漏——如果 Vertica 节点的 hostname 和 KDC 中注册的不完全匹配,Kerberos 无法正确映射 realm,认证直接失败。

4.2 参数之间的影响链

以下是一个常见的问题链条,展示了参数之间的因果关系:

HadoopConfDir 未包含 Kerberized 配置路径
  → Vertica 用非 Kerberos 方式访问 WebHDFS
    → 报 HTTP 403 Permission denied
      → external_config_check 中 hdfs_cluster_config_check 的 Kerberos Auth 显示 [false]
KerberosKeytabFile 指向不存在的文件
  → Vertica 进程启动时内部 kinit 失败
    → Eon 数据库卡在 Inviting cluster 阶段(来源:Eon启动票据验证失败诊断)
    → 企业模式不受影响(因为企业模式不需要访问公共存储)
KerberosHostname 被设置
  → vbr 备份时用 KerberosHostname 值构造 principal
    → 该值在所有节点上相同,但各节点 keytab 中的 principal 包含不同的 hostname
      → 认证失败:Server not found in Kerberos database

4.3 客户端配置差异

不同客户端的配置方式差异很大,但它们最终都在做同一件事:帮助 GSSAPI 库找到正确的服务 principal 名称

客户端 Principal 格式 配置位置 示例
vsql service@host -K 参数 vsql -K node1.example.com -h node1 -U bob
ODBC service@host 连接字符串 KerberosHostname KerberosHostname=node1.example.com
JDBC service@host JAAS 配置文件 + 连接属性 props.setProperty("KerberosHostName", "node1.example.com")
ADO.NET (Windows) 系统自动 Windows SSPI IntegratedSecurity=true

Server 端与 Client 端 Principal 格式不一致

  • Vertica 配置时的格式:KerberosServiceName/KerberosHostname@KerberosRealm(如 vertica/node1.example.com@EXAMPLE.COM
  • GSSAPI 客户端传参时的格式:KerberosServiceName@KerberosHostname(如 vertica@node1.example.com

之所以省略 realm,是因为 GSS 库会从 /etc/krb5.confdefault_realm 自动补全。

来源:Vertica 26.2 文档 Configure Clients for Kerberos Authentication。

4.4 验证工具

配置完成后,用以下函数验证:

-- 最全面的检查:Kerberos + Hadoop + HCatalog 一站式验证
SELECT EXTERNAL_CONFIG_CHECK();

-- 仅检查 Vertica 自身的 Kerberos 配置(keytab、principal、kinit)
SELECT KERBEROS_CONFIG_CHECK();

-- 仅检查 HDFS 集群连接
SELECT HDFS_CLUSTER_CONFIG_CHECK();

-- 验证 HadoopConfDir 在各节点上是否存在且有效
SELECT VERIFY_HADOOP_CONF_DIR();

KERBEROS_CONFIG_CHECK() 的验证项(来源:Vertica 26.2 文档):

  1. kinitkrb5.conf 文件是否存在
  2. keytab 文件是否存在且已设置
  3. 所有 Kerberos 参数值是否正确
  4. Kerberos 能否读取 keytab 中的密钥
  5. Kerberos 能否获取数据库 principal 的票据
  6. 数据库能否用 kinit 初始化密钥
  7. KerberosCredentialCache 的位置

5. 常见故障模式与排查路径

5.1 故障分类概览

按出现频率和排查优先级排列:

优先级 故障现象 根因方向 最快定位方式
P0 vsql 登录报 GSSAPI error keytab/KDC 基础配置 KERBEROS_CONFIG_CHECK()
P0 Eon 数据库启动卡在 Inviting cluster keytab 不存在或无效 vertica.log 查 403/401 错误
P1 能登录但访问 HDFS 外表报错 运行链路票据问题 EXTERNAL_CONFIG_CHECK()
P1 所有节点时钟不同步 NTP/chrony 未配置 date 对比各节点时间
P2 偶尔失败、偶尔成功 票据过期刷新/Hadoop token 查 token 过期时间
P2 replay cache 文件不释放 KRB5 库 bug 或文件描述符泄漏 lsof -p $(pidof vertica)

5.2 故障模式详解

模式 1:GSSAPI 登录失败 —— "No Kerberos credentials available"

现象

$ vsql -h node1 -K node1.example.com -U bob
vsql: GSSAPI continuation error: Unspecified GSS failure.
GSSAPI continuation error: No Kerberos credentials available

根因原理:客户端没有有效的 Kerberos TGT。Kerberos 认证要求客户端先通过 kinit 获取 TGT,然后才能请求 Service Ticket。

排查步骤(按顺序):

  1. 检查客户端 TGTklist 看是否有有效票据。如果没有,kinit bob@EXAMPLE.COM
  2. 检查 keytab 能否 kinitkinit -k -t /path/to/keytab vertica/node1.example.com@EXAMPLE.COM
  3. 检查 krb5.conf:确认 default_realm 正确、KDC 地址可达(telnet kdc.example.com 88
  4. 检查时钟同步:各节点 date 与 KDC 时间差应在 5 分钟内
  5. 检查 DNS/hostshostname -f 返回值与 principal 中 hostname 一致

模式 2:Eon 数据库启动卡在 Inviting cluster

现象:数据库一直停留在 (DOWN) 状态,vertica.log 中有 HTTP 403Permission denied 错误。

根因原理:Eon 模式在启动过程中需要访问公共存储(HDFS/S3 等)。如果公共存储使用 Kerberos 认证,Vertica 需要用 keytab principal 做身份验证。keytab 不存在、无效、或 keytab 中的 principal 无权访问公共存储目录,都会导致启动失败。

来源:Eon启动票据验证失败诊断(某通信运营商),企业模式无此问题。

排查步骤

  1. 检查 vertica.log 中的 WebHDFS URL 和 HTTP 状态码
  2. kinit -kt <keytab> <principal> 手动验证 keytab 能否获取票据
  3. hdfs dfs -ls <communal_storage_path> 验证 principal 对公共存储目录有访问权限
  4. 确认 bootstrap_params.conf(复活时)或数据库参数中 HadoopConfDir 包含 Kerberized Hadoop 配置路径
  5. 对于 FI 环境,确认已 source 了带 Kerberos 的 bigdata_env

模式 3:能登录但访问 HDFS 外表失败

现象:vsql 登录正常,但 SELECT * FROM hdfs_external_tableparallelexport() 到 HDFS 报认证错误。

根因原理:链路 1(接入)和链路 2(运行)分离。接入链路正常只说明客户端→Vertica 的 Kerberos 认证正常;运行链路(Vertica→HDFS)使用的是另一套票据,可能过期或不存在。

来源:HDFS导出数据失败案例分析:dbadmin 密码过期导致 crontab 刷新票据失败,parallelexport() 验证 USER_A 用户票据时票据已失效。但 COPY FROM webhdfs 不受影响(因为使用的是 ETL 服务器的票据)。

排查步骤

  1. SELECT EXTERNAL_CONFIG_CHECK() —— 最快速的全链路检查
  2. 在各节点上手动 hdfs dfs -ls /path 测试 HDFS 连通性
  3. 检查各节点的 keytab principal 是否有 HDFS 目录的访问权限(hdfs dfs -chown
  4. 检查 HadoopFSTokenRefreshFrequency 是否设置合理
  5. 如果是 Eon 复活场景,确认 bootstrap_params.conf 中包含 Kerberos 参数

模式 4:Replay Cache 文件句柄累积

现象:Vertica 进程打开大量 /var/tmp/krb5_RC* 文件,最终可能耗尽文件描述符。

根因原理:Kerberos 的 /var/tmp/krb5_RC* 文件是 replay cache(重放缓存),用于防重放攻击。但在 Vertica 作为客户端访问 Hadoop 的场景中,replay cache 没有开启的必要(只有服务端接收请求时才需要防重放)。

来源:Kerberos Replay Cache文件句柄泄漏分析(某通信运营商)。

排查步骤

  1. lsof -p $(pidof vertica) | grep 'var' | grep -c 'delete' 检查文件描述符数
  2. 设置环境变量 KRB5RCACHETYPE=none 关闭 replay cache
  3. 如果问题持续,检查是否命中 MIT krb5 库的已知 bug:none 类型 replay cache 在 krb5_rc_close 时存在内存泄漏(krb5 GitHub issue #6514 / commit 0f06098,以及互斥锁未释放的二次泄漏 #8783 / commit af2a311)。需确认华为 FI 版本是否已回合这些修复。

模式 5:时钟不同步导致间歇性失败

现象:认证偶尔成功、偶尔失败,无规律。

根因原理:Kerberos 协议在 Authenticator 中包含时间戳,用于防重放攻击。KDC 和客户端/服务端之间的时钟偏差如果超过 5 分钟(默认值),认证会被拒绝。虚拟机上尤其容易发生时钟漂移。

排查步骤

  1. 所有节点 + KDC 上执行 date 对比时间
  2. 配置 NTP(RHEL 7+ 用 chrony,旧版用 ntpd
  3. 如果与 Windows AD 同步,注意 Windows Time Service 和 Linux NTP 的兼容性问题

模式 6:vbr/admintools 认证失败

现象:vsql 登录正常,但 vbr backupadmintools 操作报 Server not found in Kerberos database

根因原理:vbr 和 admintools 使用 KerberosHostname 参数的值(如果设置了的话)构造 principal。如果 KerberosHostname 设为某一个节点的 hostname,但其他节点的 keytab 中包含不同的 hostname,跨节点操作就会因 principal 不匹配而失败。

修复

ALTER DATABASE DEFAULT CLEAR KerberosHostname;

来源:Vertica 26.2 文档 Troubleshooting Kerberos Authentication > "Authentication failure in backup, restore, or admin tools"。

5.3 排查工具速查

工具 用途 执行位置
klist 查看当前 ticket cache 中的票据 客户端/各节点
kinit -kt <keytab> <principal> 手动用 keytab 获取票据,验证 keytab 有效性 各节点
kdestroy 清除当前 ticket cache 客户端
hdfs dfs -ls / 测试 HDFS 连通性 各节点
EXTERNAL_CONFIG_CHECK() 全链路 Kerberos + Hadoop 配置验证 数据库内
KERBEROS_CONFIG_CHECK() Vertica 自身的 Kerberos 配置验证 数据库内
cat /proc/<PID>/environ \| tr '\0' '\n' \| grep KRB5 检查 Vertica 进程的 Kerberos 环境变量 各节点

来源:排查工具和命令来自 Kerberos故障排查方法论 13 条方法论及 Vertica 26.2 文档。


6. 设计原则与最佳实践

原则 1:每个节点使用独立的服务 principal

为什么:如果所有节点共用同一个 principal,任何一个节点的 keytab 泄露会影响所有节点。独立 principal 实现了安全隔离,且排查问题时可精确定位到节点。此外,vbr 跨节点操作依赖各节点有各自的 principal。

反例:设置 KerberosHostname 导致所有节点 principal 相同 → vbr 备份失败。


原则 2:keytab 和 krb5.conf 要实现文件层面的全节点一致性

为什么KerberosKeytabFile 参数指向的是路径字符串,不是文件内容。路径一致的 keytab 文件(即使每节点内容不同)配合 KerberosHostname 不设(让各节点用 gethostname() 自动选择 keytab 中匹配的 principal),这是官方推荐的做法。但 krb5.conf 必须内容一致地存放在所有节点的同一路径。

反例:扩容时新节点 keytab 路径与老节点不一致 → KERBEROS_CONFIG_CHECK 部分节点 PASS、部分 FAIL。


原则 3:总是用 keytab 做系统进程认证,不要依赖外部 crontab kinit

为什么:Vertica 内置基于 keytab 的自动 ticket 管理。外部 crontab 方案引入了额外的依赖(OS 用户口令不过期、crontab 服务正常、网络连通等),增加了故障面。

反例:某通信运营商 2020-06-25 故障——依赖 crontab 用 dbadmin 刷新票据,dbadmin 口令到期导致刷新失败,HDFS 导出中断。见 HDFS导出数据失败案例分析。


原则 4:Kerberos 配置变更后必须重启数据库

为什么KerberosKeytabFileKerberosServiceNameKerberosRealm 等参数在数据库启动时被读取并用于生成 ticket cache。参数变更(ALTER DATABASE DEFAULT SET)虽然会持久化到 catalog,但运行中的进程不会重新加载

反例:更新 keytab 后 ALTER DATABASE 修改了 KerberosKeytabFile,未重启 → 仍然使用旧 ticket cache → 直到旧票据过期后才暴露问题。


原则 5:用 HadoopFSTokenRefreshFrequency 防止 token 过期,而不是被动修复

为什么:Hadoop token 有固定有效期(由 Hadoop 集群配置决定),Vertica 中如果 token 年龄超过 HadoopFSTokenRefreshFrequency 设定值,会在下次 HDFS 访问前自动刷新。默认不设置意味着依赖 Hadoop 侧的过期机制,一旦过期就是故障。

反例:长期运行的 ETL session 中途 Hadoop token 过期 → 批量导入中断,需重跑。


原则 6:Eon 复活时必须传入完整的 Kerberos 参数

为什么:复活(revive)是新集群启动,没有原数据库的参数上下文。bootstrap_params.conf 必须包含 KerberosServiceNameKerberosRealmKerberosKeytabFileHadoopConfDir。注意 HadoopConfDir 在复活时会直接替换数据库的 HadoopConfDir 参数值,记得包含 Kerberized Hadoop 配置路径。

反例:某通信运营商 FI 环境复活时 bootstrap_params.conf 只有 HadoopConfDir 没有 Kerberos 参数 → Permission denied: user=dbadmin(复活用 dbadmin 身份而非 keytab principal)。见 FI环境Eon数据库Kerberos部署。


原则 7:不要在 GSS 认证方法上依赖 fallthrough

为什么:GSS 认证不支持 fallthrough 到 hash/ldap 等其他认证方法(来源:Vertica 26.2 文档 Authentication Method Compatibility 表)。如果 Kerberos 出问题,用户无法通过密码回退认证。需要在客户端层面实现 fallthrough 逻辑(先尝试 Kerberos,失败后用密码重连)。

反例:KDC 维护期间全集群无法登录,因为没有配置密码认证作为备用方案。


7. 扩展阅读

本库资源(按推荐阅读顺序):

  1. Vertica集成Kerberos配置 — 某金融机构环境的完整配置步骤,包含 Principal 生成、keytab 导出、认证方法创建和参数设置的全流程
  2. Kerberos故障排查方法论 — 13 条 Kerberos 故障排查方法论,覆盖时钟、网络、hosts、票据缓存等最常见问题
  3. FI环境Eon数据库Kerberos部署 — 某通信运营商 FI 环境 Eon 复活全流程,包含 HDFS 权限变更和 lease 清理脚本
  4. Kerberos Replay Cache文件句柄泄漏分析 — Replay Cache 的原理和 KRB5RCACHETYPE=none 的使用场景
  5. Eon启动票据验证失败诊断 — Eon 启动时 keytab 验证失败的快速诊断
  6. HDFS导出数据失败案例分析 — 外部 crontab kinit 方案的典型故障案例
  7. Hadoop数据加载认证错误排查 — Server vertica/@HADOOP.COM not found in Kerberos database 的三种根因

官方文档

  • Vertica 26.2 文档 Security & Authentication > Kerberos Authentication(vertica_docv26.2.pdf
  • Vertica 26.2 文档 Hadoop Integration > Accessing Kerberized HDFS Data(同 PDF)
  • Vertica 26.2 文档 SQL Reference > Config Parameters > Kerberos Parameters(同 PDF)

外部资源