当服务器数量从几台增长到几十上百台,运维方式必须随之升级。逐台SSH登录执行命令不仅效率低下,还容易因为操作不一致引发配置漂移。并行SSH执行工具的出现,让一条命令同时在全部节点上运行成为可能,但要想真正用好它,还需要建立一套完整的执行规范,包括认证方式、并发控制、输出管理、错误处理和安全审计等。本文将从基础配置讲起,逐步展开集群批量运维的核心实践。

一、SSH密钥认证与免密登录配置
批量运维的第一步是打通认证链路。如果每台机器还需要手动输入密码,并行执行就无从谈起。目前最通用的方式是部署SSH公钥认证,也就是常说的免密登录。具体做法是在管理节点上生成一对密钥,然后把公钥分发到所有目标主机的授权文件中。可以使用ssh-keygen生成密钥对,再用ssh-copy-id逐台分发,或者结合循环脚本批量推送。
分发公钥时有两个细节需要特别注意。一是公钥应该追加写入目标主机的~/.ssh/authorized_keys文件,而不是覆盖,否则会把已有授权挤掉。二是目录和文件权限必须严格:家目录不能对组开放写权限,.ssh目录应为700,authorized_keys应为600,权限过松时sshd会默认拒绝密钥认证,这是新手排查免密失败时最常见的原因。
# 管理节点生成密钥对(无口令,便于自动化)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
# 批量分发公钥到目标主机
for host in $(cat hosts.txt); do
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@$host
done
# 验证免密登录
ssh -o BatchMode=yes root@node01 "hostname"
出于安全考虑,建议管理节点使用独立的密钥对,并且在sshd配置中禁用密码登录,只保留密钥认证。密钥文件本身也要妥善保管,可以考虑配合ssh-agent使用,避免私钥长时间落盘暴露。如果集群规模较大,还可以部署统一的配置管理通道,把密钥分发纳入初始装机流程,减少手工操作带来的不确定性。
二、主流并行SSH工具的选择与使用
并行执行工具的核心思路是相同的:读取一份主机列表,以多进程或多线程方式同时建立SSH连接,把同一条命令分发到所有节点执行,再集中收集输出。常用的工具有pssh、pdsh以及Ansible,它们的能力侧重各有不同。
pssh是一套Python实现的轻量工具集,包含pssh、pscp、pslurp等子命令,适合纯粹的命令分发和文件传输场景。它的输出会按主机分文件保存,便于事后审计。使用前需要准备一个主机列表文件,每行一个地址。
# 在所有节点并行执行命令,限制并发为20 pssh -h hosts.txt -l root -p 20 -t 30 -o /tmp/out "uptime" # 并行分发文件到所有节点的指定目录 pscp -h hosts.txt -l root -p 20 nginx.conf /etc/nginx/nginx.conf # 从所有节点回收指定文件到本地目录 pslurp -h hosts.txt -l root /etc/os-release /tmp/collect
pdsh则是C语言实现的并行Shell,优势在于轻量和灵活,支持通过-w参数直接指定主机,也支持主机通配符表达式,比如pdsh -w ssh:node[01-10]可以一次匹配十台机器。它的输出是混杂在一起按行打印的,每行带有主机名前缀,适合实时观察,但不如pssh的分文件输出便于程序化处理。
如果需要更复杂的逻辑,比如条件执行、幂等操作、模块化管理配置,Ansible是更合适的选择。它基于SSH通道工作,无需在目标机安装代理,通过Playbook描述任务,天然支持失败重试和状态收敛。对于简单的批量命令,用ansible all -i hosts -m command -a "uptime"也能快速完成。三者的选择可以简单概括:临时命令分发用pssh或pdsh,体系化配置管理用Ansible。
三、并发控制、超时与错误处理规范
并行执行不等于无限并发。管理节点同时发起成百上千个SSH连接,可能耗尽本地端口、进程数或触发目标端sshd的连接限制,反而导致大面积失败。生产环境中应该把并发数控制在合理范围,一般建议单轮并发不超过20到50,规模特别大的集群可以分批执行或者采用分级管理节点架构。pssh用-p参数控制并发,Ansible通过forks参数调整,默认值是5,大规模场景下需要显式调大。
超时设置同样重要。一条命令如果在某个节点上挂住且没有超时保护,整个批次都会被拖住。建议为每次执行都设置连接超时和命令超时,pssh的-t参数指定命令超时秒数,连接超时则可以通过SSH选项传递。Ansible可以在配置中设置timeout以及任务级的async异步轮询,处理长时间运行的任务。
错误处理方面,核心规范是永远不要忽略失败节点。并行执行后必须检查退出状态和输出文件,确认哪些节点成功、哪些节点失败,失败节点要么单独重试,要么记录下来进入后续处理流程。切忌看到大部分节点成功就认为批次完成,集群中残留的少数失败节点往往就是日后故障的隐患。
# 执行后统计失败节点 pssh -h hosts.txt -l root -p 20 -t 60 -o /tmp/out "systemctl restart nginx" # 退出码非零表示存在失败节点,查看错误目录定位问题 ls /tmp/out/err/ 2>/dev/null | wc -l # 针对失败节点单独重试 pssh -h failed_hosts.txt -l root -o /tmp/retry "systemctl status nginx"
另外一条重要规范是危险命令必须灰度执行。涉及重启服务、修改内核参数、清理数据等高风险操作,应该先在少量节点上验证,观察无误后再扩大范围。可以把主机列表拆分成灰度批次,逐批执行并检查关键指标,这比一次性全量推送稳妥得多。
四、输出收集与安全审计实践
批量执行的输出管理直接影响排障效率。建议每次执行都保留完整的输出记录,包括标准输出和标准错误,并按主机归档。pssh的-o和-e参数可以分别指定输出目录和错误目录,Ansible则可以用-vvv获取详细日志或开启日志文件。对于定期执行的巡检任务,输出目录最好按时间戳组织,形成可回溯的历史记录。
安全审计是集群运维不可回避的一环。所有批量操作应该集中由跳板机或专用管理节点发起,禁止运维人员从个人电脑直接批量操作生产集群。管理节点上开启操作日志,记录执行人、执行时间、目标主机和具体命令,必要时配合堡垒机实现会话录像。主机列表文件本身也要纳入版本管理,避免使用来路不明的列表误操作。
最后需要强调最小权限原则。批量执行使用的账号不应该一律使用root,能通过sudo提权的场景,可以在命令前统一加sudo并精确控制sudoers规则;只读巡检任务则使用普通账号即可。把权限边界划分清楚,即使某次批量命令写错了目标或参数,造成的破坏也能被限制在可控范围内。通过认证规范化、工具合理选型、并发与超时控制、灰度执行和审计留痕这几层措施叠加,集群批量运维才能真正做到既高效又可靠。