目录标题
分片集群本身是如何同步用户的
✅ 问题核心
ClickHouse 分片集群本身并不会自动同步用户信息。
📌 背景知识:ClickHouse 用户存储方式
ClickHouse 用户信息默认存储在本地,具体有以下几种方式:
类型 | 说明 | 是否自动同步 |
---|---|---|
users.xml 或 users.d/*.xml | 本地 XML 文件配置用户 | ❌ 不同步 |
/var/lib/clickhouse/access/ | 二进制持久化用户数据目录(动态 SQL 创建) | ❌ 不同步 |
LDAP、PAM、Kerberos | 外部统一身份认证系统 | ✅ 可通过配置共享 |
ZooKeeper(用于表和数据的复制) | ❌ 不涉及用户 |
因此:
即使你创建了一个分片集群,ClickHouse 也不会自动同步各分片之间的用户配置(不管是 XML 用户还是 SQL 创建的用户)。
🚨 用户同步是运维职责而非 ClickHouse 内建机制
数据类型 | 是否自动同步 | 同步机制 |
---|---|---|
数据表结构(ReplicatedMergeTree) | ✅ | 通过 ZooKeeper |
数据行内容 | ✅ | 分片或副本复制 |
用户、角色、权限 | ❌ | 需要人工或系统工具同步(如 Operator) |
✅ 那如果是「直接部署的分片集群」,如何统一用户?
你可以用以下几种方式来「统一分片集群的用户信息」:
✅ 方式一:使用配置管理同步(最常见)
将统一的用户配置文件,通过以下方式同步到所有分片节点:
- 使用 Puppet/Ansible/SaltStack 等自动化工具;
- 使用 Kubernetes 下 ConfigMap/Secret 挂载;
- 手动拷贝
/etc/clickhouse-server/users.d/*.xml
或/var/lib/clickhouse/access/*
; - 使用脚本打包
/var/lib/clickhouse/access
,解压到其他节点(如你刚才所做)。
✅ 方式二:在每个分片使用 SQL 手动创建
CREATE USER admin IDENTIFIED WITH plaintext_password BY 'secure_pass';
GRANT ALL ON *.* TO admin;
你需要 在每个分片副本都执行一次,因为该命令只影响本节点。
⚠️ 但这类 SQL 创建用户默认写入 /var/lib/clickhouse/access
,建议持久化存储卷挂载,避免 Pod 重启丢失。
✅ 方式三:使用外部统一认证(推荐用于中大型系统)
-
使用 LDAP/AD + ClickHouse 配置:
<users> <user_from_ldap> <authentication> <ldap_server>ldap1</ldap_server> </authentication> </user_from_ldap> </users>
-
多个分片配置一样的
ldap_servers.xml
文件,就可以统一认证; -
修改密码、权限都在 LDAP 统一控制,无需 ClickHouse 内部同步。
✅ 方式四:Operator 自动化同步(若权限配置完整)
- ClickHouse Operator 会尝试通过
pods/exec
同步/var/lib/clickhouse/access
; - 要求 Operator 具备
exec
权限,且每个 Pod 可正常访问; - 一般在
chi.yaml
配置用户部分后自动生效:
spec:
configuration:
users:
admin:
password: my_secure_pass
✅ 小结对比
同步方式 | 是否推荐 | 适用场景 |
---|---|---|
手动复制 /var/lib/clickhouse/access | ✅ 临时解决 | 快速同步集群内用户 |
XML 配置统一挂载 | ✅ 推荐 | Kubernetes/自动化部署 |
SQL 手动建用户 | ⚠️ 不推荐(容易遗漏) | 非自动化环境 |
LDAP/外部认证 | ✅ 推荐 | 多团队、多环境 |
Operator 自动 sync_user | ✅ 推荐 | 需配置好 RBAC 权限 |
✅ 总结回答你的问题:
如果不是从单节点转换为分片,而是一开始就部署的是分片集群,ClickHouse 也不会自动同步用户配置。
你需要手动或自动配置每个节点的用户信息。
如果你希望我生成一个示例配置(ConfigMap 统一挂载 / Operator 用户配置 / LDAP 接入),请告诉我你具体的部署方式,我可以按需提供。
单机->分片
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access .
kubectl cp /tmp/access.tar.gz qfusion-admin/ck-9260f445-replica1-0:/tmp/access.tar.gz
kubectl exec -it qfusion-admin/ck-9260f445-replica1-0 -- tar xzf /tmp/access.tar.gz -C /var/lib/clickhouse/access
kubectl delete pod ck-9260f445-replica1-0 # 重启生效
你执行的两个命令如下:
第一个命令:
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access
这个命令报错:
tar: Cowardly refusing to create an empty archive
第二个命令:
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access .
这个命令执行成功。
✅ 原因解析
📌 原因本质:
tar
的 -C
参数表示“切换到这个目录”,而你没有提供任何要打包的对象,所以:
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access
相当于说:“进入 /var/lib/clickhouse/access
目录后,什么都不打包。” → 于是报错:拒绝创建空归档。
✅ 正确写法解释:
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access .
这个命令的含义是:
“进入
/var/lib/clickhouse/access
目录后,把当前目录(即.
)下的所有文件和子目录打包进/tmp/access.tar.gz
”。
✅ 所以这个写法才是正确的。
🔁 总结
命令 | 是否正确 | 原因 |
---|---|---|
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access | ❌ | 没有指定要打包的内容 |
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access . | ✅ | 指定打包当前目录下的所有内容 |
如果你接下来要 拷贝该 access 文件 到其他分片节点进行用户同步,可以继续使用如下命令:
tar czf /tmp/access.tar.gz -C /var/lib/clickhouse/access .
kubectl cp /tmp/access.tar.gz qfusion-admin/ck-9260f445-replica1-0:/tmp/access.tar.gz
kubectl exec -it qfusion-admin/ck-9260f445-replica1-0 -- tar xzf /tmp/access.tar.gz -C /var/lib/clickhouse/access
kubectl delete pod ck-9260f445-replica1-0 # 重启生效