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 痛点¶
- 运维效率低:每次批量操作需对每台主机重复输入密码
- 阻碍自动化:Ansible Playbook、批量巡检脚本、Calico 修复脚本分发等无法自动执行
- 风险残留:密码明文写在脚本里有泄露风险(虽然 sshpass 临时用,但不是长久之计)
- 一致性差:手动逐台操作易遗漏、易出错
2.2 改造价值¶
- 运维提速:从手动逐台 SSH + 输密码 →
ssh <别名>一键直达,秒级登录 - 解锁自动化:可基于免密 SSH 落地 Ansible Playbook、批量巡检、Calico 持久化脚本分发
- 降低泄露风险:密码不再出现在运维脚本里,移除 sshpass 依赖
- 运维一致性: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 注意事项¶
- OpenWrt 192.168.0.1 未配置:用户明确要求排除(路由器固件特殊,且不是运维目标)
- 0.11 自己未配置:admin 工作站不需要免密到自身
- 公网堡垒机 129.226.138.204 网络延迟较大:
~/.ssh/config中已设ConnectTimeout 20(其他主机 10s) - k8s-node-01 的
pyenv: 未找到命令是无害告警:用户 .bashrc 配置了 pyenv 但未安装,不影响免密
8.2 后续优化建议¶
- 迁移到 Ansible
authorized_key模块:当前用 sshpass 手动推送,建议后续用 Ansible Playbook 统一管理公钥生命周期(增删改查) - 生产环境加固(如需上生产):
- 私钥加 passphrase + 用 ssh-agent 缓存
- authorized_keys 公钥前加
from="192.168.0.11"限制源 IP - 关闭 sshd 的
PasswordAuthentication(强制只走公钥,杜绝密码爆破) - 定期审计 authorized_keys:建议基线巡检脚本加一条检查 12 台主机 authorized_keys 行数,发现新增未知公钥立即告警
- 私钥轮换机制:建议每半年轮换一次密钥对,避免长期使用同一密钥的安全风险
九、执行结果归档¶
| 阶段 | 状态 | 验收 |
|---|---|---|
| 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同步,请勿在站点侧修改)