Apache Kyuubi 是面向分布式数据系统的多租户 SQL 网关。它为用户和 BI 工具提供稳定的 JDBC 或 ODBC 端点,而不要求每个用户管理 Spark 应用程序生命周期、集群队列或引擎配置。
Kyuubi 将长期运行的客户端端点与执行查询的进程分离。 这种区分是 Kyuubi 在架构上的主要贡献:
- Kyuubi 服务器负责认证客户端、维护协议会话、选择引擎以及转发操作。
- Kyuubi 引擎负责运行 SQL 并消耗计算资源。Spark SQL 是最常见的引擎,而 Kyuubi 的各个发行版也可以集成其他查询引擎。
- 外部服务仍然负责提供资源管理、元数据、存储、授权策略和服务发现。
因此,Kyuubi 并不会替代 Spark、YARN、Kubernetes、Hive metastore 或对象存储。它负责协调对这些组件的访问。
架构 #
典型的 Spark-on-YARN 部署如下:
Beeline、BI 工具或应用程序
|
| 使用 HiveServer2 协议的 JDBC/ODBC
v
Kyuubi 服务器池
| |
| `----> ZooKeeper 或其他已配置的服务发现服务
|
| 启动、发现或复用
v
Spark SQL 引擎应用程序
|----> YARN,用于驱动程序和执行器资源
|----> Hive Metastore,用于表元数据
|----> HDFS 或对象存储,用于表数据
`----> Ranger 或其他授权系统由于引擎负责解析、规划、扫描、连接、shuffle 和写入,Kyuubi 服务器相对轻量。扩展服务器节点可以提高连接和操作处理能力,但不会因此增加 Spark 执行器。
Apache Hive / Kyuubi Overview 更详细地比较了这种设计与 HiveServer2 及 Spark Thrift Server 的差异。
跟踪查询 #
假设 Beeline 发送以下语句:
SELECT region, SUM(amount)
FROM lakehouse.sales
WHERE sale_date >= DATE '2026-08-01'
GROUP BY region;请求通常会经历以下阶段:
- 客户端打开传输连接,并与 Kyuubi 服务器执行已配置的身份验证交换。
- Kyuubi 创建协议会话,并确定有效用户、引擎类型、引擎共享范围和允许的配置。
- Kyuubi 搜索兼容的运行中引擎。如果不存在,则向 YARN、Kubernetes 或已配置的本地环境提交新的引擎应用程序。
- 服务器等待引擎注册,然后转发操作。
- 引擎解析并规划 SQL,读取目录元数据,检查授权,请求计算资源,并访问表文件。
- Kyuubi 暴露操作状态和日志,同时客户端轮询或获取结果。
- 关闭客户端会话后,其操作状态会被释放。引擎可能根据共享策略和超时策略继续运行以供复用,也可能停止。
这解释了两种典型的延迟模式。冷会话可能需要等待 Spark 驱动程序和执行器启动;热会话可以复用现有引擎,几乎立即开始规划。
选择引擎共享级别 #
引擎共享级别定义哪些会话可以复用同一个引擎。名称和具体细节应根据已部署的 Kyuubi 版本进行确认,但标准选项如下:
| Level | Typical ownership | Isolation | Startup cost | Common use |
|---|---|---|---|---|
CONNECTION | 一个客户端连接 | 最高 | 最高 | 大型 ETL 作业或不受信任的会话设置 |
USER | 一个经过身份验证的用户 | 强 | 中等 | 使用用户身份的交互式 SQL |
GROUP | 一个主要用户组 | 中等 | 较低 | 具有共同数据和队列策略的团队 |
SERVER_LOCAL | 到达同一 Kyuubi 服务器的会话 | 低 | 低 | 受控的服务工作负载 |
SERVER | 跨服务器池的会话 | 最低 | 最低 | 经过严格保护的共享工作负载 |
USER 是常见的默认选项,因为它在复用和隔离之间取得了平衡。但它并不自动适合生产环境:
CONNECTION可以限制会话间干扰,但可能因为大量驱动程序而使集群过载。USER在许多偶尔使用的用户各自保留一个引擎时,可能导致资源被闲置占用。GROUP可以提高利用率,但需要可信的组映射和兼容的授权规则。- 服务器范围的共享会将无关用户置于同一个引擎进程中。必须加强会话级 SQL 授权,并由管理员阻止不安全的配置、临时视图、缓存和资源交互。
共享既是安全边界,也是容量决策。不要仅仅为了减少启动时间而选择共享级别。
理解引擎生命周期 #
服务器和引擎具有相互独立的生命周期。如果选定的发现和恢复行为支持该模式,客户端可以通过另一个服务器节点重新连接,同时远程部署的引擎继续运行。
引擎通常经历以下状态:
requested -> submitted -> starting -> registered -> active -> idle -> stopped重要控制项包括:
- 启动超时: 会话等待资源分配和引擎注册的时间。
- 空闲超时: 没有活动会话的引擎继续保持可用状态的时间。
- 会话和操作超时: 回收已放弃客户端状态的时机。
- 引擎生命周期: 用于定期替换长期运行引擎的可选上限。
- 失败限制和重试策略: Kyuubi 是否重试启动,或将失败报告给客户端。
较长的空闲超时可以改善交互式延迟,但会占用驱动程序内存,并可能保留执行器、缓存数据、类加载器和目录状态。较短的超时可以节约资源,但用户会反复承担冷启动成本。在选择数值之前,应测量请求到达模式和引擎启动时间。
分离配置层 #
Kyuubi 部署包含多个配置范围:
- 服务器设置控制监听器、身份验证、服务发现、服务器超时、日志记录以及启动引擎时使用的规则。
- 引擎设置控制 Spark 驱动程序、执行器、目录、扩展、类路径、资源队列和 SQL 运行时。
- 会话设置在管理员允许时影响一个逻辑客户端会话。
- 语句设置是
SET等 SQL 命令,并受引擎和安全限制约束。
配置可能来自服务器文件、引擎默认值、特定环境的模板、JDBC URL 参数和客户端属性。确切的优先级和允许列表行为取决于版本。管理员应明确限制客户端覆盖项,而不是假设每个 spark.* 属性都无害。
例如,允许客户端选择 YARN 队列可能很有用:
#spark.yarn.queue=analytics-interactive但允许任意归档文件、JAR、扩展、代理用户、事件日志目标或目录实现,可能成为代码执行或权限提升路径。应将配置策略视为安全模型的一部分。
使用 JDBC 连接 #
Kyuubi 暴露兼容 HiveServer2 的端点,因此 Beeline 和许多 Hive JDBC 工具无需使用 Kyuubi 特定的线协议即可连接:
beeline -u \
'jdbc:hive2://sql.example.com:10009/default;ssl=true;principal=kyuubi/sql.example.com@EXAMPLE.COM'URL 包含几个不同区域:
jdbc:hive2://host:port/database;session-properties?query-properties#engine-properties支持情况和解释方式取决于客户端和服务器版本。不要将密码放入 shell 历史或进程参数中;当凭据或查询结果经过不受信任的网络时,应使用 TLS,并验证服务器证书和主机名。
如需完整的安全示例,请参阅 Kerberos Beeline-to-Kyuubi walkthrough,其中解释了以下 URL:
jdbc:hive2://kyuubi.hadoop.vip.mycompany.com:10010/default;ssl=true;principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM?kyuubi.session.cluster=analytics-prod#spark.yarn.queue=analytics-high-memory该示例跟踪 DNS 和 TLS、票据授予票据、服务票据获取、SASL/GSSAPI、Kyuubi 的服务 keytab、YARN 提交以及 Hadoop 委派令牌。
部署 Kyuubi #
服务器节点 #
在稳定端点后运行多个 Kyuubi 服务器,或使用受支持的服务发现模式。应使服务器节点保持可互换:
- 分发相同的 Kyuubi 版本、引擎制品、配置、信任库和身份验证材料;
- 在需要时,为每个节点提供唯一的通告地址;
- 将可变的查询状态保存在引擎或受支持的共享服务中,而不是某个服务器的本地磁盘上;
- 在升级前排空监听器,以便现有操作完成;以及
- 在执行滚动升级前测试混合版本行为。
TCP 负载均衡器对客户端而言较为简单,而支持服务发现的 JDBC 可以直接暴露已注册的服务器池。两种机制都不能保证失败连接中的进行中操作会被透明重放。客户端需要有界重试,并且必须了解某条语句是否可以安全地重新提交。
YARN 上的 Spark 引擎 #
对于 YARN 部署,Kyuubi 会提交一个包含驱动程序的应用程序,然后请求执行器。请验证:
- 提交者或代理身份可以使用选定的队列;
- 引擎可以本地化 Spark、Kyuubi 引擎 JAR、Hadoop 配置、keytab 和目录依赖;
- ApplicationMaster 可以通过防火墙向 Kyuubi 重新注册;
- 驱动程序和执行器主机可以访问 HMS、存储、KMS、Ranger 和 shuffle 服务;
- 队列上限允许所请求的驱动程序和执行器规格;以及
- 引擎日志和 Spark 事件日志能够在容器终止后保留。
如果会话卡在引擎创建阶段,通常是资源分配或回调问题,而不是 JDBC 问题。
Kubernetes 上的引擎 #
在 Kubernetes 上,对应的控制项包括命名空间、服务账户、RBAC、Pod、镜像、Secret、ConfigMap、持久化或对象存储支持的日志、网络策略和资源配额。避免将长期凭据直接放入镜像。按摘要固定镜像,控制哪些会话设置可以影响 Pod 模板,并将受信任的管理引擎与普通用户引擎分离。
集成目录和存储 #
Kyuubi 不存储表元数据。Spark 引擎可以使用 Hive Metastore、Iceberg 目录、JDBC 目录或其他目录插件。引擎需要:
- 匹配的客户端库和目录扩展;
- 网络访问和身份验证凭据;
- 兼容的 Hadoop 文件系统实现;
- 对象存储或 HDFS 凭据;
- 在适用时访问加密密钥;以及
- 具有正确所有权的仓库和临时位置。
目录库应放在引擎类路径中,而不仅仅是 Kyuubi 服务器类路径中。即使引擎缺少目录 JAR 或无法访问 HMS,服务器仍然可以接受 JDBC 会话,之后每条查询却都会失败。
构建安全模型 #
安全性跨越多个跳转:
client -> Kyuubi server -> engine -> metastore/storage/authorization service每个跳转回答不同的问题:
- TLS 在验证证书时保护传输并认证端点。
- Kerberos、LDAP、PAM 或其他已配置机制负责将客户端认证到 Kyuubi。
- Impersonation 或代理用户规则决定哪个身份启动引擎并访问下游 Hadoop 服务。
- 委派令牌和服务凭据使长期运行的引擎能够访问 HDFS、HMS、KMS 及相关服务。
- SQL 授权通常通过 Ranger 等策略插件实现,用于决定用户可以访问哪些目录、表、列、行和操作。
- YARN 队列或 Kubernetes 配额限制计算资源,而不是数据权限。
身份验证不等于授权。成功获取 Kerberos 服务票据只能证明身份已被 Kyuubi 识别,并不会授予表访问权限。
审计记录至少应保留经过身份验证的用户、有效用户、客户端地址、服务器、引擎应用程序 ID、会话和操作 ID、规范化语句或语句哈希、可用时的目标对象、开始和结束时间、结果以及资源队列。由于 SQL 文本可能包含敏感字面量,应保护审计日志。
运行和观测服务 #
分别监控网关和引擎。
有用的服务器信号包括:
- 已打开和被拒绝的连接;
- 活动会话和操作;
- 身份验证失败;
- 引擎启动请求、持续时间、超时和失败率;
- 请求队列深度和 RPC 延迟;以及
- 服务器堆、垃圾回收、线程和文件描述符。
有用的引擎信号包括:
- 每个引擎中的活动会话和语句;
- 驱动程序内存和垃圾回收;
- 执行器分配和丢失;
- SQL 规划和执行持续时间;
- shuffle 读写、溢写、数据倾斜和失败阶段;
- 目录和存储延迟;以及
- 空闲时长和终止原因。
将 Kyuubi 会话和操作标识符与 Spark 应用程序 ID 关联起来。只报告 Kyuubi 服务器 CPU 的单一仪表板可能显示服务健康,但所有查询实际上都被 YARN 容量或对象存储限流阻塞。
按阶段设置服务级别目标。连接建立、冷引擎启动、热查询启动和查询执行具有不同原因,不应合并为一个延迟百分位数。
规划容量 #
至少估算四个独立限制:
- 服务器连接容量: 并发传输、会话、操作和结果获取流量。
- 驱动程序容量: 根据所选共享策略保留的引擎数量和大小。
- 执行器容量: 活跃 SQL 所需的峰值和持续资源。
- 下游容量: HMS 连接、对象存储请求、HDFS 处理器、授权检查和 shuffle 带宽。
对于 USER 共享,驱动程序内存的粗略上限如下:
并发保留的用户引擎数
* (驱动程序内存 + 驱动程序开销)该上限与执行器需求分开计算。数百个大多处于空闲状态的用户引擎,可能在消耗大量执行器 CPU 之前耗尽队列应用程序限制或驱动程序内存。引擎池、经过谨慎选择的空闲超时和组共享可以降低该成本,但每种方式都会改变隔离性。
通过队列限制、语句超时、准入控制和最大结果大小保护交互式工作负载。通过 Kyuubi 获取数百万行的 JDBC 客户端,通常不如将结果写入受治理存储。
诊断常见故障 #
客户端无法连接 #
检查 DNS、负载均衡器健康状态、监听器地址、TLS 信任和主机名验证、身份验证配置,以及选定服务器是否已注册。TCP 连接拒绝发生在引擎选择之前。
身份验证成功但引擎未启动 #
检查 Kyuubi 服务器日志和集群管理器的应用程序状态。常见原因包括队列拒绝、应用程序限制耗尽、引擎制品缺失、Spark 配置无效、容器镜像不可用、回调网络受限,或身份无法提交应用程序。
引擎启动但 SQL 无法解析表 #
检查引擎目录配置和类路径、HMS URI、DNS、TLS 或 Kerberos 凭据、仓库路径以及目录版本兼容性。仅修改 Kyuubi 服务器类路径无法修复远程引擎。
查询因权限错误而失败 #
确定哪个层拒绝了请求:
- Kyuubi 身份验证或代理用户策略;
- SQL 授权策略;
- HMS 授权;
- HDFS 权限或 ACL;
- 对象存储 IAM;
- 加密密钥策略;或
- YARN/Kubernetes 资源策略。
不要通过授予 Kyuubi 服务身份广泛的存储访问权限来隐藏失败。端到端验证经过身份验证的身份和有效身份。
热查询变慢 #
分离规划和执行。检查 HMS 延迟、过期统计信息、驱动程序垃圾回收、在一个引擎上共享过多会话、执行器资源不足、数据倾斜、shuffle 溢写、对象存储限流或结果获取过大。重启服务器可能暂时掩盖不健康的引擎,但无法识别根因。
故障转移期间客户端丢失结果 #
服务器发现可以提供另一个端点,但无法使任意 SQL 操作具备安全重放能力。确定操作是否已完成,对写入使用应用程序级幂等性,并避免盲目重试 INSERT、MERGE 或 DDL。
比较主要选项 #
| Service | Client endpoint | Execution model | Strong fit |
|---|---|---|---|
| HiveServer2 | Hive JDBC/ODBC | Hive 支持的执行引擎 | HiveQL 和 Hive 原生操作 |
| Spark Thrift Server | Hive JDBC/ODBC | 一个受管理的 Spark 应用程序 | 更简单的共享 Spark SQL 端点 |
| Kyuubi | Hive JDBC/ODBC 加引擎管理 | 按策略选择的隔离或共享引擎 | 多租户 Spark/lakehouse 访问 |
Direct spark-submit | 作业提交 | 每次提交一个应用程序 | 调度式 ETL 和由应用程序负责的生命周期 |
Kyuubi 增加了运维机制,但并不会自动比 Spark Thrift Server 更快。它的价值来自引擎隔离、生命周期管理、路由、共享安全控制和稳定的服务边界。
判断 Kyuubi 是否适用 #
以下场景适合使用 Kyuubi:
- 分析师、仪表板、笔记本和应用程序需要稳定的 SQL 端点;
- Spark 或其他受支持的后端已经是期望的执行引擎;
- 工作负载需要按用户、按组或按连接进行隔离;
- 管理员需要集中管理身份验证、审计、配置策略、队列路由和引擎生命周期;以及
- 可以在冷启动延迟与保留引擎的成本之间取得平衡。
如果所有工作负载都是调度作业、一个受信任的团队可以使用单个 Spark Thrift Server,或者其他查询服务已经提供所需的延迟、并发、治理和生态支持,那么 Kyuubi 可能没有必要。
有用的思维模型是:Spark 提供计算能力;目录描述数据;集群管理器分配资源;Kyuubi 将这些组件转换为受管理的多用户 SQL 服务。
评论
在 GitHub 上阅读或评论(发表评论需要登录)