3、Apache Ranger集成:Ranger架构解析、与Spark/Hive/Trino的集成方式、策略同步机制
说到Lakehouse权限管控,Apache Ranger几乎是绕不开的组件。我最早接触Ranger是在做Hadoop集群安全加固的时候,那时候它还是个纯粹的Hive授权工具。现在呢?它已经成了数据湖和Lakehouse生态里的事实标准。
这一节,咱们就把它掰开揉碎。从架构原理,到跟Spark、Hive、Trino怎么玩,再到策略怎么同步——一条线讲清楚。
3.1 Ranger架构:核心组件与数据流
先看一张整体架构图,心里有个谱。
Ranger的架构其实不复杂。核心就三个角色:Admin、插件、审计。
- Ranger Admin:策略的管理中心。Web UI和REST API都在这。策略存到关系数据库里,审计日志发到Solr或Elasticsearch。
- Ranger 插件:轻量级Java Agent。嵌入到各个计算引擎的进程里。它定期从Admin拉策略,缓存在本地内存。每次用户执行SQL,插件先查本地缓存,命中就直接放行或拒绝,不额外请求Admin。
- 审计组件:所有授权结果——通过还是拒绝、谁干的、什么时间——都异步写入审计存储。方便事后追溯。
ranger.plugin.policy.pollIntervalMs,但别低于5秒,否则Admin压力会很大。我一般设成15秒,兼顾实时性和性能。
3.2 与Hive的集成:最成熟的方案
Ranger最早就是为Hive设计的。集成方式也最成熟。
说白了,就是在HiveServer2的classpath里放一个Ranger插件jar包,再配一个ranger-hive-security.xml。插件会拦截Hive的授权调用,把原来的StorageBasedAuthorization或SQLStdAuthorization替换掉。
具体步骤大致是这样:
- 在Ranger Admin里创建Hive服务,填上Hive Metastore的JDBC连接信息。
- 下载对应的策略配置文件(
ranger-hive-security.xml和ranger-hive-audit.xml)。 - 把这两个文件放到HiveServer2的
/etc/hive/conf目录下。 - 重启HiveServer2。
嗯,这里要注意:Ranger Hive插件支持列级和行级过滤。列级就是“用户A只能看到name和age两列”,行级就是“用户A只能看到department=‘sales’的行”。
行级过滤示例:
-- 在Ranger策略中配置行过滤条件
-- 用户 alice 查询 employees 表时,自动追加 WHERE 条件
-- 策略表达式:
department = 'sales'
-- 实际执行时,SQL 被改写为:
SELECT * FROM employees WHERE department = 'sales';
我曾经遇到过一个坑:行级过滤和Hive的视图权限叠加时,会出现意想不到的笛卡尔积。排查了半天才发现是策略优先级没搞清楚。Ranger的策略优先级是:拒绝优先,然后按策略ID排序。行过滤条件会追加到SQL的WHERE子句里,如果视图本身也有过滤条件,两者是AND关系。
3.3 与Spark的集成:SQL和DataFrame两条路
Spark的集成稍微复杂一点。因为Spark有两种使用方式:SQL和DataFrame API。
先说Spark SQL。Ranger提供了SparkSessionExtension,通过拦截SQL解析后的逻辑计划来做授权。配置方式跟Hive类似:
# spark-defaults.conf 或 spark-submit 参数
spark.sql.extensions org.apache.ranger.spark.sql.extensions.RangerSparkSessionExtension
spark.sql.ranger.service.name my_spark_service
spark.sql.ranger.service.type 180 # 180 代表 Spark SQL 服务类型
spark.sql.ranger.plugin.dir /etc/ranger/my_spark_service/policycache
启动后,所有通过spark.sql()执行的SQL都会被Ranger拦截。授权逻辑跟Hive基本一致。
再说DataFrame API。这个就有点tricky了。DataFrame API不走SQL解析器,直接生成逻辑计划。Ranger的Spark插件通过RuleExecutor注入一个检查规则,在每个逻辑计划节点上做授权。
df.select("name", "age"),Ranger只能检查到表级别,列级检查需要额外配置。我建议在关键业务场景下,优先用Spark SQL,授权更精确。
另外,Spark 3.x以后,Ranger插件对catalog的支持也做了改进。如果你用了Iceberg或Delta Lake,记得在Ranger Admin里把对应的catalog注册进去,否则插件可能认不出表名。
3.4 与Trino的集成:轻量但功能完整
Trino(以前叫PrestoSQL)的Ranger集成,我个人觉得是最清爽的。它通过SystemAccessControl接口实现,不需要改Trino内核。
配置方式:
# etc/access-control.properties
access-control.name=ranger
ranger.service.name=my_trino_service
ranger.plugin.dir=/etc/ranger/my_trino_service/policycache
Trino的Ranger插件支持:
- Catalog、Schema、Table、Column级别的授权
- Session属性管理(比如限制用户设置某些session参数)
- 查询拦截(比如禁止
SELECT *)
不过有个限制:Trino的Ranger插件不支持行级过滤。因为Trino的查询引擎没有像Hive那样方便的WHERE子句注入机制。如果你需要行级权限,得在视图层面做,或者用Trino的Row-Level Security功能配合Ranger的列级策略。
ranger.plugin.policy.pollIntervalMs=30000。但Trino的查询通常很短(秒级),30秒的缓存可能导致策略更新不及时。我曾经遇到一个场景:管理员刚把某个用户的权限收回,结果用户还能查30秒。后来我把轮询间隔改成了10秒,问题解决。
3.5 策略同步机制:拉模式与推模式
Ranger的策略同步,核心是拉模式。插件定期向Admin发起HTTP请求,拉取增量策略。
流程是这样的:
- 插件启动时,全量拉取一次策略,写入本地文件缓存。
- 每隔
pollIntervalMs毫秒,插件发请求,带上本地策略的版本号。 - Admin比较版本号,如果有更新,返回增量策略(只返回变化的部分)。
- 插件合并增量策略到本地缓存,更新版本号。
为什么不用推模式?你想想看,一个集群可能有几百个节点,每个节点上跑着多个插件。如果Admin主动推,网络风暴和Admin压力都扛不住。拉模式虽然有一定延迟,但胜在可控。
不过,Ranger 2.0以后也引入了推模式的补充机制:通过Ranger Admin的REST API,可以主动通知插件刷新。但实际生产中,我很少用这个功能。拉模式配合15秒的轮询间隔,已经能满足绝大多数场景。
策略同步参数对比:
| 参数 | 默认值 | 说明 | 建议值 |
|---|---|---|---|
ranger.plugin.policy.pollIntervalMs |
30000 | 策略轮询间隔(毫秒) | 15000 |
ranger.plugin.policy.cache.dir |
/etc/ranger/{service}/policycache | 本地策略缓存目录 | 保持默认 |
ranger.plugin.policy.rest.client.connection.timeoutMs |
120000 | 连接Admin的超时时间 | 30000 |
ranger.plugin.policy.rest.client.read.timeoutMs |
30000 | 读取响应的超时时间 | 10000 |
最后说一句:策略同步的稳定性,直接决定了你的权限管控是否可靠。我见过不少团队,Ranger Admin挂了,插件本地缓存还在,业务照常跑——这就是拉模式的好处。但反过来,如果本地缓存文件损坏,插件会降级成拒绝所有请求,那可就炸了。所以,一定要监控本地缓存目录的磁盘空间和文件完整性。