作者:杨文
DBA,负责客户项目的需求与维护,会点数据库,不限于MySQL、Redis、Cassandra、GreenPlum、ClickHouse、Elastic、TDSQL等等。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
一、背景:
客户在集群中查看用户信息 list users 时,报错 Error from server:xxx 。其实是个简单的查看语句,但魔法失灵了?下面我们将集群中用户角色等信息的查看方式做一个统一的分析说明。
二、cassandra 简单介绍:
2.1、Cassandra集群组成:节点(Node)、机架(Rack)、数据中心(Data Center);
- 节点(Node):运行Cassandra实例的服务器;
- 机架(Rack):一组相互靠近的Cassandra节点;
- 数据中心(Data Center):指逻辑机架的集合。
2.2、Cassandra通常跨多个数据中心存储数据副本,以确保高可用性,同时会将查询路由到同一数据中心的其他节点以实现最优性能,为了实现这一点,Cassandra使用两个内部协议来管理基于集群拓扑的数据路由:gossip和snitches。
- Cassandra使用Gossip协议实现了无中心架构。
- Cassandra使用Snitch机制实现了节点感知以提高性能。
- Cassandra使用环结构和令牌机制实现了集群的动态扩容和数据分区。
2.3、环结构和令牌:
- Cassandra将一个集群管理的数据表示为环,会为环中的每个节点分配一个或多个数据区间或范围,由一个令牌描述,确定数据在环中的位置。
- 通过使用散列函数为分区键计算令牌,将数据分配给节点。将该分区密钥令牌与各个节点的令牌值进行比较,以识别拥有该数据的范围,从而识别该节点。
- Cassandra将群集管理的数据表示为环。环中的每个节点被分配由令牌描述的一个或多个数据范围,该令牌确定其在环中的位置,令牌是用于标识每个分区的64位整数ID。
2.4、复制策略:
- 节点用作不同数据范围的副本。
- 如果一个节点发生故障,其他副本可以响应对该数据范围的查询。
- Cassandra以对用户透明的方式跨节点复制数据,复制因子是集群中接收相同数据的副本的节点数。
- 第一个副本将始终是声明令牌落入范围的节点,但副本的其余部分根据复制策略放置。
三、本地环境测试:
我们将通过实验测试进行 cassandra 用户角色查看时的各种情况说明。
实验环境:集群模式下跨数据中心。
数据中心 | 节点IP | 种子节点 |
---|---|---|
DC1 | 10.186.60.61、10.186.60.7、10.186.60.118、10.186.60.67 | 10.186.60.61、10.186.60.7 |
DC2 | 10.186.60.53、10.186.60.65、10.186.60.94、10.186.60.68 | 10.186.60.53、10.186.60.65 |
3.1、用户:
使用默认用户名 cassandra 和默认密码 cassandra 登录:
cqlsh 10.186.60.61 -u cassandra -p cassandra
创建用户:
cassandra@cqlsh> CREATE USER root WITH PASSWORD 'rootroot' SUPERUSER; cassandra@cqlsh> list users; name | super | datacenters ----------+-------+------------- cassandra | True | ALL root | True | ALL (2 rows)
说明:
- 只有 SUPERUSER 可以创建用户,创建的用户默认为 NOSUPERUSER;
- 只有 SUPERUSER 可以删除用户,任何用户不能删除自己。
- 如果要删除默认帐号,需要用新创建的账号重新登录,才可以删除默认账号;删除后,将不能再使用cassandra用户登录数据库了。
示例:
cqlsh 10.186.60.61 -u root -p rootroot ... root@cqlsh> drop user cassandra;
和其它分布式数据库一样,此时能查看所有用户的几种方式:
cqlsh 10.186.60.61 -u cassandra -p cassandra cqlsh 10.186.60.61 -u root -p rootroot cqlsh 10.186.60.7 -u cassandra -p cassandra cqlsh 10.186.60.7 -u root -p rootroot cqlsh 10.186.60.118 -u cassandra -p cassandra cqlsh 10.186.60.118 -u root -p rootroot cqlsh 10.186.60.67 -u cassandra -p cassandra cqlsh 10.186.60.67 -u root -p rootroot
错误的查看方式:
Connected to cluster at 10.186.60.53:9042 [cqlsh 6.0.0 | cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5] Use HELP for help. cassandra@cqlsh> LIST USERS; Unauthorized: Error from server: code=2100 [unauthorized] message="Unable to perform authorization of login permission: cannot achieve consistency level LOCAL_ONE"
可以看到不是同一个数据中心的是不能获得到权限的。
dc1数据中心中的节点是可以直接看该数据中心所有用户,但是dc2数据中心是不能直观的看dc1数据中心用户的。需通过system_auth.roles表,才能看到:
[cassandra@data05 ~]$ cqlsh 10.186.60.53 -u cassandra -p cassandra Connected to cluster at 10.186.60.53:9042 [cqlsh 6.0.0 | cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5] Use HELP for help. cassandra@cqlsh> select * from system_auth.roles; role | can_login | is_superuser | member _of | salted_hash ----------+-----------+--------------+------------+-------------------------------------------------------------- cassandra | True | True | null | $2a$10$bks/GM5rQFyw7nRQPC2sn.hxiMloTvIcG7Q6fqjSspq5970gGax3u root | True | True | null | $2a$10$eV88L/7bx08F9JH/4a.z1u/wvv2Yhv3xgIISRDKbd7/aeLvxkMzgs (2 rows)
说明:同一数据中心和跨数据中心都可以通过system_auth.roles表查看集群中所有的用户。
需要注意的是:虽然dc2数据中心有root用户,但却无法用root用户进行登录数据库。
[cassandra@data01 ~]$ cqlsh 10.186.60.53 -u root -p rootroot Connection error: ('unable to connect to any servers', {'10.186.60.53:9042': AuthenticationFailed('Failed to authenticate to 10.186.60.53:9042: Error from server: code=0100 [Bad credentials] message="unable to perform authentication: Cannot achieve consistency level LOCAL__ONE"',)})
3.2、角色:
创建角色:
create role appgroup1; create role appgroup2 with password='appgroup2' and login=true;
查看角色:
cassandra@cqlsh> list roles; role | super | login | options | datacenters ----------+-------+-------+---------+------------- appgroup1 | False | False | {} | ALL appgroup2 | False | True | {} | ALL cassandra | True | True | {} | ALL root | True | True | {} | ALL (4 rows)
同样的,跨数据中心dc2无法直接查看角色:
cassandra@cqlsh> list roles of appgroup2; NoHostAvailable: ('unable to complete the operation against any hosts', {<Host: 10.186.60.53:9042 dc2>: unavailable('Error from server: code=1000 [unavilable exception] message="cannot achieve consistency level LOCAL_ONE" info={\'consistency\': \'LOCAL_ONE\', \'required_replicas\': 1, \'alive_replicas\': 0}',)}) cassandra@cqlsh> cassandra@cqlsh> list roles; Unauthorized: Error from server: code=2100 [unauthorized] message="unable to perform authorization of super-user permission: cannot achieve consistency level LOCAL_ONE"
需用system_auth.roles表,才能看到:
cassandra@cqlsh> select * from system_auth.roles; role | can_login | is_superuser | member_of | salted_hash ----------+-----------+--------------+-----------+-------------------------------------------------------------- cassandra | True | True | null | $2a$10$bks/GM5rQFyw7nRQPC2sn.hxiMloTvIcG7Q6fqjSspq5970gGax3u root | True | True | null | $2a$10$eV88L/7bx08F9JH/4a.z1u/wvv2Yhv3xgIISRDKbd7/aeLvxkMzgs appgroup1 | False | False | null | null appgroup2 | True | False | null | $2a$10$8uOnMjPKA678nmeCF73eceme7Mezr.z775NQEIztpsPPUEQoxsd6G (4 rows)
3.3、汇总:
当两个数据中心都创建了用户时,两个数据中心中的节点都将不能使用list查看信息:
[cassandra@data01 ~]$ cqlsh 10.186.60.61 -u cassandra -p cassandra Connected to cluster at 10.186.60.61:9042 [cqlsh 6.0.0 | cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5] Use HELP for help. cassandra@cqlsh> LIST USERS; Unauthorized: Error from server: code=2100 [unauthorized] message="Unable to perform authorization of login permission: cannot achieve consistency level LOCAL_ONE" cassandra@cqlsh> quit [cassandra@data01 ~]$ cqlsh 10.186.60.61 -u root -p rootroot Connected to cluster at 10.186.60.61:9042 [cqlsh 6.0.0 | cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5] Use HELP for help. cassandra@cqlsh> LIST USERS; Unauthorized: Error from server: code=2100 [unauthorized] message="Unable to perform authorization of login permission: cannot achieve consistency level LOCAL_ONE" cassandra@cqlsh> cassandra@cqlsh> list roles; Unauthorized: Error from server: code=2100 [unauthorized] message="unable to perform authorization of super-user permission: cannot achieve consistency level LOCAL_ONE" cassandra@cqlsh> quit [cassandra@data01 ~]$ cqlsh 10.186.60.65 -u cassandra -p cassandra Connected to cluster at 10.186.60.65:9042 [cqlsh 6.0.0 | cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5] Use HELP for help. cassandra@cqlsh> LIST USERS; Unauthorized: Error from server: code=2100 [unauthorized] message="Unable to perform authorization of login permission: cannot achieve consistency level LOCAL_ONE" cassandra@cqlsh> cassandra@cqlsh> list roles; Unauthorized: Error from server: code=2100 [unauthorized] message="unable to perform authorization of super-user permission: cannot achieve consistency level LOCAL_ONE" cassandra@cqlsh> quit
当其中一个数据中心删除了自己创建的所有的用户时,另一个才能使用list查看。
dc2数据中心删除自己创建的用户:
cassandra@cqlsh> drop user yangw1; cassandra@cqlsh> LIST USERS; Unauthorized: Error from server: code=2100 [unauthorized] message="Unable to perform authorization of login permission: cannot achieve consistency level LOCAL_ONE" cassandra@cqlsh> list roles; Unauthorized: Error from server: code=2100 [unauthorized] message="unable to perform authorization of super-user permission: cannot achieve consistency level LOCAL_ONE"
此时,dc1数据中心中的节点,又可以通过list直接查看信息了:
[cassandra@data01 ~]$ cqlsh 10.186.60.61 -u cassandra -p cassandra Connected to cluster at 10.186.60.61:9042 [cqlsh 6.0.0 | cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5] Use HELP for help. cassandra@cqlsh> list users; name | super | datacenters ----------+-------+------------- appgroup2 | True | ALL cassandra | True | ALL root | True | ALL (3 rows) cassandra@cqlsh> list roles; role | super | login | options | datacenters ----------+-------+-------+---------+------------- appgroup1 | False | False | {} | ALL appgroup2 | False | True | {} | ALL cassandra | True | True | {} | ALL root | True | True | {} | ALL (4 rows)
3.4、总结:
1)哪个数据中心创建的用户和角色,哪个数据中心才能list查看,list只能查看自己数据中心创建的用户/角色,看其他数据中心的用户/角色就只能通过间接的方式看到;
2)由于两个数据中心都创建了用户/角色,所以系统分不清哪个用户/角色是哪个数据中心创建的,所以就都不让看;
3)删除角色/用户时,只能由创建它的数据中心进行删除;即:dc1数据中心创建的角色/用户,只能由dc1数据中心中的节点删除;用dc2数据中心中的节点删除时,就会报错。