【是否原创】是
【首发渠道】asktug
为什么写这篇文章
- 论坛里经常看到对 tiup 集群管理的讨论,其中 ssh 相关的账户/权限问题比较多;
- 理解了 tiup cluster 的 ssh 操作,才能更好地使用 cluster 组件;
- 希望能给排查 ssh 问题的朋友一些思路。
目标读者
如果你:
- 了解 SSH 客户端的基础,知道常用的认证/登录机器方式
- 使用 tiup cluster 管理集群
- 对 tiup 如何连接集群节点有疑惑
- 遇到过 ssh 的问题,不知道为啥报错,不知道如何解决或者不知道最佳方案
- 遇到过 ssh 的问题,能试出"让问题消失"的办法,但是不知道背后的原因
- 没有遇到过 ssh 的问题,但是希望进一步了解 tiup ssh 的细节
那么你可以读一下这篇文章,我用了一个简单的、贯穿全文的例子,将 tiup cluster 工具用到的三个账户作为切入点,跟大家说说 tiup 如何连接远程机器,以及用什么方法来确认我们已经做好了集群部署准备。
而对 tiup cluster 和 ssh 很熟悉的朋友,就不需要往下看了。
一句话概述 tiup cluster 部署
管理员在中控机上执行 tiup 命令,把从 mirror 下载的发布包拷贝到集群机器上,分发配置和脚本,创建运行服务的账户,并使用 systemd 管理各种服务。
实际上这些操作就是经典的配置管理(configuration management) 操作,
也就是被 tiup 取代的 tidb-ansible 所做的事情。
例子
我们以这份 abc.topo.yaml
拓扑文件为例,直接用例子来说话
global:
user: ti-service
ssh_port: 2222
tidb_servers:
- host: 10.2.1.3
tikv_servers:
- host: 10.2.1.3
pd_servers:
- host: 10.2.1.3
另外,集群部署的命令行如下:
ti-ctr@host:~$ whoami
ti-ctr
ti-ctr@host:~$ tiup cluster deploy abc v5.1.1 abc.topo.yaml -u admin -i tidb.id_rsa
仔细看这个简单的例子,这里提到了三个账户:
账户 | 说明 | 用户的位置 |
---|---|---|
ti-ctr |
运行 tiup 的账户 | 中控机上 |
admin |
集群节点上的高权限账户 | 集群节点上 |
ti-service |
集群服务账户 | 集群节点上 |
也许你部署集群的时候,这三个账户全是 root 或者全是 tidb (没必要,也不推荐)
但是也没关系,不影响以下的讨论,自己代入合适的角色即可
运行 tiup 的账户
即例子中的 ti-ctr
账户,这个账户的存在"理所当然",毕竟你总要先有一个账户,用这个账户去安装 tiup 和配置 tiup mirror,然后才可能发生后面的事。
tiup 对这个 ti-ctr
账户都有哪些必需的要求呢?
- 能执行 tiup
- 能访问 mirror
- 能 ssh 登录集群节点
你可能觉得有点少,但是确实不需要更多了。
- 不需要
ti-ctr
在中控机上有高权限。对中控机来说,ti-ctr
可以是一个普普通通的账户,因为使用 tiup 不需要高权限。 - 不需要
ti-ctr
能免密码登录集群节点
关于 ssh 认证和登录,社区里很多人说,要提前配置好密钥对认证,让 ti-ctr
可以免密码登录集群节点。其实完全没必要。执行一下 tiup cluster deploy -h
就能看到,你可以在部署的时候,命令行指定如何认证(密钥对认证 or 密码认证)。
如果命令行没有指定私钥文件位置,也没有指定密码。那么 tiup 会尝试用 $HOME/.ssh/id_rsa
做密钥对认证,也会尝试交互询问你 ssh 密码。
📝 集群节点上,ti-ctr
账户可以不存在,比如例子中,ti-ctr
登录集群节点是用的 admin
账户。可以用下面的 ssh 命令来理解这一点(也可以作为部署前的验证手段):
ti-ctr@host:~$ ssh 10.246.201.3 -l admin -i tidb.id_rsa -p 2222
admin@host:~$ whoami
admin
思考
- 和 Ansible 默认使用系统原生的 OpenSSH 不同,tiup 默认使用了 go 实现的 SSH(某个开源的方案),损失了一些 OpenSSH 的功能,遇到复杂的认证环境,也许会出问题。(其实 tiup 也提供了实验性功能来支持用户选择 system ssh)
- tiup 把 ssh 连接的端口信息当成了集群配置(写死在拓扑文件里),TiDB集群上的服务,本应该和 sshd 服务无关的,现在把 sshd 的端口信息绑到了 TiDB 集群配置里,这样合理吗?
集群节点上的高权限账户
即例子中的 admin
账户
如果命令行中不指定的话,默认是本地当前账户,即执行 tiup 的用户,这也是常见的 ssh 客户端行为
这个账户是初始部署/扩容时的核心账户,没有这个账户,tiup 就无法在集群节点上:
- 创建服务账户(例子中的 ti-service)
- 创建目录,分发配置文件、脚本等
- 配置系统级 systemd units, 管理进程
- 管理操作系统和硬件的参数和配置
这些操作必须得高权限账户才能做,因此可以比较自然地列出,tiup 对这个 admin
账户的要求:
- 部署集群前,集群所有节点上都必须存在
- 可以免密码 sudo as root 执行所有命令
🛠️ 部署之前,你可以在所有集群节点上使用 admin
账户执行 sudo -ll
命令,来确认一下是否满足部署条件:
注意,执行该命令不能输入密码。从结果里重点看有没有 !authenticate
的条目,以及能否以 root 身份执行所有命令。比如类似这样的:
Sudoers entry:
RunAsUsers: root
Options: !authenticate
Commands:
ALL
或者这样的:
Sudoers entry:
RunAsUsers: ALL
RunAsGroups: ALL
Options: !authenticate
Commands:
ALL
如果你能从中控机登录到集群各节点(登录账户为admin
),而且 admin
的 sudo 规则也都完整,那么恭喜你!tiup cluster deploy 的操作起码不会遇到连接问题和权限问题了。
📝 重要!在 cluster deploy 操作完成之后,tiup 就抛弃了这个 admin
账户。后续的 tiup cluster 管理操作,直接使用了下面讨论的 ti-service
账户。
集群服务账户
即例子中的 ti-service
账户
如果配置文件中不写的话,默认是
tidb
这个账户是 tiup 用 admin
账户创建出来的。也就是说,admin
账户在集群节点上拥有高权限,可以创建和管理别的账户;admin
账户在集群节点上创建了 ti-service
,并赋予了 ti-service
高权限(足以管理集群内部服务,事实上它拥有最高的权限)。
虽然上面的例子里,为了文章的主题 我显式指定了账户名 ti-service
,但是,其实不用太关心这个账户,大部分情况下保持默认值即可。tiup 对它的要求也几乎没有,如果非要配置的话,起一个有效的用户名即可。
显然, ti-service
没有必要在部署前存在(最好是部署前不存在)。
部署之后这个账户的作用有两个:
- 在集群节点上,运行像 tikv-server, tidb-server 这样的进程
- tiup 使用该账户管理集群
最关键的就是这第二点。
刚开始部署集群时,tiup 就自己生成了一对密钥对,保存在 <tiup_home>/storage/cluster/clusters/abc/ssh/
目录下,并把公钥放到了集群各节点上 ti-service
账户的 authorized_keys 中。
$ tiup cluster list
🛠️ 执行 cluster list
,注意看第二列 User 和最后一列 PrivateKey,就是管理集群的 ssh 账户和它的私钥位置。集群部署/扩容完之后,tiup 的集群管理操作就都是用这个账户了。
因此如果集群部署后 tiup 还遇到了 ssh 认证失败的问题,而你想用 ssh 客户端来做一下验证,那你得像这样验证(忘掉之前的admin
吧,tiup 今后用的都是 ti-service
):
$ ssh -i <tiup_home>/storage/cluster/clusters/abc/ssh/id_rsa -l ti-service -p 2222
思考
如果总结一下 tiup 的这个做法:就是它把运行服务的账户 ti-service
同时也当成管理服务的账户。
这跟典型的服务部署思路不太一致,一般的做法是仅分配一个普通账户来运行服务,这个账户跟管理用的高权限账户无关。以本文的例子来说,就是 ti-service
只用来跑服务,当用户使用 tiup cluster 组件来管理集群时(比如 reload/stop/start 等),用户需要告诉 tiup 用哪个账户连接、如何连接集群。我觉得这样更好,可惜 tiup
不是这样做的。
另外, tiup 固定使用一个账户来管理集群,该账户的私钥文件还是单点存储在 tiup 中控机上的,那这算不算整个集群中单点故障风险最高的地方呢?所以,如果你不知道 tiup 本地数据丢了怎么办,那就积极做备份吧。