跳转到内容

SSH

本内容于 2026-07-28 从此部署的某个 CE 上采集。sitecli/capture-manifest.json 记录了具体节点,scripts/capture-sitecli.sh --check 可对照运行中的 CE 重新验证命令接口。

SSH 可访问设备 admin 账户,其登录 Shell 为站点 CLI (/opt/bin/vpmu)。这是进入完整节点命令接口的唯一途径—— 调试 API 提供 34 条命令,而设备本身还提供许多未包含在该 API 中的命令。

Terminal window
cd terraform
SLI=$(terraform output -json ce_sli_private_ips | jq -r '.eastus01')
ssh -tt -i ~/.ssh/id_ed25519 -J azureuser@<operator-vm> "admin@$SLI"

该命令行中的每个部分都不可或缺,接下来三个章节将分别说明各参数所预防的故障。

登录后不会出现 Shell 提示符:admin 的登录 Shell 即为站点 CLI,因此您会直接进入其 >>> 提示符。在此处以 execcli <name> 运行节点命令——请参阅节点命令

为何由 cloud-init 写入密钥,而非通过 API

Section titled “为何由 cloud-init 写入密钥,而非通过 API”

站点对象上的 admin_user_credentials.ssh_key 看起来正是用于此功能的字段。它可以被接受,也能通过读回验证,但它不配置任何东西。vpm 拥有节点的本地用户管理权,并拒绝处理该账户——来自节点自身的日志,在单次启动过程中出现了三次:

vpm users.go:165: Won't do any change for user admin (internal skip)

后续所有现象都源于这一行。无论是在站点达到 ONLINE 之前还是之后,/var/home/admin/.ssh 始终不存在。admin 的 shadow 最后修改日期停留在镜像构建日期,而 vesbkpvesopcon 显示当前日期——因为 vpm 设置了这两个账户,跳过了 admin。并且 vpm 的日志中任何时候都没有关于 ssh_keyauthorized_keys 的记录。

因此,该文件必须在 vpm 之外写入。admin 的 uid 为 2202,已固化在节点镜像中,因此在 cloud-init 运行之前它就已存在,owner: admin:admin 在写入时即可解析——无需 runcmd,无需修复所有权:

- path: /var/home/admin/.ssh/authorized_keys
permissions: "0600"
owner: admin:admin
content: |
${ssh_public_key}

sshd 始终是允许的。sshd -T 报告 pubkeyauthentication yesadmin 也出现在节点上附带的两个 sshd_config 文件的 AllowUsers 中。从来没有任何需要启用的内容——只是缺少一个文件。

sshd 绑定 0.0.0.0:22,但只有**内部(SLI)**地址以 sshd 会响应的方式位于主机网络栈上。eth0 被重命名为 a-i-eth0,完全不承载主机 IP——Argo 数据平面拥有该接口,其本应承载的管理/SLO 地址改由 vhost0 承载。另外两块网卡以其自身名称保留在主机网络栈上。

从 VNet 内部的虚拟机对某个 CE 进行探测:

management/SLO address 超时
external address 超时
internal/SLI address OPEN SSH-2.0-OpenSSH_8.7
an unused address 超时 (对照组)

因此,对您熟知的节点地址进行探测,其结果与被安全组关闭时完全相同。没有任何阻断;只是该地址上没有监听器。

CE 公网地址的 22 端口同样没有监听器,这就是上述命令需要 -J 跳转的原因:需要通过一个位于 VNet 内部、与 SLI 地址处于同一子网的运维虚拟机中转。本部署为此专门构建了一个——terraform output -raw client_vm_name 可获取其名称。

admin 的登录 Shell 不是一个 Shell,而是一个 go-prompt 应用程序,它会将终端置于原始模式并逐键读取,而非按行读取。这带来四个后果,每一个的失败表现都像是不同的问题:

机制缺失时的表现
分配终端(ssh -ttgo-prompt.NewStandardInputParser 抛出 panic: no such device or address,看起来像设备崩溃
按 Enter 时发送回车符而非换行符该行永远不会被提交,会话在输入结束时关闭且未打印任何内容
保持标准输入打开连接在命令渲染完成前结束,导致正常的命令看起来没有输出
分别发送命令文本和 Enter 字节换行符以字面字符形式落入缓冲区,CLI 回应 unknown command,看起来像命令不存在

因此 ssh host 'some-command' 无法工作:参数被忽略,交互式提示符照常启动。必须作为终端来驱动,否则无从操作。scripts/sitecli_ssh_harvest.py 是参考实现。

在您输入任何内容之前,登录横幅已经回答了若干您本需花费命令才能得到的问题。来自 f5-xc-ce-vm-01 的示例,ASCII 图案和公网 IP 已省略:

UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED
All actions performed on this device are audited
Using https://register.ves.volterra.io
OS: rhel-9.2024.6
Memory: 32768MiB
Storage: sda: 31GiB
CPU: Model: Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz | CPUs: 8
Software: crt-20250613-3382
DNS: 168.63.129.16: OK
NTP: Synced
Uptime: 0 days, 5 hours, 20 minutes
Registration Status: PROVISIONED
SLO IP: 10.0.1.4/26
WELCOME IN SITE CLI

Registration Status 可区分仍在启动中的节点(PROVISIONING)和已完成的节点(PROVISIONED)。Software 是决定哪些命令存在的构建字符串。DNSNTP 涵盖了最先导致注册失败的两个依赖项,因此从未上线的节点通常在这里就已经告知了原因——无需再运行 chronyc-sourcesdig

  1. 如果您还没有密钥对,请先生成一个。选择 Ed25519 而非 RSA:更短,且被设备 sshd 接受。

    Terminal window
    ssh-keygen -t ed25519 -C "ce-operator" -f ~/.ssh/id_ed25519
  2. 公钥部分指向部署。根模块读取一次该文件并将字符串传递给每个节点:

    terraform/terraform.tfvars
    ssh_public_key_path = "~/.ssh/id_ed25519.pub"

    ssh_public_key 接受内联的密钥内容,这是计划测试所使用的方式。私钥永远不会离开您的工作站。

  3. 执行 Apply。请先阅读本页顶部的警告——在现有部署上,此操作将替换 CE 虚拟机。

以下每一项都曾在该路径仍被认为不可能时经过测试并被排除。每一项都足够合理,可能浪费一整天时间。

非原因排除方式
凭据仅在创建时生效sshd 在首次启动约 90 秒时启动,此时站点对象尚不存在。admin_user_credentials 也存在于 ReplaceSpecType 中并原地生效。
block_all_services无论是否阻断服务,管理地址上 22 端口的关闭表现完全相同。
密钥末尾有多余换行符两种方式均已测试,无变化。Cloud-init 仍会将其去除,因为字面块否则会渲染出多余的空行。
固定的旧版 CE 软件在三次构建中均已复现,包括一次运行 OpenSSH 9.9 的情况。
缺少 admin_password在全新 CE 上同时设置 admin_passwordssh_key 没有任何变化。