LXC 容器中的 SSH 运维技巧
posts/ssh-tips-for-lxc上一篇 LXC 搭建 K8s 集群计划通 中部署了一组 LXC 容器,后续的容器管理、服务访问和文件操作都大量使用了 SSH。本文整理一些 LXC 场景下常用的 SSH 技巧。
SSH 连接管理
ProxyJump 跳板配置
LXC 容器默认走 lxcbr0 的 NAT 网络,从外部无法直接 SSH 进入。可将宿主机作为跳板机,借助 ProxyJump 一次连通,配置写入 ~/.ssh/config:
Host lan.arch-lxc-1
Hostname <ip>
User root
ServerAliveInterval 10
IdentityFile ~/.ssh/personal/id_ed25519
IdentitiesOnly yes
ProxyJump lan.arch
Host lan.arch
HostName <ip>
ServerAliveInterval 10
IdentityFile ~/.ssh/personal/id_ed25519
IdentitiesOnly yes
执行 ssh lan.arch-lxc-1 时,SSH 会先连接宿主机,再由宿主机跳转至对应容器。容器数量较多时,可按 lan.arch-lxc-N 依次添加配置。
ssh -J 一次性跳板
若不想写入 config,可直接用 -J 在命令行指定跳板机:
ssh -J lan.arch lan.arch-lxc-1
效果等同于 ProxyJump,适合临时性场景。
复用 SSH 连接
在跳板机跳转的场景下,每次执行命令都需要重新进行 SSH 握手,会带来明显的延迟。可以通过 ControlMaster 实现 SSH 连接复用:
mkdir ~/.ssh/sockets/
Host lan.arch lan.arch-lxc-*
ControlMaster auto
ControlPath ~/.ssh/sockets/%C
ControlPersist 10m
%C 是 OpenSSH 根据连接参数计算出的哈希值,可以避免 ControlPath 过长。相比 %r@%h:%p 这类可读形式,使用 %C 更适合作为 Unix socket 路径。
首次执行 ssh lan.arch-lxc-1 建立主连接后,在十分钟内再次连接同一目标时,SSH 会复用已有 socket,从而跳过重复的 SSH 握手过程。
如果跳板机发生重启,已有的 master connection 会因远端连接中断而失效,本地 control socket 可能暂时残留。再次连接时,SSH 会检测到已有 master connection 不可用,并重新建立新的主连接,通常无需手动删除 socket 文件。
如果 control socket 异常残留导致连接失败,可以使用 ssh -O exit 关闭 master connection,或手动删除对应 socket。
身份认证
首次推送公钥
使用密钥认证前,需要先用 ssh-copy-id 把本机公钥推送到跳板机与容器:
ssh-copy-id -i ~/.ssh/personal/id_ed25519.pub [email protected]
后续 SSH 即可全程走密钥认证,免去每次手动输入密码。
转发 SSH Agent
跳板机或容器内需要操作 git 仓库时,可将本机的 ssh-agent 透传过去,避免在每台机器上都部署私钥:
Host lan.arch-lxc-*
ForwardAgent yes
配置后,远程主机会创建一个 SSH 转发的 Unix socket($SSH_AUTH_SOCK 通常指向 /tmp/ssh-XXX/agent.XXX),签名请求代理回本机 ssh-agent,git push/pull 等操作将走本机鉴权。需要注意的是 ForwardAgent 仅透传 agent 连接,本机 agent 内还需先加载密钥才能生效:
ssh-add ~/.ssh/personal/id_ed25519
ssh-add -l
另外 ForwardAgent 会让目标主机上的特权用户获得本机 agent 中已加载身份的使用权(虽然拿不到私钥本身,但能以这些身份登录其他机器),公网环境慎用。
文件系统访问
guest 挂载 host
容器里挂宿主机的目录:
sshfs lan.arch:/path/on/host /mnt/host
host 挂载 guest
宿主机也可挂载容器内的目录(例如调试容器内某个服务的配置文件):
sshfs lan.arch-lxc-1:/path/in/container /mnt/guest
guest 挂载 guest
一个容器挂另一个容器:
sshfs lan.arch-lxc-2:/path/in/container /mnt/other
上面三条默认以 root 身份执行,非 root 用户挂载需要加 -o allow_other,并确保 fuse 配了 user_allow_other。
网络穿透
容器里的服务默认只能从宿主机内部访问。相比 nftables 配 DNAT,用 SSH 端口转发更轻量。
Local Forward
从本地访问容器里的服务(本地浏览器打开容器内起的 dashboard):
ssh -L 8080:127.0.0.1:8080 lan.arch-lxc-1
如果想让 LAN 里其他机器一起访问,把本地地址改成 0.0.0.0:
ssh -L 0.0.0.0:8080:127.0.0.1:8080 lan.arch-lxc-1
Remote Forward
反过来,让宿主机或 LAN 里其他机器访问容器内服务(典型场景:在容器里跑 dashboard,希望宿主机 http://lan.arch:8000 能访问到):
ssh -R 0.0.0.0:8000:127.0.0.1:8000 lan.arch
这条命令要在容器内执行。SSH 会在 lan.arch(宿主机)的 8000 端口监听,远端请求沿 SSH 通道回到容器里的 127.0.0.1:8000。-R 方向和 -L 相反:客户端起连接,宿主机的端口负责监听。