AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

ssh-keygen —— 密钥对生成与 known_hosts 维护

一句话定义

ssh-keygen 是 OpenSSH 自带的工具,负责生成密钥对(公钥 + 私钥)、修剪 known_hosts 里的过期主机指纹、查看现有密钥的指纹和元信息。

典型场景

  • 第一次配置开发机:ssh-keygen -t ed25519 生成你的私人密钥对
  • 给 GitHub 加新账号 key 时:再生成一把 ~/.ssh/id_ed25519_work
  • 云机器重装、IP 复用:ssh-keygen -R <host> 清掉旧指纹
  • 检查私钥是哪种类型、什么时候生成的:ssh-keygen -lf ~/.ssh/id_rsa

公私钥配对,原理要先懂

公私钥认证(asymmetric / public-key cryptography)的本质:

  1. 私钥 (id_xxx):留在你本地,永远不外发
  2. 公钥 (id_xxx.pub):可以随便发,往远端 ~/.ssh/authorized_keys 里塞一份
  3. 登录时,ssh 客户端用私钥对一个 server 发来的挑战做签名 → 远端用公钥验证签名 → 验过就放行

所以记住:

  • 把公钥复制到远端(authorized_keys),不是私钥
  • 同一把私钥可以认证给无数台机器(把公钥分发出去就行)
  • 一个用户可以有多把私钥,给不同场景用(个人 GitHub / 公司 GitHub / 生产服务器 / 测试机)

authorized_keys 长这样:

ssh-ed25519 AAAAC3Nz...xJ user@laptop
ssh-rsa AAAAB3Nz...IDAQAB another-user@another-machine

一行一把公钥。客户端尝试的任何一把私钥,只要其公钥在这个文件里,就能登录。


基础用法

生成新密钥对

# 推荐:现代算法 ed25519
ssh-keygen -t ed25519 -C "yuanjun@hihuo 2026-05-27"

# 或:兼容性更广的 RSA 4096
ssh-keygen -t rsa -b 4096 -C "yuanjun@hihuo 2026-05-27"

# 给特定用途生成(不覆盖默认 key)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "work account"

跑完会问几个问题:

Enter file in which to save the key (~/.ssh/id_ed25519):  ← 直接回车用默认路径
Enter passphrase (empty for no passphrase):              ← 私钥密码(可选)
Enter same passphrase again:

生成两个文件:

~/.ssh/id_ed25519       ← 私钥,600 权限
~/.ssh/id_ed25519.pub   ← 公钥,644 权限

-t 算法对比

算法推荐度备注
ed25519首选短(68 字符)、快、强(128-bit 等效安全)。OpenSSH 6.5+ 支持,2014 年至今的机器都有
rsa -b 4096兼容选老旧设备(路由器、嵌入式)只认 RSA。但比 ed25519 慢、长
rsa -b 2048不要再用强度勉强,被一些合规要求禁用
ecdsa避免算法本身没问题,但有 NIST 后门质疑、生态用得少
dsa禁用OpenSSH 7+ 默认禁用

训练营建议:所有新机器用 ed25519。已有 id_rsa 的不用换(继续用就行),新需求统一用 ed25519。

-C comment 字段

ssh-keygen -t ed25519 -C "yuanjun@macbook 2026-05-27"

-C 写啥都不影响认证逻辑,但写清楚 谁生成的、什么时候生成的:

  • 多年后清理 authorized_keys:能看出"哪些 key 是老员工的、可以删"
  • 多机器混用同一个账号:能看出"这条登录记录从哪台机器来"

工业实践:<user>@<machine> <YYYY-MM-DD> 或 <purpose>@<machine>。

-f 指定输出路径

默认会写 ~/.ssh/id_<algo>,但同一台机器要多个 key 时必须指定不同路径:

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_personal

然后在 ~/.ssh/config 里给不同 Host 段指 IdentityFile 不同 key。

-N passphrase

ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_deploy   # 空密码(无 passphrase)

-N "" 给私钥设空密码 —— 适合自动化脚本用的 key(CI / deploy bot),让脚本不用每次输密码。

代价:私钥文件泄露 = 直接被人登录。人用的 key 一定要设 passphrase,配合 ssh-agent 解锁一次后免输入。


推送公钥到远端

方法 1:ssh-copy-id —— 首选

ssh-copy-id user@host                          # 默认推 ~/.ssh/id_*.pub
ssh-copy-id -i ~/.ssh/id_ed25519_work.pub m1   # 指定推某把

ssh-copy-id 帮你做了几件事:

  • 用密码登录远端
  • 创建 ~/.ssh 目录(如果不存在),权限 700
  • 追加公钥到 ~/.ssh/authorized_keys,权限 600
  • 幂等:已存在不重复

方法 2:手动 cat + ssh —— 适合脚本批量推

PUBKEY=$(cat ~/.ssh/id_rsa.pub)
for ip in 10.0.24.28 10.0.24.29 10.0.24.30; do
  sshpass -p "$IP_PWD" ssh -o StrictHostKeyChecking=accept-new root@$ip "
    mkdir -p /root/.ssh && chmod 700 /root/.ssh
    grep -qxF '$PUBKEY' /root/.ssh/authorized_keys 2>/dev/null \
      || echo '$PUBKEY' >> /root/.ssh/authorized_keys
    chmod 600 /root/.ssh/authorized_keys
  "
done

注意 grep -qxF '...' || echo '...' >> —— 幂等关键:

  • -q:静默
  • -x:整行匹配(避免子串误判)
  • -F:把 pattern 当字面量(公钥里有 + / = 等正则特殊字符)

方法 3:远端没 ssh,本地直接编辑文件

很少见。比如远端是新装的 Ubuntu Cloud Image,要写 cloud-init 配置:

# cloud-config
ssh_authorized_keys:
  - ssh-ed25519 AAAAC3...xJ user@laptop

known_hosts 维护

~/.ssh/known_hosts 存的是你信任过的远端 host key 指纹。每次连接,ssh 客户端对比远端指纹和本地记录,不一致就拒连(防止中间人攻击)。

看一条记录

ssh-keygen -F m1                # 查 m1 在不在 known_hosts
# m1 RSA SHA256:...

ssh-keygen -lf ~/.ssh/known_hosts | head
# 列出所有记录的指纹

清掉某个 host

云机器 IP 复用 / 机器重装 / 阿里云重新分配 IP,都会让远端 host key 变化,本地会报:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

修复:

ssh-keygen -R m1                    # 按 alias 删
ssh-keygen -R 10.0.24.28            # 按 IP 删
ssh-keygen -R '[example.com]:2222'  # 非默认端口的 host 要这样转义

-R 会就地修改 known_hosts、把旧记录注释成 # Host ... removed。

一次性临时跳过校验(仅限"反正是测试机")

ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@$ip

或写在 config 里(见 ssh-config.md)。


查看 / 比对密钥指纹

看私钥/公钥的指纹

ssh-keygen -lf ~/.ssh/id_ed25519              # 私钥指纹
ssh-keygen -lf ~/.ssh/id_ed25519.pub          # 公钥指纹(应该一样)
# 256 SHA256:abcd... user@machine (ED25519)

跟 GitHub 上添加的指纹核对

GitHub Settings → SSH and GPG keys 里每把 key 都显示指纹。和本地 ssh-keygen -lf 输出对一下、确认你的本地 key 已经登记。

验远端 host key

第一次连陌生机器,对方应该公告它的 host key 指纹(云厂商 console、IDC 工单里)。比一下:

ssh -o StrictHostKeyChecking=ask m1
# The authenticity of host 'm1 (10.0.24.28)' can't be established.
# ED25519 key fingerprint is SHA256:xxxxx
# Are you sure you want to continue connecting (yes/no)?

对比无误后输 yes,本地记入 known_hosts,下次免问。


多 key 管理:IdentityFile + IdentitiesOnly yes

一台开发机有多把 key 时(个人 GitHub、公司 GitHub、生产服务器、测试机),靠 ~/.ssh/config 分配:

Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

Host prod-*
  IdentityFile ~/.ssh/id_ed25519_prod
  IdentitiesOnly yes

IdentitiesOnly yes 不是可选项,是必加项。

原因:默认情况下 ssh 会先尝试 ssh-agent 里所有 key,再用 IdentityFile 指定的。GitHub 看到第一把不匹配的 key 直接拒绝(甚至触发 rate limit)。IdentitiesOnly yes 让 ssh 严格只用 IdentityFile 指定的那把。

详见 ssh-config.md "场景 3:GitHub 多账号"。


常见踩坑

坑 1:生成时回车太快,把已有 key 覆盖了

ssh-keygen -t ed25519
Enter file in which to save the key (~/.ssh/id_ed25519):   ← 默认路径
Overwrite (y/n)?                                            ← 这里手快按 y 就完了

已有 key 千万别覆盖 —— 覆盖了,之前所有部署过这把公钥的机器全部认不出你。

防御做法:

  • 生成新 key 时显式 -f ~/.ssh/id_ed25519_<purpose>
  • 在 ~/.ssh/ 已经有 id_* 时,先 ls ~/.ssh/ 看清楚

坑 2:私钥权限太宽,ssh 拒用

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/root/.ssh/id_rsa' are too open.

修复:

chmod 600 ~/.ssh/id_*           # 所有私钥
chmod 644 ~/.ssh/id_*.pub       # 公钥
chmod 700 ~/.ssh                # 目录
chmod 600 ~/.ssh/config         # config 也要 600
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/known_hosts

坑 3:把私钥 commit 进了 git

如果 ~/.ssh/id_rsa 不小心 commit 进 git 仓库(哪怕是 private 仓库),立刻视作泄漏:

  1. 生成新 key
  2. 在所有部署过的远端 ~/.ssh/authorized_keys 里删旧公钥
  3. GitHub 上从所有账号删旧 key
  4. 旧私钥从 git 历史里清掉(git filter-repo 或 BFG)—— 但即使清了,也应该认定泄漏过,不能再用

坑 4:authorized_keys 里有多行同样的公钥

手推 key 时 >> 反复追加 → 文件里同一个公钥出现 5 遍。不影响认证(认证逻辑是"任意一行匹配即通过"),但难维护。

修复(去重保留顺序):

awk '!seen[$0]++' ~/.ssh/authorized_keys > /tmp/auth && mv /tmp/auth ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

或者一开始就用幂等模式:grep -qxF '$PUBKEY' || echo '$PUBKEY' >>(见上面方法 2)。

坑 5:把公钥写错位置

echo "$PUBKEY" > ~/.ssh/authorized_keys           # ❌ 单 > 覆盖原有内容
echo "$PUBKEY" >> ~/.ssh/authorized_keys          # ✅ 双 >> 追加

血泪:> 写错 → 原 authorized_keys 里别人或自己其它 key 全没了 → 用户全部锁外面。

养成习惯:追加配置一律 >>,写新文件才 >。

坑 6:ed25519 老机器不认

no matching host key type found. Their offer: ssh-rsa

对方是老 ssh (OpenSSH < 6.5),不支持 ed25519。三种选择:

  1. 用 RSA key 连那台机器(推荐)
  2. 临时启用 RSA 算法:ssh -o HostKeyAlgorithms=+ssh-rsa user@host
  3. 升级远端 OpenSSH

关联命令

  • ssh-config —— 把这些 key 分发到不同 Host 段
  • ssh —— 用这把 key 实际登录
  • sshd —— 远端必须允许 PubkeyAuthentication,否则你 key 再对也白搭
  • ssh-add —— 把私钥加进 ssh-agent,免每次输 passphrase
在 GitHub 上编辑此页