ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ClickHouse登录报错Code 516:从用户创建到认证排查全解析

ClickHouse登录报错Code 516:从用户创建到认证排查全解析 自己在生产环境用ClickHouse时最常接到的一类报障就是账号明明建好了登录却失败客户端直接抛一串Code: 516。很多同学第一反应怀疑网络不通、端口没开折腾半天才发现是认证层的问题。516这个错误码在ClickHouse里对应的全称是UNKNOWN_USER含义非常直接服务端在验证登录时找不到一个“与本次连接匹配”的用户。注意我的措辞不是简单的“用户不存在”而是“匹配不上”。这里面的差别极大很多诡异问题就是因为场景不匹配造成的。这篇文章我会把创建用户、登录、排查516的完整链路拆开讲包含SQL写法、三种验证方式、隐藏坑点和常见案例照着流程走基本上十分钟之内能把问题定位到具体原因上。1. 先把code 516的逻辑搞清楚1.1 516在认证链路里到底处于哪一环ClickHouse的登录认证服务端是分步骤检查的。第一步先看“用户是否存在”第二步看“该用户是否允许从当前IP/主机登录”第三步才校验密码。516出现的位置在前两步。再叠加另一个高频错误码198AUTHENTICATION_FAILED来看逻辑就非常清晰了错误码语义产生条件排查方向516UNKNOWN_USER用户名在系统里找不到或客户端来源地址不在该用户允许的HOST范围内system.users表、HOST配置198AUTHENTICATION_FAILED用户存在但密码校验不通过密码明文、认证方式、特殊字符转义很多刚接触ClickHouse的人以为516就是“密码错”其实密码错了通常是198。如果你看到的报错确实是516先把“用户匹配”作为第一怀疑对象。这里有个比较误导人的地方如果你用clickhouse-client连接很可能因为users.xml里残留了同名用户、或者本机配置文件指向了别的用户目录导致服务端实际看到的用户名和你以为的用户名不一致此时报的也是516。所以第一步绝不是盯着密码猜而是确认服务端视角里的用户到底是什么状态。1.2 为什么“用户明明存在”还会516我把实际排查中遇到的情况归类了一下最常见的是这四类第一用户名拼写或大小写不一致。ClickHouse的用户名是区分大小写的AppReader和appreader是两个完全不同的用户。手滑把P大写写成小写登录就会516。第二HOST范围没放进去。这个特别典型很多教程里创建用户时不写HOST子句或者只写了HOST IP 127.0.0.1本地测试没问题。一旦从局域网的另外一台机器、或者Docker容器里连接来源IP不在白名单里服务端视同“这个用户在当前连接上不存在”直接516。第三连接到了错误的实例或者错误的端口。ClickHouse默认的Native协议端口是9000HTTP端口是8123。如果机器上装了多个ClickHouse而客户端实际连接的是另一个实例服务端里自然没有你创建的那个用户。第四users.xml配置目录和SQL管理系统冲突。新版ClickHouse支持CREATE USER创建用户但如果users.xml里存在同名用户很多版本会以配置文件为准SQL里创建的用户虽然写在system.users里实际登录时却走了配置文件那一套性质上等于“没这个用户”。2. 创建用户的正确姿势从语法到权限2.1 先确认你的ClickHouse支持SQL管理用户老版本ClickHouse管理用户只能改users.xml新版本才支持SQL方式。第一步先看一眼版本clickhouse-client --query SELECT version()如果你的版本低于20.4建议直接升级否则后续所有基于SQL的用户管理都无从谈起。另外还要确认配置里开启了access_management在config.xml中对应user_directories users_xml pathusers.xml/path access_management1/access_management /users_xml /user_directories如何确认当前生效的用户目录类型可以查系统表SELECT * FROM system.user_directories;通常能看到至少一个local directory或users_xml条目。如果你启用了多个目录注意它们的优先级这直接影响后面同名用户冲突的排查。2.2 创建用户时把HOST写对能省一半的排查时间很多人习惯写最简单的CREATE USER app_rw IDENTIFIED BY password;这句话本身没问题默认HOST是全部允许。但如果你加了一个HOST限制就要非常小心。看这个例子CREATE USER IF NOT EXISTS app_rw IDENTIFIED WITH sha256_password BY Pssw0rd! HOST IP 127.0.0.1, 192.168.10.15;这个用户只能在本地或者192.168.10.15这台机器上登录。其他地址全部516。HOST子句支持多种写法HOST IP 192.168.%使用IP网段通配HOST LIKE %example.com使用域名后缀匹配HOST REGEXP ^.*\.internal$使用正则匹配HOST ANY表示允许所有来源HOST NONE表示不允许任何来源我的建议是开发环境直接不写HOST或者写HOST ANY生产环境宁可写严一点比如内网网段但一定要把运维机器、监控机器、ETL机器的IP都列进去否则上线后第一个接到516报障的就是你自己。2.3 密码认证方式怎么选IDENTIFIED BY和IDENTIFIED WITH xx BY的差别很多人不清楚。直接记结论-- 方式1不指定密码算法默认使用sha256_password CREATE USER user1 IDENTIFIED BY secret; -- 方式2显式指定明文密码 CREATE USER user1 IDENTIFIED WITH plaintext_password BY secret; -- 方式3显式指定SHA256 CREATE USER user1 IDENTIFIED WITH sha256_password BY secret; -- 方式4旧协议兼容 CREATE USER user1 IDENTIFIED WITH double_sha1_password BY secret;生产环境不推荐plaintext_password因为密码会以明文形式存在元数据里虽然ClickHouse内部存储也不是纯明文但风险比SHA256高。double_sha1_password是给老的MySQL客户端协议用的日常不需要。如果你用HTTP接口登录密码走Basic Auth服务端同样按对应算法验证。这里经常出的坑是建用户时用了sha256_password但某些老工具默认用double_sha1_password发密码两边算法对不上结果就是“密码明明是对的却登不进去”。3. 一次完整创建到登录验证的实操闭环3.1 从建用户到给权限的完整命令直接给一套可复制的流程。假设我要建一个只读账号report_ro用于报表查询clickhouse-client进入命令行后依次执行CREATE DATABASE IF NOT EXISTS app_data; CREATE USER IF NOT EXISTS report_ro IDENTIFIED WITH sha256_password BY Report#2024! HOST IP 127.0.0.1, 192.168.10.%; GRANT SELECT ON app_data.* TO report_ro;这里有个很多人问的点只给SELECT用户登录后能执行SELECT 1吗能。SELECT 1不涉及任何库表属于不依赖细粒度权限的表达式查询。但如果执行SELECT * FROM app_data.orders没权限就会报Code: 497之类的“Not enough privileges”错误。如果你想给他查看当前库表的能力但不允许改数据可以再加GRANT SHOW TABLES ON app_data.* TO report_ro; GRANT SHOW DATABASES ON *.* TO report_ro;这些权限用完即止不要顺手把ALTER、DROP也给了。3.2 本地用Native客户端验证登录退出当前客户端用新用户登录clickhouse-client --host 127.0.0.1 --port 9000 --user report_ro --password Report#2024!登录成功后执行SELECT currentUser();输出应该是report_ro。这里顺带提一下密码尽量用单引号包住尤其是包含!、#、$这类符号时双引号在部分shell里还会做变量展开单引号最稳。如果你在命令行里不写--password客户端会交互式询问这是最安全的方式也不容易把密码留在shell历史里。3.3 HTTP接口的验证方式除了原生客户端ClickHouse的HTTP接口也是一种很常用的登录验证手段而且排查问题时更快curl -u report_ro:Report#2024! http://127.0.0.1:8123/?querySELECT%201响应里会直接返回1。如果返回Code: 516说明HTTP端口上的认证同样失败。这里的技巧是-u传用户名密码时客户端会自动做Basic Auth编码比在URL query里手动写userxxxpasswordyyy安全得多——后者一旦密码里有或者%极易被解析错。顺便说一句如果返回的是Code: 198那么用户是匹配到的只需要改密码或者重新确认密码本身就够了返回Code: 516则继续回上面查system.users。3.4 登录后立刻检查实际权限登录不是终点权限对不对才是重点。执行SHOW GRANTS FOR report_ro;输出里应该包含你之前的授权。再尝试SELECT * FROM app_data.orders LIMIT 1;如果这个查询返回Not enough privileges检查授权粒度如果返回Table doesnt exist则是库表不存在方向和516已经无关。4. 登录排查五连问和定位手段4.1 把516的排查流程固化成五个问题我每次处理类似报障都按固定顺序问自己用户真的在服务端存在吗去system.users查一下用SELECT name, auth_type FROM system.users;一条命令就能看到全部用户。用户允许的来源包含当前连接地址吗重点看HOST信息。密码一字不差吗特别注意隐藏字符、大小写、中文输入法混入的全角字符。端口和协议对吗9000是Native8123是HTTP9004是MySQL协议9005是PostgreSQL协议别串了。有没有同名用户被users.xml或其他目录抢先匹配列维一下这五个问题覆盖了我在生产中遇到过的90%的516。尤其是第二条是最容易被忽略的。现在容器化部署特别多你在宿主机上测试用的是127.0.0.1等应用从容器里连过来源IP变成了Docker网段172.x.x.x如果HOST没放开516就在所难免。4.2 用服务端日志直接看认证结果有时我们很难从客户端完整看到具体原因。最有效的是去服务端看日志sudo tail -n 200 /var/log/clickhouse-server/clickhouse-server.log或者journalctl -u clickhouse-server --since 10 minutes ago --no-pager抓关键信息Unknown user xxx基本可以定位到“用户名不存在”或“用户被HOST过滤”Authentication failed: password incorrect是密码错误对应198User xxx is not allowed to connect from host ...非常明确地告诉你HOST不匹配日志里信息越明确越没必要猜。拿不准的时候先看日志再动手改配置能少走很多弯路。4.3 两个高频场景复现场景一开发同学在测试机创建了用户本机能登录但跑批服务器报516。查system.users发现用户存在查HOST定义发现自己只写了HOST IP 127.0.0.1。跑批机的IP是10.0.0.88显然不在白名单。解决方式ALTER USER report_ro HOST IP 127.0.0.1, 10.0.0.%;改完再登录就正常了。这里用到的是ALTER USER不用重建用户。场景二用户在SQL里创建了app_rw测试也能登上。隔天重启后登录报516。查system.users用户还在但system.user_directories里显示有两个目录users.xml里也定义了一个同名但密码不同的app_rw。此时配置文件优先级盖过了SQL用户。解决方式从users.xml中移除同名用户配置重启服务端即可。5. 高频踩坑清单和一些额外提醒5.1 速查表故障场景报错样例核心原因处理建议用户不存在Code: 516, Unknown user用户名写错/未创建system.users确认来源IP被限制Code: 516日志里有not allowedHOST范围不含当前IPALTER USER ... HOST IP密码错Code: 198密码明文不一致重置密码密码含特殊字符Code: 198或连接直接失败shell转义、URL编码单引号包裹、用-u连错端口连接超时或5169000/8123混淆确认端口协议同名配置覆盖516但system.users有记录users.xml同名清理配置文件算法不一致198客户端与用户认证方式不匹配统一用sha256_password忘记授权Code: 497用户存在密码对但无权限GRANT相应权限我建议把这个表存下来报一个516过一个效率提升非常明显。5.2 两个容易被忽视的运维细节第一个ClickHouse的SQL用户元数据默认存放在/var/lib/clickhouse/access/目录下做备份的时候一定要把这个目录也带上。很多备份策略只备份data目录恢复到一个新实例后发现所有SQL用户全部丢失应用又回退到匿名登录风险很大。第二个改造密码时用ALTER USER而不是先DROP USER再重建。DROP会同时级联清理授权重建后如果忘记重新GRANT你还会遇到另一个看似“权限丢失”的问题。能原地改就原地改ALTER USER report_ro IDENTIFIED WITH sha256_password BY NewPass9!;5.3 还有一个顺带提一下的重启坑如果你之前手工动过system库下的表比如在default库里建过一个同名的query_log表或者多次手动创建系统表副本重启ClickHouse时可能碰到failed to flush system log ... already exists这种报错。这个问题跟516没有直接关系但两者经常一起出现在同一批维护操作里。原因多半是系统表元数据与内部附加表发生了命名冲突处理时需要把多余的同名表清理或重命名后再启动。操作前强烈建议先备份/var/lib/clickhouse下的相关目录尤其是不应随意改动系统库表结构。6. 从实际案例中提炼出的最后建议处理516这类认证问题最忌讳的就是“觉得密码没问题”然后反复重试。每次重试都会在服务端产生一条认证日志但不会有任何实质性帮助。正确做法是先确认用户匹配确认来源地址再谈密码。我个人的操作习惯是三层验证先SELECT * FROM system.users确认用户存在然后SHOW GRANTS FOR 用户名确认权限再分别用Native客户端和HTTP接口各登一次。三层都过基本可以判定问题不在认证层哪一层不过就对应处理哪一层。这个方法在几次线上故障中帮我快速规避了“猜密码”的弯路也推荐给你。如果你现在正好被516卡住按照上面的顺序查一遍大概率能直接找到原因。如果你是刚部署ClickHouse前面提到的创建语法和users.xml冲突问题建议提前读完再开工能省下不少折腾时间。
返回列表