当我们与银行和大型企业合作时,Kafka 很少是一个全新起步的话题。
更常见的情况是,Kafka 已经运行了多年。团队依赖它,关键数据在其中流动,平台也积累了大量运维决策、命名约定、服务账号、topic 模式以及访问规则的历史沉淀。等到一个组织决定迁移到 Confluent Platform 时,Kafka 早已不只是一个消息系统,而是生产骨干的一部分。
这一背景很重要,因为在这类环境中,迁移不仅仅是技术项目,更是风险管理工作。
在 Confluent 迁移的第一阶段,最安全的做法通常是尽可能少做改动。目标是先迁移平台基础、让它稳定下来,然后才引入更大的改进。认证与授权也是这个故事的一部分。现有的 Kafka 安装往往依赖 Apache Kafka ACL,因为 ACL 是开源 Kafka 中内置的授权模型。
不过,Confluent Platform 还提供了 RBAC:基于角色的访问控制。在组织规模上,RBAC 通常更易于理解,更契合平台治理,并能自然地与其他 Confluent 组件集成,例如 Metadata Service、Control Center 以及 Confluent for Kubernetes。
于是问题就变成:如何在不把访问控制变成高风险手工迁移的前提下,将一个现有的、基于 ACL 的 Kafka 资产迁移到 Confluent RBAC?
这正是我们构建 monedula-acl-rbac-converter 的原因。
为什么 ACL 到 RBAC 的迁移比看上去更难
一个只有少量 topic 和用户的小型 Kafka 集群可以手工迁移。你检查 ACL,确定对应的 RBAC 角色,创建绑定,验证访问,再移除旧的 ACL。
但大多数成熟的企业环境并不是这个样子。
在真实的部署中,你可能会遇到成百上千条 ACL 规则。有些由平台团队创建,有些由应用团队创建,有些来自自动化,有些虽然很旧但仍在使用,有些使用带前缀的 topic 模式,有些引用的是早已被重命名的服务用户,还有些是从多年无人触碰的脚本里导出的。
在这种情况下,手工迁移存在若干问题:
- 速度慢,
- 容易出错,
- 难以审查,
- 难以重复,
- 难以审计,
- 而且一旦开始清理就会变得危险。
创建新的 RBAC 绑定只是迁移的一半。更微妙的部分是证明新的绑定提供了与旧 ACL 相同的有效访问,然后才移除源 ACL。
正因如此,我们并不想要一个只是「翻译文件」的工具。我们想要的是一套迁移工作流。
转换器做什么
monedula-acl-rbac-converter 是一个命令行工具,它读取现有的 Kafka ACL,将其转换为 Confluent RBAC 角色绑定计划,并帮助运维人员以受控、可审计的方式执行迁移。
它可以从多种真实世界的来源读取 ACL,包括:
- 一个运行中的 Kafka 集群,
- 导出的
kafka-acls.sh --list输出, - JSON、YAML 或 CSV 转储文件,
- Strimzi
KafkaUser清单, - Confluent for Kubernetes 清单,
- 一个运行中的 Kubernetes 集群,
- 或者一个包含
kafka-acls --add ...命令的 shell 脚本。
最后这种情况在棕地(brownfield)环境中尤为有用。许多团队并不是从一份干净的导出开始的。相反,他们手里有一个最初创建这些 ACL 的旧安装脚本。
例如,输入脚本中可能包含这样的命令:
kafka-acls.sh \
--bootstrap-server kafka.example.com:9093 \
--command-config admin.properties \
--add \
--allow-principal User:svc-billing \
--operation Read \
--topic billing.events \
--group billing-consumer
kafka-acls.sh \
--bootstrap-server kafka.example.com:9093 \
--command-config admin.properties \
--add \
--allow-principal User:svc-billing \
--operation Describe \
--topic billing.events
转换器可以将这些 ACL 定义提取到一个规范化的 acls.json 文件中。从这里出发,它能生成一份经过审查的迁移计划、输出脚本或清单、将绑定直接应用到 Confluent MDS、验证结果,并为旧 ACL 生成清理脚本。
为高风险变更而设计的工作流
访问控制迁移需要护栏。一个错误的权限可能会破坏生产工作负载。一个过于宽泛的权限可能会引发安全事件。一个执行得过早的清理步骤可能会导致服务中断。
正因如此,生产工作流是明确的、分步骤的:
1. extract -> 创建规范化 ACL 快照
2. plan -> 将 ACL 转换为 RBAC 迁移计划
3. apply dry-run -> 预览 MDS 变更
4. apply -> 创建 RBAC role bindings
5. verify -> 检查有效访问权限
6. wait -> 让用户验证新路径
7. delete-acls -> 为旧 ACL 生成删除脚本
8. review + run -> 手动执行清理
每一步都会生成可被检查、审查、版本化或附加到变更请求中的产物。
该工具有意将计划与应用分离、将应用与验证分离、将验证与删除分离。这使得迁移更易于理解,在受监管的环境中运行也更安全。
示例:从一个 ACL 安装脚本迁移
假设起点是一个包含 kafka-acls.sh --add 命令的 shell 脚本。
1. 提取 ACL
首先,将 ACL 提取为一个规范化的 JSON 表示:
monedula-acl-rbac extract \
--from script \
--input setup-acls.sh \
--vars vars.yaml \
--out runs/billing-batch-1/acls.json
当脚本中包含变量时,可选的 vars.yaml 文件就很有用。该工具不会去猜测未解析的值。如果存在变量,应当显式提供它们,或者在迁移前先把脚本展开。
在这个阶段,输出仍然只是一个快照。没有任何外部状态被改变。
2. 创建迁移计划
接下来,将提取出的 ACL 转换为一个角色绑定计划:
monedula-acl-rbac plan \
--acls runs/billing-batch-1/acls.json \
--scopes scopes.yaml \
--rules rules.yaml \
--principals principals.yaml \
--out runs/billing-batch-1/plan.json
scopes.yaml 文件标识了 RBAC 绑定应针对的 Confluent 集群。可选的 rules.yaml 和 principals.yaml 文件让运维人员能够使转换适应自己的环境,例如将源 principal 映射到 MDS 所期望的 principal 格式。
计划步骤还会生成一份报告。这是整个工作流中最重要的审查点之一。它展示了每条源 ACL 变成了什么,并标记出任何无法映射或不应自动转换的内容。
3. 阅读报告
在应用任何内容之前,运维人员应当阅读生成的报告。
正是在这里,迁移工作变得可见。团队不必依赖一个黑盒式的转换,而是可以审查生成的绑定、调查未映射的 ACL,并决定是否需要自定义映射规则。
DENY 类型的 ACL 值得特别关注。Confluent RBAC 没有等价的拒绝语义,因此 DENY ACL 不会被悄无声息地转换。它们会被报告出来并单独处理。
4. 对应用步骤进行 dry-run
在 MDS 中创建角色绑定之前,先运行一次 dry-run:
monedula-acl-rbac apply \
--plan runs/billing-batch-1/plan.json \
--mds-url https://mds.example.com \
--mds-token-file ~/.confluent/token \
--dry-run
dry-run 会预览将要进行的 MDS 调用。它还会执行读取检查,以便可以幂等地跳过已存在的绑定。
这为运维人员在第一次真正变更之前提供了又一个检查点。
5. 应用 RBAC 绑定
在审查过 dry-run 输出之后,应用该计划:
monedula-acl-rbac apply \
--plan runs/billing-batch-1/plan.json \
--mds-url https://mds.example.com \
--mds-token-file ~/.confluent/token \
--confirm
应用步骤会在 Confluent MDS 中创建 RBAC 绑定。它被设计为可重复运行:如果某个绑定已存在,就会被跳过。
6. 验证有效访问
在应用 RBAC 绑定之后,验证它们确实授予了 ACL 最初提供的访问权限:
monedula-acl-rbac verify \
--plan runs/billing-batch-1/plan.json \
--mds-url https://mds.example.com \
--mds-token-file ~/.confluent/token
这比检查某个绑定是否存在更为有力。其目标是确认原始 principal、operation 和资源的有效访问。
这一区别在企业环境中尤为重要,因为身份传播、组成员关系、LDAP 集成或 scope 不匹配都可能导致一个绑定虽然存在却没有按预期工作。
7. 生成 ACL 删除脚本
只有在验证成功之后,并且经过运维人员定义的冷却期之后,才应移除源 ACL。
该工具不会直接删除 ACL。相反,它会生成一个由运维人员自行检查并运行的脚本:
monedula-acl-rbac delete-acls \
--plan runs/billing-batch-1/plan.json \
--verify runs/billing-batch-1/verify.json \
--bootstrap-server kafka.example.com:9093 \
--command-config admin.properties \
--principal User:svc-billing \
--confirm \
--i-understand-this-is-destructive
生成的产物包括:
delete-acls.sh
deleted-acls.json
rollback.sh
这是一个有意设置的人工检查点。运维人员可以打开脚本,审查每一条 kafka-acls --remove 命令,逐个 principal 地运行它,并在迁移稳定之前一直保留回滚脚本。
针对不同运维模式的不同输出
并非每个组织都想要相同的应用模式。
有些团队乐于直接应用到 MDS。另一些团队则需要每一次变更都经过变更控制流程、GitOps 流程或外部 CD 流水线。
转换器通过输出不同类型的产物来支持这些场景:
# 包含 Confluent CLI role-binding 命令的 shell 脚本
monedula-acl-rbac emit \
--plan runs/billing-batch-1/plan.json \
--format script \
--out-dir emit/
# Confluent for Kubernetes 清单
monedula-acl-rbac emit \
--plan runs/billing-batch-1/plan.json \
--format cfk \
--out-dir emit/
# 面向 MDS REST API 的 curl 命令
monedula-acl-rbac emit \
--plan runs/billing-batch-1/plan.json \
--format mds-curl \
--out-dir emit/
这使得该工具既适用于动手实操的迁移工作,也适用于那些基础设施变更必须通过独立审批与部署系统的环境。
为真实迁移中的混乱而构建
我们尽力去支持那些在实际 Kafka 资产中会出现的输入和约束,而不仅仅是干净的演示场景。
这包括:
- 实时 Kafka 提取,
- 文本导出,
- 结构化文件,
- Kubernetes 原生资源,
- 现有的 Confluent for Kubernetes 清单,
- 旧的安装脚本,
- principal 重映射,
- 自定义转换规则,
- dry-run 执行,
- 直接 MDS 应用,
- 输出的脚本和清单,
- 有效访问验证,
- 删除脚本生成,
- 回滚产物,
- 以及用于可重复迁移批次的 status/diff 命令。
最终得到的是一款既可用于探索、又可用于生产级迁移的工具。
对于小型实验,一次性的 convert 命令可以在单个步骤中完成提取、计划和脚本输出:
monedula-acl-rbac convert \
--from yaml \
--input acls.yaml \
--scopes scopes.yaml \
--rules rules.yaml \
--principals principals.yaml \
> bindings.sh
对于生产环境,推荐采用明确的流水线路径,因为它能保留审计产物和审查点。
结语
从 Kafka ACL 迁移到 Confluent RBAC 不只是一个语法转换问题。
它是对一个运行中的数据平台授权模型的一次受控变更。在大型组织中,尤其是在银行业和受监管行业里,这种变更需要是可审查、可重复、可审计的,并且在可能的情况下是可逆的。
我们构建 monedula-acl-rbac-converter,是因为我们不断看到同样的模式:Kafka 早已就位,ACL 早已就位,而团队希望在迁移压力之下采用 Confluent RBAC,却不必手工翻译成百上千条规则。
这款工具的目的不是隐藏迁移过程,而是让它变得可见。
提取当前状态。规划目标状态。审查报告。Dry-run 变更。审慎地应用。验证有效访问。生成清理脚本。审查它们。然后,只有在你准备好时,才移除旧的 ACL。
这正是我们希望访问控制迁移所采用的那种工作流。
我们构建它,是因为它对我们有用。我们也希望它对其他人同样有用。
你可以在 GitHub 上找到 monedula-acl-rbac-converter。如果你发现了 bug 或有改进建议,欢迎提交 issue。