在 Proxmox VE 虚拟化环境中搭建集群时,大量节点间的认证交互往往会成为自动化道路上的第一只拦路虎。如果你正准备用 Ansible、SaltStack 或简单的批量脚本管理 9 台 Ubuntu 节点,那么一个稳定、免密的 SSH 通信环境就是基础设施的基石。本文将记录一次从零开始为 9 个节点配置完全 SSH 互信、验证网络连通性并固化环境的实战过程,内容涵盖原理、命令脚本和常见坑点,适合快速复现和参考。

环境总览与实训任务

这次操作的物理/虚拟环境如下:

  • 虚拟化平台:Proxmox VE,9 台已克隆的 Ubuntu 22.04 LTS 虚拟机
  • 网络规划:所有节点位于同一虚拟网桥平面,已分配静态 IP 与主机名
  • 管理方式:可使用 PVE Web 控制台或外部 SSH 连接到各节点
  • 权限:拥有各节点 root 或 sudo 权限的用户凭据

总体目标非常明确:**实现任一节点到其他 8 个节点的 SSH 无密码登录,为后续自动化批量管理(如 Ansible 主机清单)铺平道路**。整个过程分为清单核对、连通性验证、密钥生成与分发、全互信配置、全覆盖验证、环境快照与交付共计六个阶段。

1. 清单核对:先看清楚再动手

养成“先列清单再操作”的工程习惯,可以减少大量误操作。整理一张简单的对照表,包含序号、主机名、静态 IP 和在线状态,例如:

主机名

IP 地址

网关

DNS

ControlNodeA

192.168.0.151

192.168.0.1

8.8.8.8

ControlNodeB

192.168.0.152

192.168.0.1

8.8.8.8

ControlNodeC

192.168.0.153

192.168.0.1

8.8.8.8

WorkNodeA

192.168.0.154

192.168.0.1

8.8.8.8

WorkNodeB

192.168.0.155

192.168.0.1

8.8.8.8

DataMidNode

192.168.0.156

192.168.0.1

8.8.8.8

DevOpsToolNode

192.168.0.157

192.168.0.1

8.8.8.8

ObservabilityNode

192.168.0.158

192.168.0.1

8.8.8.8

DSDRNode

192.168.0.159

192.168.0.1

8.8.8.8

快速抽检时,在其中一台节点上执行循环 ping:

Bash
#只显示通/不通,执行更快

for host in {151..159}; do

  ping -c 2 -W 1 -q 192.168.0.$host > /dev/null

  if [ $? -eq 0 ]; then

    echo "✅ 192.168.0.$host 连通正常"

  else

    echo "❌ 192.168.0.$host 连通失败"

  fi

done

如果某些主机名不通但 IP 可达,说明是名称解析的问题;此时检查 /etc/hosts 或 DNS 配置,确保所有节点的映射都已添加。

2. 全互通网络深度验证

在分发密钥之前,必须保证 IP 层和主机名解析完全正常。从管理节点(假设为 ControlNodeA)出发,用循环脚本完成两项测试:

测试 IP 连通性:

Bash
for ip in 192.168.0.{151..159}; do
  echo -n "$ip: "
  ping -c 4 $ip | tail -2
done

测试主机名解析:

Bash
for host in ControlNodeA ControlNodeB ControlNodeC WorkNodeA WorkNodeB DataMidNode DevOpsToolNode ObservabilityNode DSDRNode; do

  echo -n "检查 $host ... "

  ip=$(getent hosts "$host" | awk '{print $1}')

  if [ -n "$ip" ]; then

    echo "✅ 解析成功:$ip"

  else

    echo "❌ 解析失败!"

  fi

done

如果某些地址丢包,大概率是防火墙禁用了 ICMP,或者虚拟网桥绑定出错。可以通过 ufw status 或 iptables -L 检查。主机名解析失败时,建议在 /etc/hosts 文件中统一追加:

Plain Text
sudo tee -a /etc/hosts << 'EOF'

192.168.0.151   ControlNodeA

192.168.0.152   ControlNodeB

192.168.0.153   ControlNodeC

192.168.0.154   WorkNodeA

192.168.0.155   WorkNodeB

192.168.0.156   DataMidNode

192.168.0.157   DevOpsToolNode

192.168.0.158   ObservabilityNode

192.168.0.159   DSDRNode

EOF

3. 消除 “yes/no” 交互:巧用 ssh-keyscan

首次 SSH 连接时总会提示是否信任主机公钥,需要手动输入 yes,这在批量操作中是严重阻碍。解决办法是提前用 ssh-keyscan 采集所有节点的公钥,并写入 ~/.ssh/known_hosts 文件。

示例脚本如下:

Bash
> ~/.ssh/known_hosts  # 清空旧记录(可选,更干净)

for ip in {151..159}; do

  ssh-keyscan -H 192.168.0.$ip >> ~/.ssh/known_hosts 2>/dev/null

done

echo "✅ 所有节点公钥已添加到信任列表,SSH 不再提示 yes!"

这样做之后,后续的连接将不再出现交互确认。需要注意的是,ssh-keyscan 仅在可信网络环境使用,并且采集后应检查 known_hosts 内容是否正确。

4. SSH 免密原理简述

理解密钥认证流程有助于排错。基本过程是:

  1. 客户端发起连接请求,携带用户名;
  1. 服务端查找该用户家目录下的 ~/.ssh/authorized_keys 文件;
  1. 若文件中存在客户端对应的公钥,服务端生成一段随机字符串,用该公钥加密后发给客户端;
  1. 客户端用私钥解密得到随机串并返回;
  1. 服务端比对一致,认证通过,无需密码。

这背后的关键文件权限必须严格:

  • ~/.ssh 目录:700
  • authorized_keys 文件:600
  • 私钥文件:600

为满足全自动化,我们通常生成无密码短语的密钥(即 -N ""),但在生产环境中强烈建议配合 ssh-agent 使用,以提升私钥安全性。

5. 密钥生成与分发:从管理节点到全互信

5.1 生成 RSA 4096 位密钥

在管理主控节点(例如 ControlNodeA)上执行:

Bash
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa

这会在 ~/.ssh/ 下产生 id_rsa(私钥)和 id_rsa.pub(公钥)。

5.2 分发公钥到所有节点

ssh-copy-id 循环推送公钥,包括本机也需要推送以便本地免密:

Bash
USER=jack

for i in {151..159}; do

  ssh-copy-id -o StrictHostKeyChecking=no $USER@192.168.0.$i

done

每台节点需要输入一次用户密码。推送完成后,可在目标节点上检查 ~/.ssh/authorized_keys 文件中是否已包含管理节点的公钥串。

5.3 全互信配置(任意两节点均免密)

如果只想从 ControlNodeA 管理其他节点,上述分发已经足够。但如果希望任意两节点之间都可以相互免密,可以采用“统一私钥”方案:

  1. 将 ControlNodeA 上的 id_rsaid_rsa.pub 和 authorized_keys 文件复制到其余 8 个节点的对应路径;
  1. 在所有节点上统一修正权限:

一键批量复制脚本

Bash
# 要同步的节点:152~159(共8台)

for i in {152..159}; do

  echo "===== 同步到 192.168.0.$i ====="

  # 同步私钥、公钥、认证文件

  scp ~/.ssh/{id_rsa,id_rsa.pub,authorized_keys} jack@192.168.0.$i:~/.ssh/

  # 必须设置权限(SSH 强制要求)

  ssh jack@192.168.0.$i "chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_rsa && chmod 644 ~/.ssh/id_rsa.pub && chmod 600 ~/.ssh/authorized_keys"

done

echo -e "\n✅ 所有节点密钥同步完成!"

这样,每一台节点都拥有相同的密钥对,且信任该公钥,实现了真正意义上的全网无密码互访。

⚠️ 安全提示:该方案适用于隔离、可信的实训或内部开发环境。在生产环境中,推荐为每个节点生成独立密钥,并通过配置管理工具(如 Ansible)维护 authorized_keys 文件。

6. 全覆盖验证:零死角测试

直接在当前的 ControlNodeA 执行这一条命令,采集所有大小写、IP、主机名的公钥,彻底覆盖::

Bash
# 清空旧记录,重新采集所有节点公钥(彻底杜绝弹框)

> ~/.ssh/known_hosts

for host in ControlNodeA ControlNodeB ControlNodeC WorkNodeA WorkNodeB DataMidNode DevOpsToolNode ObservabilityNode DSDRNode; do

ssh-keyscan -H $host >> ~/.ssh/known_hosts 2>/dev/null

ssh-keyscan -H ${host,,} >> ~/.ssh/known_hosts 2>/dev/null

# 小写也加进去

done

for ip in {151..159}; do

ssh-keyscan -H 192.168.0.$ip >> ~/.ssh/known_hosts 2>/dev/null

done

echo "✅ 所有主机名/小写/IP 公钥已全部信任 → 再也不会弹 yes 确认!"

验证是确保环境质量不可省略的环节。编写一个简单的脚本,从管理节点强制关闭密码认证,逐一测试连接并获取主机名:

Bash
# 集群全覆盖免密验证(强制禁止密码,只允许密钥登录) 

for host in ControlNodeA ControlNodeB ControlNodeC WorkNodeA WorkNodeB DataMidNode DevOpsToolNode ObservabilityNode DSDRNode; do echo -n "验证免密 -> $host : " 

ssh -o PasswordAuthentication=no jack@$host hostname 

done

预期结果是无任何密码提示,直接返回对应节点的主机名。如果某个节点失败,常见原因及排查步骤如下:

  • authorized_keys 权限:必须为 600,ls -la ~/.ssh/ 检查;
  • .ssh 目录权限:必须为 700;
  • 私钥未分发:确认目标节点家目录下存在 id_rsa 且权限为 600;
  • 公钥内容:检查 authorized_keys 中是否确实包含管理节点的公钥。

还可以随机登录一个节点(如 ObservabilityNode),尝试 SSH 到 DataMidNode 和 ControlNodeA 并执行远程命令,确认双向互通:

Bash
ssh DataMidNode 'hostname'   # 应返回 DataMidNode
ssh ControlNodeA 'hostname'   # 应返回 ControlNodeA

7. 环境固化与交付标准

在全部验证通过后,立即对环境进行快照和归档,才能形成稳定的基线。

  1. 创建 PVE 快照:在 Proxmox VE 管理界面为 9 台虚拟机分别创建快照,命名遵循规范,例如 ssh_trust_setup_20260505,方便后续回滚或状态对比。

  1. 整理交付物
  • 最终的 IP–主机名对照表;
  • 密钥存放位置说明(如 ~/.ssh/id_rsa);
  • 验证脚本和测试截图/日志。
  1. 环境清理
  • 删除测试用的临时脚本;
  • 确保每节点 .ssh 目录下仅保留一套标准密钥和配置文件,避免混乱。

8. 后续步骤与闭环

SSH 互信通道打通后,可以立即投入到自动化部署中:

  • 编写 Ansible 主机清单,利用免密通道并行管理所有节点;
  • 批量部署 Docker、Kubernetes 或 Ceph 等集群服务,所有操作无需再处理认证;
  • 将当前快照作为基础设施的“基线存档”,后续任何变更都有可回溯的起点。

9. 常见问题排故速查

现象

可能原因

解决方案

SSH 仍要求密码

公钥未追加成功或权限错误;authorized_keys 非600;家目录或.ssh 权限错误

登录目标节点执行 chmod 600 ~/.ssh/authorized_keys; chmod 700 ~/.ssh,并重试

ping 不通但 SSH 可通

防火墙禁止 ICMP 但放行 TCP 22

检查 ufw status 或 iptables 规则,按需放行 ICMP

主机名 ping 不通,IP 通

/etc/hosts 缺少对应条目或 DNS 配置错误

/etc/hosts 中添加正确映射

ssh-keyscan 失败

目标节点 SSH 服务未启动或 22 端口未放行

使用 nc -zv IP 22 检查端口可达性,确认 sshd 服务运行

本文为“搭建DevOps企业级仿真实验环境”系列的一部分,所有内容均基于实际硬件环境(32核64线程 / 128G内存 / 6T硬盘)编写,力求贴近真实企业部署场景。

欢迎各位 DevOps、SRE 爱好者,在评论区留言交流探讨,互相学习。

更多推荐