做过 Ambari Kerberos 环境的人应该都有过这种经历集群里 Ranger 节点一台台都起来了HA 状态看着也正常就是当你把访问入口从节点主机名换成统一域名之后浏览器死活不肯出那个 Kerberos 认证框要么直接 401要么一直转圈出不了登录页。这个问题的根源90% 不在 Ranger 本身而在 Kerberos 票据这一层。Kerberos 认证是“认名字”的浏览器或客户端去访问什么域名它就向 KDC 申请什么域名的服务票据。原来你访问的是 ranger-node-1.example.com现在统一域名变成了 ranger-ha.example.com票据对不上服务端自然不认。这篇是 Ranger HA 搭建系列的第二篇只讲一件事在 Ambari 开启 Kerberos 的场景下如何为统一访问域名生成和部署 Kerberos 票据把整个认证链路捋顺。适合正在搭 Ranger HA、或者搭完发现认证不通过的运维和安全工程同学。1. 为什么 HA 之后原有票据就不够用了先理清认证链路1.1 从一次正常的 Ranger 页面访问说起在没有 HA 之前你访问 Ranger Admin地址栏里输入的是节点主机名比如 http://ranger-node-1.example.com:6080。集群开启 Kerberos 之后Ranger Admin 的 Web 界面会启用 SPNEGO 认证也就是基于 HTTP 协议的 Kerberos 认证。这个时候浏览器做的事情大概是这样的浏览器发现目标主机是 ranger-node-1.example.com因为浏览器配置了该域名的 SPNEGO 白名单它向 KDC 申请一张 HTTP/ranger-node-1.example.com 的服务票据浏览器把这张票据塞进 Authorization 请求头发给 RangerRanger 端拿到 keytab 里的 HTTP/ranger-node-1.example.com 条目对票据做解密验证验证通过页面正常返回。这里有一个容易被忽略但极其关键的点整个链路本质上是“客户端请求的 SPN”和“服务端 keytab 里的 principal”做精确匹配。Kerberos 是严格的姓名匹配主机名差一个字符、大小写不一致都匹配不上。平时大家说“票据生成好了”实际是在说这个配对关系打通了。1.2 HA 引入统一域名后链路发生了什么变化HA 搭好之后两个 Ranger Admin 节点前面挂了一台负载均衡器或者配置了一个 VIP对外暴露的是统一域名比如 ranger-ha.example.com。用户访问 Ranger不再直接访问某一台节点而是访问这个统一域名。问题就出在这里。浏览器的访问目标变了它现在向 KDC 申请的是 HTTP/ranger-ha.example.com 的服务票据。可是 Ranger Admin 节点上的 keytab 里只有原来基于各自主机名的 HTTP/ranger-node-1.example.com 和 HTTP/ranger-node-2.example.com。服务端翻遍整个 keytab找不到 HTTP/ranger-ha.example.com 这个 principal自然解不开浏览器发来的票据于是 401、无限重定向、登录框反复弹各种诡异现象就来了。这里我要强调一个容易混淆的概念负载均衡只是把 TCP/IP 层的请求转发到了后端节点它不会帮你改 HTTP 头里的 Kerberos 票据。票据里的 SPN 是客户端在发起请求时根据访问域名定好的目标域名是什么票据就申请什么。这不是负载均衡能“透传”或“改写”的。所以统一域名的票据必须单独生成、单独配置没有任何捷径。1.3 需要补哪些票据一张表说清楚在 Ranger HA 场景下围绕统一域名需要关注的访问链路其实不止浏览器一条。我按“谁在访问、访问谁、服务端怎么验证”拆开通常是下面几条访问场景客户端是谁服务端需要验证的 SPN客户端身份用户浏览器访问 Ranger Admin UI浏览器SPNEGOHTTP/ranger-ha.example.com登录用户的 principal命令行/脚本调用 Ranger REST APIcurl、脚本、Java 程序HTTP/ranger-ha.example.com执行者的 principalRanger Usersync 连接 Ranger Admin 上报用户Ranger UsersyncHTTP/ranger-ha.example.com如果 policymgr URL 用了统一域名rangerusersync/_HOST很多人在这一步只想到浏览器那张 HTTP SPN忘了 Ranger Usersync 也可能走统一域名。Ranger Usersync 启动后会作为一个 Kerberos 客户端去连接 Ranger Admin 的 REST API如果 Ambari 里配置的ranger.usersync.policymgr.url是https://ranger-ha.example.com:6182那么它在发请求时同样需要申请 HTTP/ranger-ha.example.com 的服务票据。所以这张表里的核心其实是同一个 SPNHTTP/ranger-ha.example.com只是它服务的对象很多。另外两个 Ranger Admin 节点之间的数据同步和心跳走的是 Ambari / Ranger 内部机制一般不依赖统一域名下的 Kerberos SPN平时不用专门为它额外生成票据。真正要盯住的是对外暴露的那几条访问链路。2. 票据生成前的准备KDC、keytab 与 principal 规划2.1 确认现有 Ranger principal 现状动手之前先花十分钟把现状摸清楚。Ambari 开启 Kerberos 后会自动为每个组件生成 principal 和 keytabRanger 相关的常见 principal 大概是这几个实际以你的 Ambari 配置为准rangeradmin/_HOSTYOUR-REALM.COMkeytab 通常在/etc/security/keytabs/rangeradmin.keytabrangerusersync/_HOSTYOUR-REALM.COMkeytab 在/etc/security/keytabs/rangerusersync.keytab还有rangerlookup、rangerkms等搭 Ranger Admin HA 的话前两个是重点_HOST是 Ambari 生成配置时替换成实际主机名的占位符。也就是说每台 Ranger 节点上的 keytab 条目都跟它自己的主机名绑定。这本身没问题只是遇到统一域名时覆盖不到。在修改任何东西之前先到每一台 Ranger 节点上执行一次klist -kt /etc/security/keytabs/rangeradmin.keytab确认现有 keytab 里有哪些 principal、kvno 是多少。这一步能避免后面改配置时把原有认证搞坏也方便你对比新旧差异。我当时为了方便排查会顺手把每台机器上 klist 的输出连同日期保存下来省得改完之后说不清是谁的密钥版本。这个习惯在工作中有多机协作的时候特别好用一份现场留档能帮你快速定位是某台机器漏了部署还是 kvno 不一致。2.2 规划统一域名的 principal 命名统一域名定下来之后principal 的规划其实很固定原则是“服务名/域名REALM”域名部分必须与实际访问的 FQDN 完全一致大小写也一致。我建议至少规划下面这个条目HTTP/ranger-ha.example.comYOUR-REALM.COM如果 Ranger Usersync 的 policymgr URL 也打算走统一域名就保持这一个 HTTP SPN 即可因为 Usersync 申请的是目标 URL 的服务票据。至于 Usersync 自己的身份 principal如果 Ambari 里的ranger.usersync.kerberos.principal仍然保留_HOST形式那就不需要为统一域名额外建这种 principal只有当你打算把用户同步组件的身份也统一成域名形式时才需要建对应的条目。我的建议是除非有强制要求否则 Usersync 自身身份保留主机名形式就好少动一个变量排错就少一分复杂度。这里有个不少人踩过的坑HTTP这个服务名必须是大写。HTTP/作为 SPNEGO 的标准服务名是约定俗成的RFC 4559 里定得很清楚。你写成http/或者Http/全都匹配不上认证照样失败。我见过有人折腾了两天最后发现只是大小写问题。2.3 顺手把时钟偏移问题解决Kerberos 对时间极其敏感默认允许的时钟偏移一般是 5 分钟具体看 krb5.conf 里的clockskew参数。统一域名场景下请求要经过负载均衡链路变长如果某个环节的机器 NTP 同步没做好就会出现“票据看起来生成了但认证就是不通过”的诡异现象。我的习惯是在配置票据之前先在所有 Ranger 节点、KDC 节点、以及客户端测试机上执行一次时间同步然后统一跑一遍date确认时间差在 1 分钟以内。这个步骤花不了两分钟但能省掉后面一个小时查错。如果你环境里有 Windows 客户端参与测试还要注意 Windows 默认时间同步周期比较长最好手动同步一次。3. 生成并部署统一域名的 Kerberos 票据分步实操3.1 在 KDC 上创建新 principal接下来进入正题。先在 KDC 服务器上创建配套的 principal。以下命令在 KDC 上执行推荐使用kadmin.local除非你的 KDC 配置允许远程 kadmin 并且你已经有了相应权限。创建浏览器 SPNEGO 用的 HTTP principalsudo kadmin.local kadmin.local: addprinc -randkey HTTP/ranger-ha.example.comYOUR-REALM.COM创建完可以用listprincs确认一下kadmin.local: listprincs | grep ranger-ha确认无误后退出 kadmin.local。这里用-randkey的意思是生成一个随机密钥而不是为 principal 设置密码。keytab 场景下我们不需要账密交互随机密钥更安全也符合服务账号的使用惯例。关于“要不要把内部通信相关 principal 也改成统一域名”我的看法是分场景看。如果你们的 Ranger 内部调用比如 Usersync 同步、插件拉取策略在 HA 架构里都配置了统一域名那就建如果内部仍然走各节点真实主机名那就保持原样只建 HTTP 那个 SPN 就够了。不要为了统一而统一内部通信走主机名反而更简单少一层对负载均衡的依赖链路也更可控。3.2 导出 keytab 并分发到 Ranger 节点principal 创建好之后要导出成 keytab 文件然后分发到所有 Ranger Admin 节点。这一步要特别注意一个细节如果用 kadmin 的ktadd命令直接往节点上的 keytab 文件里追加条目可能会有密钥轮转kvno 变更的风险导致其他节点上已有的旧 keytab 全部失配。正确的做法是导到一个临时文件再复制分发到各节点。导出命令kadmin.local: xst -norandkey -k /tmp/ranger-ha-http.keytab HTTP/ranger-ha.example.comYOUR-REALM.COM-norandkey的作用是导出时不再随机修改密钥保证 keytab 里的密钥跟 KDC 里当前记录的密钥一致。这对多节点分发特别重要你导出一次分发到两台或三台机器所有机器上的 keytab 内容完全相同kvno 也相同。如果导出两次且过程中密钥变过很可能第一台机器能用、第二台就报错排查起来非常难受。导出之后把 keytab 文件分发到每一台 Ranger Admin 节点放到一个 Ranger 进程可读的路径。常见做法是放在和现有 keytab 同一个目录/etc/security/keytabs/下权限管理也统一。分发完成后立刻设置权限和属主。这一步很容易被忽略但不做的话Ranger 进程起不来或者认证失败你会一头雾水。我的习惯配置是sudo chown ranger:ranger /etc/security/keytabs/ranger-ha-http.keytab sudo chmod 400 /etc/security/keytabs/ranger-ha-http.keytabkeytab 文件属于敏感凭证权限必须收紧建议直接 400。而且要先确认 Ranger 进程是以 ranger 用户运行的所以属主设为 ranger 才读得到。如果你环境里 Ranger 用户的属主不是 ranger记得按实际用户调整。3.3 修改 Ambari 中的 Ranger 配置分发完 keytab接下来是修改 Ambari 上的 Ranger 配置让 Ranger Admin 的 SPNEGO 过滤器使用新的 principal 和 keytab。这里强烈建议不要直接手工去改服务器上的ranger-admin-site.xml。Ambari 重启服务时会用数据库里保存的配置覆盖生产配置文件你手工改的东西会被冲掉。正确做法是在 Ambari Web UI 里改或者用 Ambari REST API 改。在 Ambari UI 中进入 Ranger Admin 服务的 Configs 页面找到ranger-admin-site相关的配置项不同 Ranger 版本位置略有差异一般在 Advanced 或 Custom 标签里重点修改下面两个ranger.spnego.kerberos.principal改成HTTP/ranger-ha.example.comYOUR-REALM.COMranger.spnego.kerberos.keytab改成/etc/security/keytabs/ranger-ha-http.keytab如果你决定内部通信和 Usersync 也走统一域名还需要在ranger-admin-site.xml或ranger-ugsync-site.xml中搜索kerberos.principal关键字找到 Admin 服务自身和 Usersync 的 principal 配置项同步改成对应配置并修改 keytab 路径。不同版本之间这些属性名可能略有差异所以我更推荐在 Ambari 配置页里直接搜spnego和kerberos.principal两组关键字来定位而不是生搬硬套某一个属性名。改完配置后在 Ambari 里保存然后通过 Ambari 重启 Ranger Admin以及 Ranger Usersync如果改了它的配置。这里我要多说一句重启顺序建议先重启 Ranger Admin确认页面能正常起来再重启 Ranger Usersync。Usersync 启动时会连 Ranger Admin 做注册如果顺序反了Usersync 那边会报连不上日志会误导你去查网络问题实际上是时序问题。3.4 验证票据生成是否正常配置完成、服务重启之后先别急着开浏览器先在服务器上用命令行验证底层票据链路是否正常。第一步验证 keytab 文件可读且条目正确sudo -u ranger klist -kt /etc/security/keytabs/ranger-ha-http.keytab输出里应该能看到HTTP/ranger-ha.example.comYOUR-REALM.COM这一条而且 kvno 跟 KDC 里的一致。第二步用 keytab 手动获取 TGT确认这个 principal 在 KDC 侧可用sudo -u ranger kinit -kt /etc/security/keytabs/ranger-ha-http.keytab HTTP/ranger-ha.example.comYOUR-REALM.COM sudo -u ranger klist正常的话会看到一张 TGT 票据。这一步验证的核心是“principal 和 keytab 这一对凭证可用”。第三步用 curl 模拟一次 SPNEGO 请求直接打 Ranger Admin 的服务接口curl -k --negotiate -u : https://ranger-ha.example.com:6182/service/plugins/info端口 6182 是 Ranger Admin HTTPS 常见端口具体以你环境为准。如果返回 JSON 而不是 401说明整个服务端票据验证链路已经通了。如果 curl 报错先确认当前 shell 环境能不能正常拿到票据可以先用测试用户kinit之后再执行 curl。浏览器侧的 SPNEGO 和命令行尽管细节有差异但服务端验证的逻辑是同一个命令行通了服务端基本就没什么大问题了。4. 验证与排错票据生成了不代表认证就通了4.1 客户端侧老被忽略的几个点服务端 keytab 配好了但实际使用中很多问题出在客户端侧。三个常见的坑集中说一下。第一个是浏览器 SPNEGO 白名单。浏览器不会对任何域名都自动发起 Kerberos 认证只有命中白名单的域名才会。Chrome 有--auth-server-whitelist参数Firefox 有network.negotiate-auth.trusted-uris配置。如果你访问 ranger-ha.example.com 时浏览器干脆没弹认证、只给你一个 401 或者反复转圈十有八九是白名单里没有这个统一域名。另外在 Windows 上要把 ranger-ha.example.com 同时加入“本地 Intranet”或信任站点Windows 对域名的信任判断比 Linux 严格不加信任站点它默认不会主动发 Kerberos 票据。第二个是 DNS 解析和 hosts 必须一致。客户端申请票据时KDC 是按请求里的主机名匹配 SPN 的。你在浏览器里输入的是 ranger-ha.example.com那票据里的 SPN 就是 HTTP/ranger-ha.example.com。如果你用 hosts 临时把 ranger-ha.example.com 指到某台机器KDC 发正确票据没问题但最终落到的那台机器上如果没有这份新 keytab服务端照样解不开。所以负载均衡也好、VIP 也好一定要保证最终转发到的每一台 Ranger Admin 节点上都确实有HTTP/ranger-ha.example.com这个 principal 的 keytab并且配置生效。第三个是测试用户的权限问题。Kerberos 认证通过只代表“你是谁”这件事验证成功不代表你一定能用 Ranger 管理页面。认证通过但权限不足Ranger 会返回明确的权限不足提示认证没过通常是 401。这两个状态要分清楚排查方向完全不同。不然你拿着一个普通用户去测认证已经通了却一直以为是票据问题会绕很多弯路。4.2 常见失败现象对照表排错的时候我习惯先看现象再对症下药。下面这张表是我在实际项目里常用的排查对照基本覆盖了票据链路能遇到的绝大部分情况现象最可能的原因检查方式浏览器一直弹认证框或直接 401客户端 SPNEGO 白名单没配或申请了错误的 SPN打开浏览器开发者工具看请求头里有没有Authorization: Negotiatecurl 返回 401但浏览器正常curl 没启用--negotiate或当前 shell 没有 Kerberos 凭证先kinit再加--negotiate -u :服务端 keytab 权限不对Ranger 进程读不到 keytab 文件查看 ranger-admin.log搜 keytab 相关报错时间不同步认证包里的时间戳超出clockskew范围各端执行date对比强制 NTP 同步负载均衡转发的节点没有新 keytab只在一台机器放了 keytab逐台执行klist -kt对比kvno 不一致导出 keytab 时没有用-norandkey对比 KDC 和本地 keytab 的 kvno这张表不复杂但非常实用。我建议把它存在你的排错文档里后续再遇到类似的 Kerberos 认证问题能少走很多弯路。4.3 最值得记的一条经验改动前保留现场整个票据生成和配置过程中最让我长记性的一条教训是改动任何 keytab 和 principal 之前一定先把现状留档。包括每台机器上原有的klist -kt输出、Ambari 上原来的配置项、以及 KDC 上相关 principal 的 kvno。这套“现场记录”做完可能只要十分钟但在排错的时候它能直接帮你判断问题是出在“本次变更引入”还是“原本就存在”。另外改完配置后不要贪多求快一次改一个变量。比如你要新增 HTTP/ranger-ha.example.com 的 SPN又顺手改了ranger.spnego.kerberos.principal还把 keytab 路径换了个目录那万一失败了你根本不知道是 principal 建错了、配置写错了还是路径权限有问题。一次只动一个变量验证通过再进下一步。这套方法论在 Kerberos 这种“牵一发动全身”的体系里尤其重要能省下大量无效排查时间。最后补一个我自己常用的收尾习惯整个票据链路打通之后不要急着收工。把各台机器上的 keytab 输出、Ambari 配置项、curl 验证命令整理成一份简短的 check-list存到团队的文档里。Kerberos 这套东西隔三个月再回头看几乎没人记得清当时改了什么。有这份 check-list后续再做 Ranger 节点扩容、更换证书、或者整个集群迁移都能省下大把时间。Step2 的票据生成关键就是把“客户端申请什么 SPN、服务端 keytab 里有没有对应 principal、两个能不能对上”这条链路彻底想明白再动手。链路清晰了剩下的就是按部就班执行而已。