跳转至

SOP - 0.11 admin 工作站到 12 台主机 SSH 免密登录配置

文档类型:运维操作 SOP(标准作业程序) 执行日期:2026-08-24 执行人:rian@192.168.0.11 (admin 工作站) 执行环境:个人测试学习集群(kubeadm K8s 1.22.1 + 6 节点 + 周边 CentOS 主机) 依据资产清单:../inventory.yaml


一、更改的背景

1.1 现状

  • admin 工作站 0.11 (Ubuntu 22.04) 作为统一运维入口
  • 此前每次 SSH 登录其他主机都需要手动输入 root 密码(Rain--4630),既繁琐又阻碍自动化运维
  • 后续需要执行批量运维:Calico BGP 修复脚本分发、Ansible Playbook 推送、K8s 集群巡检等,没有免密登录这些自动化都做不了

1.2 资产清单概览(inventory.yaml 提取)

hostname IP 角色 OS 是否本次配置
k8s-master-01 192.168.0.2 K8s master + slurm + lsf CentOS 7 ✅
k8s-master-02 192.168.0.3 K8s master + lsf_backup CentOS 7 ✅
k8s-master-03 192.168.0.4 K8s master + lustre_oss CentOS 7 ✅
k8s-node-01 192.168.0.5 K8s node + slurm/lsf compute CentOS 7 ✅
k8s-node-02 192.168.0.6 K8s node + slurm/lsf compute CentOS 7 ✅
k8s-node-03 192.168.0.7 K8s node + slurm/lsf compute CentOS 7 ✅
IDE 192.168.0.9 k8s_master + slurm_submit CentOS 7 ✅
frp-openvpn 192.168.0.10 frp_client + openvpn_server CentOS 7 ✅
rian 192.168.0.11 trae_remote_ssh + k8s_Admin_Workstation Ubuntu 22.04 ❌(admin 自己,不需要)
harbor 192.168.0.12 docker_registry + lustre_mgs CentOS 7 ✅
nfs 192.168.0.13 nfs_server + lustre_mds CentOS 7 ✅
HP-R620 192.168.0.250 all_KVM_virtual_machine_hosts CentOS 7 ✅
VM-4-4-centos 129.226.138.204 frp_server + public_bastion_host CentOS 7 ✅(公网堡垒机)
OpenWrt 192.168.0.1 self-built_router OpenWrt ❌(用户明确排除)

合计目标主机:12 台(6 K8s 节点 + IDE + frp-openvpn + harbor + nfs + HP-R620 + 公网堡垒机)


二、为什么要更改(动机与价值)

2.1 痛点

  1. 运维效率低:每次批量操作需对每台主机重复输入密码
  2. 阻碍自动化:Ansible Playbook、批量巡检脚本、Calico 修复脚本分发等无法自动执行
  3. 风险残留:密码明文写在脚本里有泄露风险(虽然 sshpass 临时用,但不是长久之计)
  4. 一致性差:手动逐台操作易遗漏、易出错

2.2 改造价值

  1. 运维提速:从手动逐台 SSH + 输密码 → ssh <别名> 一键直达,秒级登录
  2. 解锁自动化:可基于免密 SSH 落地 Ansible Playbook、批量巡检、Calico 持久化脚本分发
  3. 降低泄露风险:密码不再出现在运维脚本里,移除 sshpass 依赖
  4. 运维一致性:12 台主机统一治理,避免遗漏

三、底层原理与执行逻辑

3.1 SSH 公钥认证原理

0.11 (admin 工作站)            目标主机 (k8s-master-01)
─────────────────             ─────────────────────────
1. ssh-keygen 生成密钥对:
   - ~/.ssh/id_ed25519 (私钥)   ┐
   - ~/.ssh/id_ed25519.pub (公钥) ┘ 永远不离开 0.11
                                │
2. 推送公钥到目标主机 ──────────┼─→ ~/.ssh/authorized_keys (追加 1 行公钥)
                                │   权限 600,目录 700
                                │
3. ssh k8s-master-01 发起连接 ─→ 4. sshd 收到请求,发随机挑战字符串
                                │
5. 0.11 用私钥签名挑战 ────────┼─→ 6. sshd 用 authorized_keys 中
                                   的公钥验签
                                │
                                ←─ 7. 验签通过 → 免密登录成功

3.2 关键技术选型

选型 选择 理由
密钥算法 ed25519 比 RSA2048 更安全(NIST 推荐),密钥更短(113 字节公钥 vs RSA 540 字节),OpenSSH 6.5+ 原生支持
私钥 passphrase 空 自动化运维需要无人值守,私钥加 passphrase 会触发交互式输入阻碍自动化
公钥推送工具 sshpass + ssh 简单直接,无需在目标主机安装额外 agent;后续建议改用 Ansible 的 authorized_key 模块(已具备免密后可平滑迁移)
别名管理 ~/.ssh/config 集中管理主机别名 + 全局 SSH 选项,避免运维命令里写一堆 -o 参数

3.3 安全增强配置(~/.ssh/config)

Host *
  StrictHostKeyChecking no         # 首次连接自动接受 host key(已知主机文件指向 /dev/null)
  UserKnownHostsFile /dev/null       # 不污染 known_hosts(测试环境简化)
  ServerAliveInterval 60             # 60s 心跳保活,防止长连接被中间设备断开
  ServerAliveCountMax 3              # 3 次心跳无响应才判定断连(180s 容忍)
  PreferredAuthentications publickey,keyboard-interactive,password
                                     # 认证优先级:公钥 > 键盘交互 > 密码(强制优先公钥)

四、更改后的作用与达成的效果

4.1 直达别名清单(运维日常用)

# K8s 集群 3 master
ssh k8s-master-01    # → root@192.168.0.2
ssh k8s-master-02    # → root@192.168.0.3
ssh k8s-master-03    # → root@192.168.0.4

# K8s 集群 3 worker
ssh k8s-node-01      # → root@192.168.0.5
ssh k8s-node-02      # → root@192.168.0.6
ssh k8s-node-03      # → root@192.168.0.7

# 其他业务主机
ssh ide              # → root@192.168.0.9
ssh frp-openvpn      # → root@192.168.0.10
ssh harbor           # → root@192.168.0.12
ssh nfs              # → root@192.168.0.13
ssh hp-r620          # → root@192.168.0.250
ssh vm-4-4-centos    # → root@129.226.138.204 (公网堡垒机)

4.2 验证铁证(执行结果)

主机 退出码 whoami 远端 IP 系统
k8s-master-01 0 root 192.168.0.2 CentOS 7.6
k8s-master-02 0 root 192.168.0.3 CentOS 7.6
k8s-master-03 0 root 192.168.0.4 CentOS 7.6
k8s-node-01 0 root 192.168.0.5 CentOS 7.6
k8s-node-02 0 root 192.168.0.6 CentOS 7.6
k8s-node-03 0 root 192.168.0.7 CentOS 7.6
ide 0 root 192.168.0.9 CentOS 7.9
frp-openvpn 0 root 192.168.0.10 CentOS 7.6
harbor 0 root 192.168.0.12 CentOS 7.6
nfs 0 root 192.168.0.13 CentOS 7.6
hp-r620 0 root 192.168.0.250 CentOS 7.9
vm-4-4-centos 0 root 10.0.4.4 CentOS 7.6

12/12 全部免密登录成功,强制公钥认证(PasswordAuthentication=no + BatchMode=yes)退出码全部 0,whoami 全部 root。

4.3 达成的运维能力跃迁

之前 之后
sshpass -p 'Rain--4630' ssh root@192.168.0.2 "command" ssh k8s-master-01 "command"
Ansible 需要 ansible_password 配置 Ansible 直接用 --private-key=~/.ssh/id_ed25519
批量脚本里硬编码密码 批量脚本无密码泄露风险
逐台手动 SSH 一条命令并行批量执行

五、更改实现的具体步骤与方法(可复现 SOP)

5.1 前置准备(admin 工作站 0.11)

# 1. 检查并生成 ed25519 密钥对(如未存在)
if [ ! -f ~/.ssh/id_ed25519 ]; then
  # 备份现有 ~/.ssh 目录(如果有)
  [ -d ~/.ssh ] && cp -r ~/.ssh ~/.ssh.bak.$(date +%Y%m%d_%H%M%S)
  # 生成 ed25519 密钥(无 passphrase,注释标识来源)
  ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519 -C "admin-workstation-0.11-$(date +%Y%m%d)"
fi
# 2. 确保 sshpass 已安装(推送公钥首次需要密码登录)
command -v sshpass >/dev/null || sudo apt-get install -y sshpass

5.2 配置 ~/.ssh/config(运维便捷性核心)

cat > ~/.ssh/config <<'EOF'
# SSH 客户端配置 - admin 工作站 0.11
# 全局默认
Host *
  User root
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null
  ServerAliveInterval 60
  ServerAliveCountMax 3
  ConnectTimeout 10
  PreferredAuthentications publickey,keyboard-interactive,password

# K8s 3 Master
Host k8s-master-01 192.168.0.2
  HostName 192.168.0.2
Host k8s-master-02 192.168.0.3
  HostName 192.168.0.3
Host k8s-master-03 192.168.0.4
  HostName 192.168.0.4

# K8s 3 Worker
Host k8s-node-01 192.168.0.5
  HostName 192.168.0.5
Host k8s-node-02 192.168.0.6
  HostName 192.168.0.6
Host k8s-node-03 192.168.0.7
  HostName 192.168.0.7

# 其他业务主机
Host ide 192.168.0.9
  HostName 192.168.0.9
Host frp-openvpn 192.168.0.10
  HostName 192.168.0.10
Host harbor 192.168.0.12
  HostName 192.168.0.12
Host nfs 192.168.0.13
  HostName 192.168.0.13
Host hp-r620 192.168.0.250
  HostName 192.168.0.250

# 公网堡垒机
Host vm-4-4-centos 129.226.138.204
  HostName 129.226.138.204
  ConnectTimeout 20
EOF
chmod 600 ~/.ssh/config

5.3 推送公钥到 12 台目标主机

# 高危操作前置提醒:
# ⚠️ 会修改目标主机 root 的 ~/.ssh/authorized_keys 文件
# 🔁 回滚方案:从 authorized_keys 中删除 "admin-workstation-0.11" 公钥行
#             或还原备份 mv ~/.ssh/authorized_keys.bak.20260824 ~/.ssh/authorized_keys

PASS='Rain--4630'
PUBKEY=$(cat ~/.ssh/id_ed25519.pub)
TS=$(date +%Y%m%d)
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10 -o PreferredAuthentications=password -o PubkeyAuthentication=no"

# 12 台目标主机
HOSTS=(
  "192.168.0.2:k8s-master-01" "192.168.0.3:k8s-master-02" "192.168.0.4:k8s-master-03"
  "192.168.0.5:k8s-node-01" "192.168.0.6:k8s-node-02" "192.168.0.7:k8s-node-03"
  "192.168.0.9:ide" "192.168.0.10:frp-openvpn"
  "192.168.0.12:harbor" "192.168.0.13:nfs" "192.168.0.250:hp-r620"
  "129.226.138.204:vm-4-4-centos"
)

for entry in "${HOSTS[@]}"; do
  IP="${entry%%:*}"
  NAME="${entry##*:}"
  echo "推送 $NAME ($IP)..."
  sshpass -p "$PASS" ssh $SSH_OPTS root@$IP "
    # 1. 备份现有 authorized_keys(首次推才备份,避免重复备份覆盖首次备份)
    [ ! -f ~/.ssh/authorized_keys.bak.$TS ] && [ -f ~/.ssh/authorized_keys ] && cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.bak.$TS
    # 2. 确保 .ssh 目录
    mkdir -p ~/.ssh && chmod 700 ~/.ssh
    # 3. 追加公钥(grep 去重,避免重复追加)
    grep -qF '$PUBKEY' ~/.ssh/authorized_keys 2>/dev/null || echo '$PUBKEY' >> ~/.ssh/authorized_keys
    # 4. 修正权限
    chmod 600 ~/.ssh/authorized_keys
    # 5. 输出统计
    echo \"OK 行数=\$(wc -l < ~/.ssh/authorized_keys)\"
  " 2>&1 | tail -3
done

5.4 验证免密登录生效

# 强制公钥认证(禁用密码回退),用退出码判断真免密
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10 -o PasswordAuthentication=no -o PreferredAuthentications=publickey -o BatchMode=yes -q"

for entry in "${HOSTS[@]}"; do
  ALIAS="${entry##*:}"
  OUT=$(timeout 15 ssh $SSH_OPTS $ALIAS "hostname; whoami" 2>/dev/null)
  RC=$?
  [ $RC -eq 0 ] && echo "✅ $ALIAS → $(echo $OUT | tr '\n' ' ')" || echo "❌ $ALIAS 失败"
done

5.5 高级运维场景验证(批量并行执行)

# 一条命令查 12 台主机内网IP + 系统 + 内核
for entry in "${HOSTS[@]}"; do
  ALIAS="${entry##*:}"
  ssh $SSH_OPTS $ALIAS "hostname -I | awk '{print \$1}'; cat /etc/redhat-release; uname -r" 2>/dev/null \
    | paste -sd '|' | sed "s/^/  $ALIAS → /"
done

六、风险与回滚方案

6.1 安全风险与缓解

风险 缓解措施
0.11 被攻破后所有目标主机失守 ⚠️ 测试环境可接受;生产环境建议私钥加 passphrase + 在 authorized_keys 公钥前加 from="192.168.0.11" 限制源 IP
私钥泄露 ~/.ssh/id_ed25519 权限 600(仅 rian 可读),不外传
公钥被多次追加 推送脚本用 grep -qF 去重,避免重复追加
公钥覆盖原有 authorized_keys 用 >> 追加而不是 > 覆盖,并先备份 authorized_keys.bak.$TS

6.2 一键回滚方案(任意主机撤销 0.11 公钥)

# ============================================================
# 用途:从指定目标主机撤销 0.11 的免密公钥
# 入参:$1 = 目标主机别名(如 k8s-master-01)或 IP
# 适用系统:CentOS7/Ubuntu22+
# ============================================================
TARGET_HOST="${1:?用法: $0 <hostname_alias_or_ip>}"
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"

# 先用免密登录(如果还能免密就执行撤销;如果已撤销就用密码登录)
ssh $SSH_OPTS $TARGET_HOST "
  # 备份当前 authorized_keys
  [ -f ~/.ssh/authorized_keys ] && cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.before_revoke.\$(date +%Y%m%d_%H%M%S)
  # 删除含 'admin-workstation-0.11' 标识的公钥行
  sed -i '/admin-workstation-0.11/d' ~/.ssh/authorized_keys
  echo \"撤销后剩余公钥数:\$(wc -l < ~/.ssh/authorized_keys)\"
" 2>&1 | tail -3
echo "✅ $TARGET_HOST 上的 0.11 公钥已撤销"

批量撤销所有 12 台:

for entry in "${HOSTS[@]}"; do
  bash revoke_one.sh "${entry##*:}"
done

或还原备份(更彻底):

for entry in "${HOSTS[@]}"; do
  ALIAS="${entry##*:}"
  ssh $ALIAS "mv ~/.ssh/authorized_keys.bak.20260824 ~/.ssh/authorized_keys 2>/dev/null && echo '✅ $ALIAS 已还原备份' || echo '⚠️ $ALIAS 无备份可还原'"
done

七、关联文件清单(运维回溯用)

文件/路径 说明
资产清单 ../inventory.yaml
本 SOP 文档 ./SOP-0.11到12台主机SSH免密登录配置.md
0.11 私钥 /home/rian/.ssh/id_ed25519(权限 600,永不离 0.11)
0.11 公钥 /home/rian/.ssh/id_ed25519.pub(已推送到 12 台目标主机)
0.11 SSH 配置 /home/rian/.ssh/config(含 12 个 Host 别名段,权限 600)
0.11 SSH 目录备份 /home/rian/.ssh.bak.20260824_103900(操作前的完整 ~/.ssh 备份)
目标主机 authorized_keys 备份 每台主机 ~/.ssh/authorized_keys.bak.20260824(推送前备份)

八、注意事项与后续优化建议

8.1 注意事项

  1. OpenWrt 192.168.0.1 未配置:用户明确要求排除(路由器固件特殊,且不是运维目标)
  2. 0.11 自己未配置:admin 工作站不需要免密到自身
  3. 公网堡垒机 129.226.138.204 网络延迟较大:~/.ssh/config 中已设 ConnectTimeout 20(其他主机 10s)
  4. k8s-node-01 的 pyenv: 未找到命令 是无害告警:用户 .bashrc 配置了 pyenv 但未安装,不影响免密

8.2 后续优化建议

  1. 迁移到 Ansible authorized_key 模块:当前用 sshpass 手动推送,建议后续用 Ansible Playbook 统一管理公钥生命周期(增删改查)
  2. 生产环境加固(如需上生产):
  3. 私钥加 passphrase + 用 ssh-agent 缓存
  4. authorized_keys 公钥前加 from="192.168.0.11" 限制源 IP
  5. 关闭 sshd 的 PasswordAuthentication(强制只走公钥,杜绝密码爆破)
  6. 定期审计 authorized_keys:建议基线巡检脚本加一条检查 12 台主机 authorized_keys 行数,发现新增未知公钥立即告警
  7. 私钥轮换机制:建议每半年轮换一次密钥对,避免长期使用同一密钥的安全风险

九、执行结果归档

阶段 状态 验收
SSH-1 生成 ed25519 密钥 + 配置 ~/.ssh/config ✅ 完成 私钥/公钥生成成功,config 12 个别名段就绪
SSH-2 推送公钥到 12 台主机 ✅ 完成 12/12 成功,目标主机 authorized_keys 行数全部增加,原文件已备份
SSH-3 干净验证(强制公钥认证) ✅ 完成 12/12 RC=0,whoami=root 全部通过,别名直连+批量运维场景验证通过
SSH-4 生成 SOP.md ✅ 完成 本文档归档

🎉 总体验收:12/12 主机免密登录 100% 配置成功,运维入口已统一在 0.11 (admin 工作站)。


来源:/home/rain/Documents/trae_for_om/ssh_passwordless_setup/SOP-0.11到12台主机SSH免密登录配置.md | 最后更新:2026-08-27 17:50(由 build/sync.py 同步,请勿在站点侧修改)