首页 / 资讯中心 / 文章详情

CentOS 7集群配置:SSH免密登录与主机名设置全攻略

CentOS 7集群配置:SSH免密登录与主机名设置全攻略 ★ FEATURED ARTICLE
大家搭建集群的时候应该都遇到过这种场景明明只有三台机器来回切换还要一遍遍输密码跑批处理脚本时因为中间需要人工输密码动不动就断开更难受的是节点一多IP地址根本记不住还得不停查表格确认哪台对应哪台。尤其在CentOS 7环境下搭Hadoop、Kafka、数据库集群主机名和SSH免密这两件事没做好后边基本寸步难行。我这篇就专门把CentOS 7集群的SSH免密登录和主机名配置完整梳理一遍从最基础的主机名规划讲起到hosts解析、密钥分发、批量脚本最后把各种踩过的坑也都列出来方便你照着配置到生产环境。1. 为什么集群第一件事就是配置主机名和免密1.1 先想清楚一件事你的集群是“认IP”还是“认名字”很多人一开始觉得机器之间通信用IP不就行了为什么非要折腾主机名我在实际运维里见过不少例子项目初期所有脚本里写死IP节点少的时候还能忍一旦扩到几十台就彻底乱套。因为你写脚本的时候看到的IP毫无语义node03和db-backup-01哪个是备份节点看IP根本看不出来。更重要的是主流集群组件基本都依赖主机名通信。Hadoop的core-site.xml里写的是hdfs://master01:8020ZooKeeper的配置里填的是server.1node01:2888:3888数据库主从同步的配置文件里也经常用到主机名。这些组件启动时会做主机名解析如果解析不到服务直接起不来而且报错信息往往特别隐晦查半天才发现是hosts漏配了。所以集群配置的顺序应该是先规划主机名再配置hosts解析最后才做SSH免密。主机名和hosts是地基SSH免密是地上建筑顺序反了或者漏了一环后边全得返工。1.2 这套配置到底解决什么问题SSH免密和主机名配置解决的是三个层面的痛点。第一操作层面你从管理机ssh到任何一台节点不用输密码scp传文件也不用输密码批量执行命令的脚本才能跑得起来。没有免密所谓的自动化脚本全是空话因为脚本执行到一半停下来等你输密码这自动化就断了。第二身份识别层面主机名是有语义的标签。node01、node02、node03一眼就能看出是序号节点master、worker、storage这种命名方式体现出角色。配置好/etc/hosts之后所有节点用统一的解析表不会出现同一台机器在这个节点叫node01、在那个节点叫vm-12这样的情况。第三程序通信层面集群框架的节点互相发现、心跳检测、数据同步都需要稳定的地址解析。我们曾经在生产环境遇到过一个问题某套分布式存储集群经常出现节点掉线查了好久发现是因为节点启动时解析主机名走的是DNS而DNS偶尔抽风导致解析超时。后来在/etc/hosts里全量写入节点映射问题立刻消失。2. 配置前的主机名规划与整体思路设计2.1 节点规划应该怎么做在动手改配置之前先把整个环境的结构画出来。一套典型的CentOS 7测试集群建议至少规划3个节点既能完整的跑的起多数分布式框架又不至于管理成本太高。以我常用的规划为例节点角色主机名IP地址用途说明主节点master01192.168.56.101部署NameNode、主数据库等管理角色工作节点1node01192.168.56.102运行计算任务、数据节点工作节点2node02192.168.56.103运行计算任务、数据节点这套规划的思路是master01负责管理和调度node01和node02干活。主机名不要起得太随意比如test1、test2这种看起来方便实际用起来完全不知道节点是干什么的。命名最好体现角色加序号字母全小写不要带特殊字符这是集群软件的通用约定。2.2 CentOS 7主机名的三层概念CentOS 7里主机名其实有三个概念静态主机名、瞬态主机名、pretty主机名。最初接触的时候我也被搞晕过。静态主机名static hostname存在/etc/hostname文件里是内核和系统初始化时用的瞬态主机名transient hostname是运行时临时分配的一般来自DHCP或者DNS重启后就没了pretty主机名是给人看的可以带空格和特殊字符纯展示用。用hostnamectl命令操作时默认改的就是静态主机名。执行hostnamectl set-hostname master01系统会同步修改/etc/hostname文件同时把瞬态主机名也一起改了这是CentOS 7推荐的做法。2.3 hosts文件是集群的“内部通讯录”/etc/hosts文件的本质是本地DNS解析表。集群内网里搭DNS服务器当然也可以但中小型集群完全没必要引入额外依赖直接在每台机器的hosts文件里写全所有节点映射简单、稳定、不依赖外部服务。hosts文件配置有一个原则把127.0.0.1 localhost localhost.localdomain放着别动不要把主机名映射到127.0.0.1上。然后追加内网IP和主机名的映射192.168.56.101 master01 192.168.56.102 node01 192.168.56.103 node02这里要强调一个细节hosts文件里每行格式是“IP地址 主机名”IP地址在最前面这个顺序不能反了。另外有些框架会用完全限定域名FQDN所以也可以写成192.168.56.101 master01 master01.example.com第二列是短主机名第三列是FQDN。如果你的环境没有内部域名第二列就够用了。2.4 配置顺序为什么重要整体的执行顺序是改主机名 → 配hosts → 做SSH免密。原因很简单SSH免密的第一步是生成密钥然后把公钥分发到目标机器。分发的时候如果用主机名来指定目标机器比如ssh-copy-id node01那前提就是本地能解析node01这个主机名。如果hosts没配好ssh-copy-id就会报“Could not resolve hostname node01”直接卡住。还有一个隐蔽的问题hostnamectl set-hostname之后当前终端的主机名提示符不会立刻变要重新登录或者执行exec bash才能看到变化。如果你这个时候直接去做SSH免密旧的终端显示的还是旧名字容易让人产生“配置没生效”的错觉。3. 主机名配置实操与验证细节3.1 三台机器依次修改主机名在每台机器上分别执行对应的命令# master01上执行 hostnamectl set-hostname master01 # node01上执行 hostnamectl set-hostname node01 # node02上执行 hostnamectl set-hostname node02执行完之后用hostnamectl查看确认重点看Static hostname那一行hostnamectl还有一种老办法是手动编辑/etc/hostname文件把原来的内容删掉写入master01然后重启network服务。这个方法在CentOS 7上也能用但既然有hostnamectl这么方便的工具没必要再去手动编辑文件除非你的系统被裁剪过才用老方法。3.2 写好各节点的hosts文件在每一台机器的/etc/hosts文件里追加集群所有节点的映射。我用统一的模板cat /etc/hosts EOF 192.168.56.101 master01 192.168.56.102 node01 192.168.56.103 node02 EOF为什么三台机器都要写全因为集群里的节点会互相访问。Node01访问master01的时候它自己也能解析master01的IP不是只有管理机需要知道所有节点。很多新手只在自己本地电脑上配了hosts结果节点之间互相解析失败框架照样起不来。3.3 验证主机名配置是否生效配置完成后先不要急着做免密花一分钟做验证。在任意节点上执行ping -c 2 master01 ping -c 2 node01 ping -c 2 node02如果全部能ping通且显示的IP地址是192.168.56.x而不是127.0.0.1说明hosts解析正常。然后再执行hostname和hostnamectl确认当前节点的主机名改了。最后重启一台机器验证主机名是否持久化生效——reboot重启后重新登录再看hostname如果输出还是master01说明静态主机名配置成功了。这里有个容易搞混的地方hostname命令和hostnamectl命令的区别。hostname显示的是内核当前的主机名hostnamectl显示的是完整的配置信息。在CentOS 7里正常情况两者应该一致。4. SSH免密登录原理与实操步骤4.1 免密登录的本质是密钥认证SSH免密听起来很玄其实原理很简单。SSH支持两种登录认证方式密码认证和密钥认证。密钥认证用的是非对称加密你生成一对密钥一个私钥一个公钥。私钥自己留着相当于你的身份证公钥放到你要登录的机器上相当于把身份证复印件交给门卫。登录的时候服务器用一个随机数加密发给你你用私钥解密后返回结果服务器再用公钥验证你确实是持有私钥的那个人。验证通过直接放行全程不需要输入密码。理解了这个原理你就能明白公钥分发的位置了你需要在目标机器的目标用户家目录下把本机的公钥追加到~/.ssh/authorized_keys文件里。root用户的公钥放在/root/.ssh/authorized_keys普通用户的公钥放在/home/用户名/.ssh/authorized_keys。4.2 生成密钥对在管理机上执行ssh-keygen -t rsa -b 2048执行过程会问你保存位置和密码短语直接一路回车就行。生成完成后在~/.ssh/目录下会有两个文件id_rsa # 私钥千万不能泄露 id_rsa.pub # 公钥需要分发到各节点私钥文件的默认权限是600这个权限不要改。如果私钥权限太宽松SSH会直接拒绝使用这把密钥这是安全机制。这里提醒一句如果当前用户是root生成的是root的密钥如果当前用户是普通用户生成的是那个普通用户的密钥。集群里用哪个用户运维就用哪个用户生成密钥并分发。不要用root生成完再去给普通用户用权限模型会混乱。4.3 单台分发公钥ssh-copy-idCentOS 7默认安装了ssh-copy-id这个工具使用起来非常方便ssh-copy-id -i ~/.ssh/id_rsa.pub rootmaster01 ssh-copy-id -i ~/.ssh/id_rsa.pub rootnode01 ssh-copy-id -i ~/.ssh/id_rsa.pub rootnode02第一次执行ssh会询问是否确认目标主机指纹输入yes继续然后输入root密码完成公钥追加。这个工具会自动处理authorized_keys文件的权限和路径比自己手动去追加省心很多。如果目标机器的SSH端口不是默认的22需要指定端口ssh-copy-id -i ~/.ssh/id_rsa.pub -p 2222 rootnode014.4 验证免密配置分发完成后测试一下ssh master01 hostname ssh node01 hostname如果每条命令都能直接输出对应主机名且没有要求输入密码说明免密配置成功。从master01到node01的免密也是同样的逻辑如果集群里所有节点都需要互通就在每台机器上都生成密钥并分发到其他节点。4.5 没有ssh-copy-id时的替代方案有些精简版系统没装ssh-copy-id这时候手动配置也不复杂。核心就三步把公钥内容复制出来在目标机器上创建.ssh目录把公钥追加进去。# 在管理机上 cat ~/.ssh/id_rsa.pub # 在目标机器上执行 mkdir -p ~/.ssh chmod 700 ~/.ssh echo 粘贴公钥内容 ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys注意echo追加的时候要确保authorized_keys文件里没有重复的公钥。同一把公钥重复追加虽然不影响登录但会导致文件冗余以后追溯密钥归属时容易混乱。5. 批量配置与自动化脚本实战5.1 用循环批量分发公钥节点少的时候手动执行ssh-copy-id没问题节点一多一台一台输密码也会让人崩溃。我写过一个简单的批量分发脚本原理就是循环调用ssh-copy-id用expect自动应答密码。先装expectyum install -y expect然后写脚本#!/bin/bash NODESmaster01 node01 node02 PASSWORD你的密码 for node in $NODES; do expect -c spawn ssh-copy-id -o StrictHostKeyCheckingno -i /root/.ssh/id_rsa.pub root$node expect { \password:\ { send \$PASSWORD\r\; exp_continue } eof } done这个脚本关键点有两个StrictHostKeyCheckingno是让首次连接不出现指纹确认提示直接进入密码验证环节exp_continue是处理可能多次要求密码的情况。脚本执行完成后三个节点的免密一次性搞定。5.2 主机名和hosts的批量下发思路主机名没法通过root用户直接远程修改并保持永久生效但hosts文件可以批量下发。准备一个标准的hosts文件模板然后循环拷贝到各节点#!/bin/bash NODESmaster01 node01 node02 for node in $NODES; do scp /root/hosts_template $node:/etc/hosts done注意这个方案要求各节点的业务IP都在同一个hosts模板里写全。模板内容就是前面列的192.168.56.101到103的映射。执行完之后再单独登录每台机器执行hostnamectl改主机名或者用类似的远程方式执行ssh rootnode01 hostnamectl set-hostname node01 ssh rootnode02 hostnamectl set-hostname node02我实际用的比较多的是这种组合因为主机名涉及每台机器自己的身份没法用一个统一的模板去套hosts文件是所有机器共享的通讯录可以通过模板统一下发。组合起来效率最高。5.3 批量操作后的统一校验配置完成后批量验证是必要的环节。可以在管理机上一个循环把全部节点的hostname和关键网络配置拉出来看看#!/bin/bash NODESmaster01 node01 node02 for node in $NODES; do echo $node ssh $node hostname cat /etc/hosts | grep 192.168.56 done执行结果应该每个节点都输出自己的主机名和完整的hosts映射。用这个命令可以快速发现哪个节点的hosts是旧的、哪台机器主机名改失败不用一台台登录去对比。6. 常见问题与排查技巧实录6.1 免密登录失败Permission denied (publickey,password)这个问题出现概率极高但原因往往不在密钥本身而在权限设置。SSH对密钥相关文件的权限非常敏感authorized_keys权限大于600或者.ssh目录权限大于700SSH服务就会认为文件不安全直接拒绝使用公钥认证。解决方法chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys还有个隐蔽的问题是SELinux上下文。CentOS 7默认开启了SELinux如果authorized_keys是从别的机器拷贝过来的文件的安全上下文可能不对。这种情况用restorecon修复restorecon -Rv ~/.ssh6.2 ssh-copy-id提示找不到主机名如果执行ssh-copy-id rootnode01时报错“Could not resolve hostname node01”说明本机的hosts文件里没有node01的解析记录或者hosts文件配置错了。排查步骤grep node01 /etc/hosts ping -c 1 node01 getent hosts node01getent hosts和grep /etc/hosts的结果对比能帮你判断系统用的解析源到底是hosts文件还是DNS。如果getent能解析出来但ping报unknown host多半是nsswitch配置的问题。6.3 第一次连接卡在“Are you sure you want to continue connecting”这是首次连接时的host key指纹确认。自动化和脚本里如果不希望出现这个交互在连接命令里加参数ssh -o StrictHostKeyCheckingno rootnode01或者在~/.ssh/config里统一配置Host * StrictHostKeyChecking no在生产环境建议保持默认的yes首次连接确认一次指纹更安全。我只在批量初始化集群的时候关掉等所有节点确认过了再恢复。6.4 手动配置authorized_keys后依然要输密码我排查过很多次这类问题最常见的原因有三个第一公钥内容粘贴的时候出现了换行错乱比如用了echo时不带引号导致特殊字符被解释。正确做法是用双引号包裹公钥内容或者用cat重定向的方式从文件写入。第二目标机器的SSH配置禁用了公钥认证。检查sshd_config里PubkeyAuthentication是否为yes改完要重启sshdgrep PubkeyAuthentication /etc/ssh/sshd_config systemctl restart sshd第三登录的用户不对。你在管理机上用root生成的公钥分发到了root的authorized_keys里但执行ssh的时候用的用户是普通用户。检查一下当前登录用户whoami6.5 集群软件启动时报Could not resolve host这种问题通常不在SSH层面而是集群软件在跑的时候需要解析节点主机名但hosts文件不全。比如Hadoop启动时datanode会尝试连接配置文件里写的namenode主机名如果那台节点上解析不了对应的名字进程就起不来。解决思路是确保所有节点上的/etc/hosts内容完全一致每台机器打开hosts文件检查一遍不要只在一台机器上配置。还有一点值得注意有些软件包管理工具在安装时会自动往hosts文件里加一些条目这些条目可能会和你的手工配置冲突排查的时候看清楚hosts文件里有没有重复的IP映射。6.6 SSH连接很慢输完密码等好几秒才登录这种情况通常是SSH服务在做DNS反向解析。CentOS 7默认开启了UseDNS客户端连接时服务器会尝试用客户端IP反查域名如果DNS不可用就得等到超时。处理办法vi /etc/ssh/sshd_config # 找到 UseDNS改为no UseDNS no systemctl restart sshd6.7 集群节点改动主机名后Datanode/RegionServer进程假死改主机名要趁早。我遇到过一个场景集群已经跑了一段时间为了统一命名把某个节点的主机名改了结果namenode和datanode的注册信息还是旧主机名导致节点反复掉线。最终只能停止相关服务、清空集群的临时状态目录、重新格式化代价非常大。所以我的建议是主机名规划在集群搭建的第一天就定好一次性配置到位后边尽量不要再改。如果确实要改先下架该节点上的服务改完主机名后重启节点再重新加入集群。7. 实操总结与个人经验补充7.1 一套顺手的工作流配置了无数次CentOS 7集群之后我记录下两件比较重要的事帮你少走弯路。第一公钥文件建议单独命名。生产环境里我遇到过因为把公司内网密钥和集群密钥混在一起导致某个项目组拿到错误私钥的事。后来我习惯生成密钥时指定专用文件名ssh-keygen -t rsa -b 2048 -f ~/.ssh/cluster_key -C cluster-deploy使用的时候通过-i参数指定密钥ssh -i ~/.ssh/cluster_key rootnode01多套环境之间不会互相干扰排查问题的时候也清晰这个密钥是给哪套集群用的一目了然。第二升级系统和重启sshd之前检查防火墙。CentOS 7默认开启了firewalld如果节点间有防火墙策略隔离就算免密配好了也可能连不上。遇到连接超时先看防火墙firewall-cmd --list-all如果需要放行SSH端口firewall-cmd --permanent --add-servicessh firewall-cmd --reload7.2 最后一个小技巧配置过程中最容易忽略的其实是最基础的东西每台机器的时钟同步。SSH密钥认证本身和时钟关系不大但Kerberos、证书认证体系都强依赖时间一致性很多集群软件的租约机制也会被时钟偏移影响。建议在配置主机名的同时就把chrony或者ntpd时间同步一起做了否则后面集群框架报各种认证失败的时候你怎么排查都想不到问题出在时间上。我的个人习惯是新建集群时先统一改主机名、写hosts、做免密接着做时间同步然后开始装软件。这套基础做扎实了后边不管跑什么框架都很少出现诡异的基础环境问题。希望这篇文档能帮你少踩几个坑节省下来的时间去看日志和调优才是更值得花精力的事。
阅读完成 · 觉得有帮助?
咨询建站