在日常运维中,无论是测试环境还是生产环境,只要涉及多台服务器(集群)的安装与配置,几乎都离不开一项基础操作——为集群内的服务器配置SSH免密码登录。例如,在部署Hadoop、HBase这类分布式系统时,或者仅仅为了后续运维更方便,免密配置已成为不可或缺的标准步骤。
最近正好在搭建一套测试环境,借机把多台服务器之间实现SSH互相免密访问的配置过程详细整理了一下,并总结成以下步骤。整体流程大致分为:修改主机名、配置汇聚服务器密钥、汇聚其他服务器密钥、拷贝汇聚密钥文件、生成known_hosts文件、拷贝known_hosts文件。
1. 集群规划
先来看一下集群的拓扑结构:
| 主机IP | 主机名称 |
| 10.141.93.101 | dmz01 |
| 10.141.93.102 | dmz02 |
| 10.141.93.103 | inside01 |
| 10.141.93.104 | inside02 |
| 10.141.93.105 | inside03 |
| 10.141.93.106 | inside04 |
| 10.141.93.107 | inside05 |
| 10.141.93.108 | inside06 |
| 10.141.93.109 | inside07 |
| 10.141.93.110 | inside08 |
| 10.141.93.111 | inside09 |
| 10.141.93.112 | inside10 |
| 10.141.93.113 | inside11 |
| 10.141.93.114 | inside12 |
| 10.141.93.115 | inside13 |
| 10.141.93.116 | inside14 |
| 10.141.93.117 | inside15 |
| 10.141.93.118 | inside16 |
整个集群包含18台服务器:DMZ区域2台,INSIDE区域16台。它们分别承担Web服务器、应用服务器、数据库、缓存等角色。为了方便部署应用和统一管理,需要将这18台服务器全部配置为SSH互访免密码。
2. 修改主机名称
无论是刚安装的操作系统还是云主机,默认的主机名通常为“localhost”或“VM_75_173_centos”这类缺乏辨识度的名称,不利于区分各台服务器的用途。为了便于安装、部署和后续维护,第一步应先修改主机名。
修改主机名只需执行一条命令:
hostnamectl set-hostname inside01
执行完成后重新通过SSH登录,即可看到主机名已成功更新。
3. 配置汇聚服务器密钥
所谓“汇聚服务器”,是指从集群中挑选一台机器作为中心节点,其他所有服务器都向它建立SSH免密信任。这里我们选择dmz01(10.141.93.101)作为汇聚服务器,拓扑关系如下图所示:

其他所有服务器都需要向dmz01发起免密信任配置,dmz01便是整个集群的核心汇聚点。
生成密钥对的操作非常简单:
[root@dmz01 ~]# ssh-keygen -t rsa
执行后一路按回车键即可:
Generating public/private rsa key pair. Enter file in which to sa ve the key (/root/.ssh/id_rsa): [Enter] Enter passphrase (empty for no passphrase): [Enter] Enter same passphrase again: [Enter] Your identification has been sa ved in /root/.ssh/id_rsa. Your public key has been sa ved in /root/.ssh/id_rsa.pub. The key fingerprint is: 43:0d:08:18:ec:9e:d6:1f:ea:5f:04:30:0f:66:26:41 root@dmz01 The key's randomart image is: +--[ RSA 2048]----+ | oE+O. .. | | o= =. o | | . o . . | | . o | | . o S | | + . .. . | | . o .. . | | . .. | | .... | +------------------+
进入/root/.ssh目录,生成authorized_keys文件:
cat id_rsa.pub >> authorized_keys
结果如下所示:
[root@inside01 .ssh]# ll total 12 -rw-r--r-- 1 root root 395 Nov 12 16:25 authorized_keys -rw------- 1 root root 1675 Nov 12 16:24 id_rsa -rw-r--r-- 1 root root 395 Nov 12 16:24 id_rsa.pub
4. 拷贝其他服务器密钥
完成第3步之后,接下来需要依次配置dmz02、inside01……inside16等17台服务器的密钥。操作方法与第3步完全一致,每台机器上执行ssh-keygen生成密钥对即可。
当所有服务器的密钥都生成完毕后,需要将这17台服务器的公钥拷贝到汇聚服务器dmz01上。具体实现方式是通过ssh-copy-id命令,将本机的公钥添加到目标服务器的authorized_keys中。不过此处需要反向操作——在其他各台服务器上执行以下命令:
[root@dmz01 .ssh]# ssh-copy-id -i dmz01 (注意:这条命令实际上应该在dmz02上执行,原文如此。准确做法是:在每台其他服务器上执行 ssh-copy-id root@dmz01)
依次将17台服务器的公钥汇聚到dmz01上。
5. 拷贝汇聚密钥文件
汇聚完成后,dmz01上的/root/.ssh/authorized_keys文件已经包含了所有服务器的公钥。现在需要把这个汇总了全部公钥的文件,再拷贝回其他17台服务器,覆盖它们本地的authorized_keys文件。这样一来,每台服务器都拥有了集群内所有机器的公钥,从而实现相互免密。
在dmz01上执行scp命令进行分发:
[root@dmz01 .ssh]# scp authorized_keys dmz02:/root/.ssh/
[root@dmz01 .ssh]# scp authorized_keys inside01:/root/.ssh/
…
[root@dmz01 .ssh]# scp authorized_keys inside16:/root/.ssh/
root@inside16's password:
authorized_keys 100% 7104 6.9KB/s 00:00
注意,该过程中需要输入每台服务器的密码(因为此时尚未完全实现免密)。
拷贝完成后,测试SSH免密是否生效:
[root@dmz01 .ssh]# ssh dmz02
The authenticity of host 'dmz02 (10.141.68.179)' can't be established.
ECDSA key fingerprint is 22:49:b2:5c:7c:8f:73:56:89:29:8a:bd:56:49:74:66.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'dmz02,10.141.68.179' (ECDSA) to the list of known hosts.
Last login: Sat Nov 12 17:19:19 2016 from 10.141.93.186
可以看到,SSH登录dmz02时已不再需要输入密码,但系统提示需要将dmz02加入known hosts列表。这是第一次连接时的正常确认,后续再次连接便不会再出现此提示。
6. 生成known_hosts文件
从汇聚服务器依次SSH访问其他17台服务器,虽然免密登录已经生效,但每次都会弹出“是否将主机加入known hosts”的确认提示。为了避免后续自动化操作被中断,需要一次性生成完整的known_hosts文件。
操作方法十分简单:在dmz01上依次使用ssh命令登录每一台服务器(包括它自身),首次连接时输入yes确认即可。注意,连自己也要执行一次:
[root@dmz01 .ssh]# ssh dmz01
最后生成的known_hosts文件内容如下:

检查行长数:
[root@dmz01 .ssh]# wc -l known_hosts
18 known_hosts
每一行对应一台主机,说明dmz01已经记录了集群内全部18台服务器的host key。
7. 拷贝known_hosts文件
现在dmz01上已经拥有完整的known_hosts,但其他17台服务器之间尚未互相识别。最简单的方式就是将dmz01上的known_hosts文件拷贝到所有其他服务器:
[root@dmz01 .ssh]# scp known_hosts inside10:/root/.ssh/
[root@dmz01 .ssh]# scp known_hosts inside15:/root/.ssh/
...(依次拷贝到所有服务器)
全部拷贝完成后,整个集群便真正实现了SSH互访免密码。接下来进行一次完整的链路验证:
[root@dmz01 .ssh]# ssh inside10
Last login: Tue Nov 15 15:01:18 2016 from 10.141.93.186
[root@inside10 ~]# ssh inside15
Last login: Sat Nov 12 17:52:29 2016 from 10.141.93.186
[root@inside15 ~]# ssh dmz02
Last login: Sat Nov 12 20:05:59 2016 from 10.141.93.186
[root@dmz02 ~]# ssh dmz01
Last login: Thu Nov 17 23:56:05 2016 from 218.10.89.246
[root@dmz01 ~]# ssh inside15
Last login: Fri Nov 18 00:23:54 2016 from 10.141.114.152
从dmz01 → inside10 → inside15 → dmz02 → dmz01 → inside15,整个链路畅通无阻,无需任何密码提示。
8. 总结
整篇文章涉及的核心命令实际上只有以下几行:
hostnamectl set-hostname inside01 # 修改主机名
ssh-keygen -t rsa # 生成密钥对
ssh-copy-id -i dmz01 # 将本机公钥添加到远程服务器(实际使用时需指定远程主机)
只要将汇聚服务器和known_hosts文件分发到位,18台机器的互信配置大约半小时即可完成。希望这个流程能对大家在搭建集群时有所帮助。
