排查 SSH 错误


本文档介绍使用 SSH 连接到虚拟机实例时可能会遇到的常见错误、解决错误的方法以及诊断失败的 SSH 连接的方法。

SSH 问题排查工具

使用 SSH 问题排查工具来帮助确定 SSH 连接失败的原因。问题排查工具会执行以下测试,以检查 SSH 连接失败的原因:

  • 用户权限测试:检查您是否具有使用 SSH 连接到虚拟机所需的 IAM 权限
  • 网络连接测试:检查虚拟机是否已连接到网络
  • 虚拟机实例状态测试:检查虚拟机的 CPU 状态,了解虚拟机是否正在运行。
  • VPC 设置测试:检查默认 SSH 端口。

运行问题排查工具

您可以使用 Google Cloud 控制台或 Google Cloud CLI 检查可能导致 SSH 连接失败的网络问题和用户权限错误。

控制台

SSH 连接失败后,您可以选择重试连接,或使用浏览器中的 SSH 问题排查工具来诊断连接问题。

要运行问题排查工具,请点击问题排查

启动 SSH 问题排查工具。

gcloud

使用 gcloud compute ssh 命令运行问题排查工具:

gcloud compute ssh VM_NAME \
    --troubleshoot

VM_NAME 替换为无法连接的虚拟机的名称。

该工具会提示您提供执行问题排查测试的权限。

查看结果

运行问题排查工具后,请执行以下操作:

  1. 查看测试结果,了解虚拟机的 SSH 连接无法正常工作的原因。
  2. 通过执行该工具提供的补救步骤来解决 SSH 连接问题。
  3. 尝试重新连接到虚拟机。

    如果连接失败,请尝试执行以下操作来手动排查问题:

常见 SSH 错误

以下是使用 SSH 连接到 Compute Engine 虚拟机时可能会遇到的常见错误示例。

SSH-in-Browser 错误

未经授权错误 401

当您从 Google Cloud 控制台使用 SSH-in-browser 连接到虚拟机时,可能会发生以下错误:

Unauthorized
Error 401

如果您的用户属于在 Google Workspace 中管理的组织,并且 Workspace 政策中存在有效限制,导致用户无法访问 SSH-in-browser 和 Google Cloud 中的串行控制台,则会发生此错误。

如需解决此问题,请让 Google Workspace 管理员执行以下操作:

  1. 确认已为组织启用 Google Cloud

    如果 Google Cloud 被停用,请启用它并重试连接。

  2. 确认已启用无法单独控制的服务。

    如果这些服务被停用,请启用它们并重试连接。

如果在 Google Workspace 中启用 Google Cloud 设置后问题仍然存在,请执行以下操作:

  1. 从您启动 SSH-in-Browser SSH 连接时开始,以 HTTP 归档格式 (HAR) 文件的形式捕获网络流量

  2. 创建 Cloud Customer Care 支持请求并附上 HAR 文件。

无法连接,正在重试…

启动 SSH 会话时可能会出现以下错误:

Could not connect, retrying ...

无法连接,正在重试

如需解决此问题,请执行以下操作:

  1. 虚拟机完成启动后,重新尝试连接。如果连接不成功,请通过运行以下命令验证虚拟机未在紧急模式下启动:

    gcloud compute instances get-serial-port-output VM_NAME \
    | grep "emergency mode"
    

    如果虚拟机在紧急模式下启动,请对虚拟机启动过程进行问题排查,以确定启动过程失败的位置。

  2. 串行控制台中运行以下命令,验证 google-guest-agent.service 服务是否正在运行。

    systemctl status google-guest-agent.service
    

    如果该服务已停用,请运行以下命令启用并启动该服务:

    systemctl enable google-guest-agent.service
    systemctl start google-guest-agent.service
    
  3. 验证 Linux Google 代理脚本是否已安装并正在运行。如需了解更多信息,请查看 确定 Google 代理状态。 如果未安装 Linux Google 代理,请重新安装

  4. 验证您是否拥有连接到虚拟机所需的角色。如果您的虚拟机使用 OS Login,请参阅分配 OS Login IAM 角色。如果虚拟机没有使用 OS Login,则您需要 Compute Instance Admin 角色Service Account User 角色(如果虚拟机设置为以服务账号运行)。需要这些角色才能更新实例或项目 SSH 密钥元数据。

  5. 运行以下命令,验证是否存在允许 SSH 访问的防火墙规则:

    gcloud compute firewall-rules list | grep "tcp:22"
    
  6. 验证是否存在通往互联网(或堡垒主机)的默认路由。如需了解详情,请参阅检查路由

  7. 确保根卷没有耗尽磁盘可用空间。如需了解更多信息,请查看 排查磁盘已满问题和磁盘大小调整问题

  8. 运行以下命令,确保虚拟机没有耗尽内存:

    gcloud compute instances get-serial-port-output instance-name \
    | grep "Out of memory: Kill process" - e "Kill process" -e "Memory cgroup out of memory" -e "oom"
    

    如果虚拟机内存不足,请连接到串行控制台以进行问题排查。

Linux 错误

权限遭拒(公钥)

在连接到虚拟机时可能会出现以下错误:

USERNAME@VM_EXTERNAL_IP: Permission denied (publickey).

此错误可能是由多种原因造成的。以下是导致此错误的最常见原因:

  • 使用存储在元数据中的 SSH 密钥连接到启用了 OS Login 的虚拟机。如果您的项目启用了 OS Login,则虚拟机不接受存储在元数据中的 SSH 密钥。 如果您不确定是否已启用 OS Login,请参阅检查是否已配置 OS Login

    要解决此问题,请尝试以下方法之一:

  • 使用存储在 OS Login 配置文件中的 SSH 密钥连接到未启用 OS Login 的虚拟机。如果您停用了 OS Login,则虚拟机不接受存储在 OS Login 配置文件中的 SSH 密钥。 如果您不确定是否已启用 OS Login,请参阅检查是否已配置 OS Login

    要解决此问题,请尝试以下方法之一:

  • 虚拟机已启用 OS Login,但您的 IAM 权限不足以使用 OS Login。 如需连接到已启用 OS Login 的虚拟机,您必须具有 OS Login 所需的权限。如果您不确定是否已启用 OS Login,请参阅检查是否已配置 OS Login

    如需解决此问题,请授予必要的 OS Login IAM 角色

  • 您的密钥已过期,Compute Engine 删除了 ~/.ssh/authorized_keys 文件。如果您手动将 SSH 密钥添加到虚拟机,然后使用 Google Cloud 控制台连接到虚拟机,则 Compute Engine 为您的连接创建了新的密钥对。新的密钥对过期后,Compute Engine 删除了虚拟机中的 ~/.ssh/authorized_keys 文件,其中包含您手动添加的 SSH 密钥。

    要解决此问题,请尝试以下方法之一:

  • 您使用了第三方工具进行连接,并且 SSH 命令配置有误。如果使用 ssh 命令进行连接,但未指定指向私钥的路径,或者指向私钥的路径不正确,则虚拟机会拒绝连接。

    要解决此问题,请尝试以下方法之一:

    • 运行以下命令:
      ssh -i PATH_TO_PRIVATE_KEY USERNAME@EXTERNAL_IP
      

      替换以下内容:
      • PATH_TO_PRIVATE_KEY:您的 SSH 私钥文件的路径。
      • USERNAME:连接到该实例的用户的用户名。如果您在元数据中管理 SSH 密钥,则用户名是您在创建 SSH 密钥时指定的名称。对于 OS Login 账号,用户名在 Google 个人资料中定义。
      • EXTERNAL_IP:您的虚拟机的外部 IP 地址。
    • 使用 Google Cloud 控制台或 Google Cloud CLI 连接到您的虚拟机。当您使用这些工具进行连接时,Compute Engine 会为您管理密钥创建。如需了解详情,请参阅连接到虚拟机
  • 您的虚拟机客机环境未在运行。如果这是您第一次连接到虚拟机并且客机环境未在运行,则虚拟机可能会拒绝您的 SSH 连接请求。

    如需解决此问题,请执行以下操作:

    1. 重启虚拟机。
    2. 在 Google Cloud 控制台中,检查串行端口输出中的系统启动日志,以确定客机环境是否正在运行。如需了解详情,请参阅验证客机环境
    3. 如果客机环境未运行,请通过克隆虚拟机的启动磁盘并使用启动脚本手动安装客机环境
  • OpenSSH 守护程序 (sshd) 未运行或配置不正确。 sshd 通过 SSH 协议提供对系统的安全远程访问。如果该服务器配置不正确或未运行,您将无法通过 SSH 连接到虚拟机。

    如需解决此问题,请尝试以下一项或多项操作:

    • 查阅操作系统的用户指南,确保正确设置了 sshd_config

    • 确保您拥有以下内容的必要所有权和权限设置:

      • $HOME$HOME/.ssh 目录
      • $HOME/.ssh/authorized_keys 文件

      负责

      客机环境会将已获授权的 SSH 公钥存储在 $HOME/.ssh/authorized_keys 文件中。$HOME$HOME/.ssh 目录以及 $HOME/.ssh/authorized_keys 文件的所有者必须与连接虚拟机的用户相同。

      权限

      客机环境需要以下 Linux 权限:

      路径 权限
      /home 0755
      $HOME 070007500755 *
      $HOME/.ssh 0700
      $HOME/.ssh/authorized_keys 0600

      * 如需了解哪些选项是 $HOME 目录的正确默认权限,请参阅适用于您的特定 Linux 发行版的官方文档。


      或者,您也可以基于同一映像创建新虚拟机,并检查 $HOME 的默认权限。

      如需了解如何更改权限和所有权,请阅读有关 chmodchown 的说明。

    • 运行以下命令重启 sshd

      systemctl restart sshd.service
      

      通过运行以下命令检查状态是否存在任何错误:

      systemctl status sshd.service
      

      状态输出可能包含退出代码、失败原因等信息。您可以使用这些详细信息进一步进行问题排查。

  • 虚拟机的启动磁盘已满。建立 SSH 连接后,客机环境会将会话的 SSH 公钥添加到 ~/.ssh/authorized_keys 文件。如果磁盘已满,则连接会失败。

    如需解决此问题,请执行以下一项或多项操作:

  • $HOME$HOME/.ssh$HOME/.ssh/authorized_keys 上的权限或所有权有误。

    负责

    客机环境会将已获授权的 SSH 公钥存储在 $HOME/.ssh/authorized_keys 文件中。$HOME$HOME/.ssh 目录以及 $HOME/.ssh/authorized_keys 文件的所有者必须与连接虚拟机的用户相同。

    权限

    客机环境需要以下 Linux 权限:

    路径 权限
    /home 0755
    $HOME 070007500755 *
    $HOME/.ssh 0700
    $HOME/.ssh/authorized_keys 0600

    * 如需了解哪些选项是 $HOME 目录的正确默认权限,请参阅适用于您的特定 Linux 发行版的官方文档。


    或者,您也可以基于同一映像创建新虚拟机,并检查 $HOME 的默认权限。

    要了解如何更改权限和所有权,请参阅 chmodchown

连接失败

从 Google Cloud 控制台、gcloud CLI、堡垒主机或本地客户端连接到虚拟机时,可能会出现以下错误:

  • Google Cloud 控制台:

    Connection Failed
    
    We are unable to connect to the VM on port 22.
    
  • gcloud CLI:

    ERROR: (gcloud.compute.ssh) [/usr/bin/ssh] exited with return code [255].
    
  • 堡垒主机或本地客户端:

    port 22: Connection timed out.
    
    port 22: Connection refused
    

出现这些错误可能有多种原因。以下是导致这些错误的一些最常见原因:

  • 虚拟机正在启动,而 sshd 尚未运行。在虚拟机运行之前您无法连接到虚拟机。

    如需解决此问题,请等待虚拟机完成启动,并尝试重新连接。

  • sshd 在自定义端口上运行。如果您将 sshd 配置为在端口 22 以外的端口上运行,您将无法连接到虚拟机。

    如需解决此问题,请使用以下命令创建自定义防火墙规则,以允许 sshd 运行的端口上的 tcp 流量:

    gcloud compute firewall-rules create FIREWALL_NAME \
      --allow tcp:PORT_NUMBER
    

    如需详细了解如何创建防火墙规则,请参阅创建防火墙规则

  • SSH 防火墙规则缺失或不允许来自 IAP 或公共互联网的流量。如果防火墙规则不允许来自 IP 范围 0.0.0.0/0 的 IAP 或 TCP 入站流量的连接,则 SSH 连接会被拒绝。

    如需解决此问题,请执行以下某项操作:

    • 如果您使用 Identity-Aware Proxy (IAP) 进行 TCP 转发,请更新自定义防火墙规则以接受来自 IAP 的流量,然后检查 IAM 权限。

      1. 更新自定义防火墙规则,以允许来自 35.235.240.0/20(IAP 用于 TCP 转发的 IP 地址范围)的流量。如需了解详情,请参阅创建防火墙规则
      2. 授予使用 IAP TCP 转发的权限(如果您尚未授予权限)。
    • 如果您不使用 IAP,请更新自定义防火墙规则以允许入站 SSH 流量。

      1. 更新自定义防火墙规则以允许到虚拟机的入站 SSH 连接
  • 升级虚拟机内核后 SSH 连接失败。内核更新后,虚拟机可能会遇到内核崩溃问题,导致虚拟机无法访问。

    如需解决此问题,请执行以下操作:

    1. 将磁盘装载到另一个虚拟机
    2. 更新 grub.cfg 文件以使用上一个版本的内核。
    3. 将磁盘挂接到无响应的虚拟机
    4. 使用 gcloud compute instances describe 命令验证虚拟机的状态是否为 RUNNING
    5. 重新安装内核
    6. 重启虚拟机。

    或者,如果您在升级虚拟机之前创建了启动磁盘快照,请使用快照创建虚拟机

  • OpenSSH 守护程序 (sshd) 未运行或配置不正确。 sshd 通过 SSH 协议提供对系统的安全远程访问。如果该服务器配置不正确或未运行,您将无法通过 SSH 连接到虚拟机。

    如需解决此问题,请尝试以下一项或多项操作:

    • 查阅操作系统的用户指南,确保正确设置了 sshd_config

    • 确保您拥有以下内容的必要所有权和权限设置:

      • $HOME$HOME/.ssh 目录
      • $HOME/.ssh/authorized_keys 文件

      负责

      客机环境会将已获授权的 SSH 公钥存储在 $HOME/.ssh/authorized_keys 文件中。$HOME$HOME/.ssh 目录以及 $HOME/.ssh/authorized_keys 文件的所有者必须与连接虚拟机的用户相同。

      权限

      客机环境需要以下 Linux 权限:

      路径 权限
      /home 0755
      $HOME 070007500755 *
      $HOME/.ssh 0700
      $HOME/.ssh/authorized_keys 0600

      * 如需了解哪些选项是 $HOME 目录的正确默认权限,请参阅适用于您的特定 Linux 发行版的官方文档。


      或者,您也可以基于同一映像创建新虚拟机,并检查 $HOME 的默认权限。

      如需了解如何更改权限和所有权,请阅读有关 chmodchown 的说明。

    • 运行以下命令重启 sshd

      systemctl restart sshd.service
      

      通过运行以下命令检查状态是否存在任何错误:

      systemctl status sshd.service
      

      状态输出可能包含退出代码、失败原因等信息。您可以使用这些详细信息进一步进行问题排查。

  • 虚拟机未启动,因此您无法使用 SSH 或串行控制台进行连接。如果虚拟机无法访问,则您的操作系统可能已损坏。如果启动磁盘未启动,您可以诊断问题。如果您要恢复损坏的虚拟机并检索数据,请参阅恢复损坏的虚拟机或存储空间已满的启动磁盘

  • 虚拟机正在以维护模式启动。 在维护模式下启动时,虚拟机不接受 SSH 连接,但您可以连接到虚拟机的串行控制台并以根用户身份登录。

    如需解决此问题,请执行以下操作:

    1. 如果您尚未为虚拟机设置根密码,请在启动期间使用元数据启动脚本运行以下命令:

      echo "root:NEW_PASSWORD" | chpasswd

      NEW_PASSWORD 替换为您选择的密码。

    2. 重启虚拟机。

    3. 连接到虚拟机的串行控制台,然后以根用户身份登录。

意外错误

尝试连接到 Linux 虚拟机时,可能会出现以下错误:

Connection Failed
You cannot connect to the VM instance because of an unexpected error. Wait a few moments and then try again.

此问题可能是由多种原因造成的。以下是导致此错误的一些常见原因:

  • OpenSSH 守护程序 (sshd) 未运行或配置不正确。 sshd 通过 SSH 协议提供对系统的安全远程访问。如果该服务器配置不正确或未运行,您将无法通过 SSH 连接到虚拟机。

    如需解决此问题,请尝试以下一项或多项操作:

    • 查阅操作系统的用户指南,确保正确设置了 sshd_config

    • 确保您拥有以下内容的必要所有权和权限设置:

      • $HOME$HOME/.ssh 目录
      • $HOME/.ssh/authorized_keys 文件

      负责

      客机环境会将已获授权的 SSH 公钥存储在 $HOME/.ssh/authorized_keys 文件中。$HOME$HOME/.ssh 目录以及 $HOME/.ssh/authorized_keys 文件的所有者必须与连接虚拟机的用户相同。

      权限

      客机环境需要以下 Linux 权限:

      路径 权限
      /home 0755
      $HOME 070007500755 *
      $HOME/.ssh 0700
      $HOME/.ssh/authorized_keys 0600

      * 如需了解哪些选项是 $HOME 目录的正确默认权限,请参阅适用于您的特定 Linux 发行版的官方文档。


      或者,您也可以基于同一映像创建新虚拟机,并检查 $HOME 的默认权限。

      如需了解如何更改权限和所有权,请阅读有关 chmodchown 的说明。

    • 运行以下命令重启 sshd

      systemctl restart sshd.service
      

      通过运行以下命令检查状态是否存在任何错误:

      systemctl status sshd.service
      

      状态输出可能包含退出代码、失败原因等信息。您可以使用这些详细信息进一步进行问题排查。

  • 未知 SSH 守护程序问题。如需诊断未知 SSH 守护程序问题,请检查串行控制台日志中是否存在错误。

    根据串行控制台日志的输出,尝试执行以下操作来救援虚拟机并解决与 SSH 守护程序相关的问题:

    1. 磁盘挂接到另一个 Linux 虚拟机。
    2. 连接到具有已装载磁盘的虚拟机。
    3. 将操作系统内的磁盘装载到虚拟机内的 MOUNT_DIR 目录下。
    4. 查看与 SSH 相关的日志(/var/log/secure/var/log/auth.log),了解任何问题/错误。如果您看到任何可以修复的问题,请尝试修复这些问题。否则,请创建支持请求并附加日志。
    5. 使用 umount 命令从操作系统卸载磁盘:

      cd ~/
      umount /mnt
      
    6. 从虚拟机分离磁盘

    7. 磁盘挂接到原始虚拟机。

    8. 启动虚拟机。

无法连接到后端

从 Google Cloud 控制台或 gcloud CLI 连接到虚拟机时,可能会出现以下错误:

  • Google Cloud 控制台:

    -- Connection via Cloud Identity-Aware Proxy Failed
    
    -- Code: 4003
    
    -- Reason: failed to connect to backend
    
  • gcloud CLI:

    ERROR: (gcloud.compute.start-iap-tunnel) Error while connecting [4003: 'failed to connect to backend'].
    

如果您尝试使用 SSH 连接到没有公共 IP 地址并且未在端口 22 上配置 Identity-Aware Proxy 的虚拟机,则会出现这些错误。

如需解决此问题,请在端口 22 上创建防火墙规则,用于允许来自 Identity-Aware Proxy 的入站流量。

主机密钥不匹配

在连接到虚拟机时可能会出现以下错误:

Host key for server IP_ADDRESS does not match

~/.ssh/known_hosts 文件中的主机密钥与虚拟机的主机密钥不匹配时,将会发生此错误。

如需解决此问题,请从 ~/.ssh/known_hosts 文件中删除主机密钥,然后重试连接。

元数据值过大

如果您尝试向元数据添加新的 SSH 密钥,可能会发生以下错误:

ERROR:"Value for field 'metadata.items[X].value' is too large: maximum size 262144 character(s); actual size NUMBER_OF_CHARACTERS."

元数据值的大小上限为 256 KB。如需缓解此限制,请执行以下操作之一:

Windows 错误

权限遭拒,请重试

在连接到虚拟机时可能会出现以下错误:

USERNAME@compute.INSTANCE_ID's password:
Permission denied, please try again.

此错误表示尝试连接到虚拟机的用户在该虚拟机上不存在。以下是导致此错误的最常见原因:

  • 您的 gcloud CLI 版本已过期

    如果 gcloud CLI 已过期,您可能会尝试使用未配置的用户名进行连接。如需解决此问题,请更新 gcloud CLI

  • 您尝试连接到未启用 SSH 的 Windows 虚拟机。

    如需解决此错误,请在项目或实例元数据中将 enable-windows-ssh 键设置为 TRUE。如需详细了解如何设置元数据,请参阅设置自定义元数据

权限遭拒(公钥、键盘交互式)

当您连接到未启用 SSH 的虚拟机时,可能会发生以下错误:

Permission denied (publickey,keyboard-interactive).

如需解决此错误,请在项目或实例元数据中将 enable-windows-ssh 键设置为 TRUE。如需详细了解如何设置元数据,请参阅设置自定义元数据

无法通过 SSH 连接到实例

从 gcloud CLI 连接到虚拟机时,可能会发生以下错误:

ERROR: (gcloud.compute.ssh) Could not SSH into the instance.
It is possible that your SSH key has not propagated to the instance yet.
Try running this command again.  If you still cannot connect, verify that the firewall and instance are set to accept ssh traffic.

此错误可能是由多种原因造成的。以下是导致这些错误的一些最常见原因:

连接超时

SSH 连接超时可能是由以下某种原因造成的:

  • 虚拟机尚未完成启动。虚拟机启动会需要一些时间,请稍等片刻。

    如需解决此问题,请等待虚拟机完成启动,并尝试重新连接。

  • 未安装 SSH 软件包。Windows 虚拟机要求您安装 google-compute-engine-ssh 软件包,然后才能使用 SSH 进行连接。

    如需解决此问题,请安装 SSH 软件包

诊断失败的 SSH 连接

以下部分介绍了诊断 SSH 连接失败原因的步骤以及修复连接的步骤。

在诊断失败的 SSH 连接之前,请完成以下步骤:

Linux 和 Windows 虚拟机的诊断方法

测试连接性

如果存在与防火墙、网络连接或用户账号相关的连接性问题,您可能无法通过 SSH 连接到虚拟机实例。您可以按照本部分中的步骤来确定任何连接性问题。

检查防火墙规则

Compute Engine 为每个项目预配了一组允许 SSH 流量的默认防火墙规则。如果您无法访问实例,请使用 gcloud compute 命令行工具来检查您的防火墙列表并确保存在 default-allow-ssh 规则。

在本地工作站上,请运行以下命令:

gcloud compute firewall-rules list

如果缺少该规则,请重新添加:

gcloud compute firewall-rules create default-allow-ssh \
    --allow tcp:22

如需查看与您的项目中 default-allow-ssh 防火墙规则关联的所有数据,请使用 gcloud compute firewall-rules describe 命令

gcloud compute firewall-rules describe default-allow-ssh \
    --project=project-id

如需详细了解防火墙规则,请参阅 Google Cloud 中的防火墙规则

测试网络连接

如需确定网络连接是否正常,请测试 TCP 握手:

  1. 获取虚拟机的外部 natIP

    gcloud compute instances describe VM_NAME \
        --format='get(networkInterfaces[0].accessConfigs[0].natIP)'
    

    VM_NAME 替换为无法连接的虚拟机的名称。

  2. 测试从您的工作站到虚拟机的网络连接:

    Linux、Windows 2019/2022 和 macOS

    curl -vso /dev/null --connect-timeout 5 EXTERNAL_IP:PORT_NUMBER
    

    替换以下内容:

    • EXTERNAL_IP:您在上一步中获得的外部 IP 地址
    • PORT_NUMBER:端口号

    如果 TCP 握手成功,则输出类似于以下内容:

    Expire in 0 ms for 6 (transfer 0x558b3289ffb0)
    Expire in 5000 ms for 2 (transfer 0x558b3289ffb0)
    Trying 192.168.0.4...
    TCP_NODELAY set
    Expire in 200 ms for 4 (transfer 0x558b3289ffb0)
    Connected to 192.168.0.4 (192.168.0.4) port 443 (#0)
    > GET / HTTP/1.1
    > Host: 192.168.0.4:443
    > User-Agent: curl/7.64.0
    > Accept: */*
    >
    Empty reply from server
    Connection #0 to host 192.168.0.4 left intact
    

    Connected to 行表示 TCP 握手成功。

    Windows 2012 和 2016

    PS C:> New-Object System.Net.Sockets.TcpClient('EXTERNAL_IP',PORT_NUMBER)
    

    替换以下内容:

    • EXTERNAL_IP:您在上一步中获得的外部 IP
    • PORT_NUMBER:端口号

    如果 TCP 握手成功,则输出类似于以下内容:

    Available           : 0
    Client              : System.Net.Sockets.Socket
    Connected           : True
    ExclusiveAddressUse : False
    ReceiveBufferSize   : 131072
    SendBufferSize      : 131072
    ReceiveTimeout      : 0
    SendTimeout         : 0
    LingerState         : System.Net.Sockets.LingerOption
    NoDelay             : False
    

    Connected: True 行表示 TCP 握手成功。

如果 TCP 握手成功完成,则软件防火墙规则不会阻止连接,操作系统正确转发数据包,并且服务器正在监听目标端口。如果 TCP 握手成功完成,但虚拟机不接受 SSH 连接,则问题可能在于 sshd 守护程序配置错误或无法正常运行。请查看操作系统的用户指南,确保正确设置了 sshd_config

如需运行连接测试以分析两个虚拟机之间的 VPC 网络路径配置,并检查编程的配置是否应允许流量,请参阅检查 Google Cloud 中配置有误的防火墙规则

以其他用户身份连接

导致您无法登录的问题可能仅限于您的用户账号。例如,可能没有为用户正确设置实例上 ~/.ssh/authorized_keys 文件的权限。

您可以使用 gcloud CLI 在 SSH 请求中指定 ANOTHER_USERNAME,尝试以其他用户身份登录。gcloud CLI 将更新项目的元数据以添加新用户并允许进行 SSH 访问。

gcloud compute ssh ANOTHER_USERNAME@VM_NAME

替换以下内容:

  • ANOTHER_USERNAME 是不同于您自己的用户名的用户名
  • VM_NAME 是您要连接的虚拟机的名称

使用串行控制台对问题进行调试

我们建议您检查串行控制台中的日志是否存在连接错误。您可以使用浏览器以根用户身份从本地工作站访问串行控制台。如果您无法使用 SSH 登录或者实例没有连接到网络,这种方法非常有用。在这两种情况下,串行控制台仍然可供访问。

如需登录虚拟机的串行控制台并排查虚拟机问题,请按照以下步骤操作:

  1. 启用对于虚拟机串行控制台的交互式访问

  2. 对于 Linux 虚拟机,请修改根密码,并将以下启动脚本添加到您的虚拟机:

    echo root:PASSWORD | chpasswd

    PASSWORD 替换为您选择的密码。

  3. 使用串行控制台连接到您的虚拟机

  4. 对于 Linux 虚拟机,请在完成对所有错误的调试后停用根账号登录:

    sudo passwd -l root

Linux 虚拟机的诊断方法

在不关停虚拟机实例的情况下对其进行检查

您可能无法连接某个实例,但该实例可以继续正常处理生产流量。遇到这种情况时,建议您在不中断实例的情况下检查磁盘。

如需检查磁盘并进行问题排查,请执行以下操作:

  1. 通过创建磁盘快照来备份您的启动磁盘。
  2. 通过该快照创建一个常规永久性磁盘。
  3. 创建一个临时实例。
  4. 将该常规永久性磁盘挂接并装载到新的临时实例。

此过程会创建仅允许通过 SSH 连接的隔离网络,以防止克隆实例干扰生产服务,造成意想不到的后果。

  1. 创建新的 VPC 网络以托管您的克隆实例:

    gcloud compute networks create debug-network
    

    NETWORK_NAME 替换为您想要使用的新网络名称。

  2. 添加防火墙规则以允许通过 SSH 连接到网络:

    gcloud compute firewall-rules create debug-network-allow-ssh \
       --network debug-network \
       --allow tcp:22
    
  3. 创建启动磁盘的快照。

    gcloud compute disks snapshot BOOT_DISK_NAME \
       --snapshot-names debug-disk-snapshot
    

    BOOT_DISK_NAME 替换为启动磁盘的名称。

  4. 使用您刚创建的快照创建新磁盘:

    gcloud compute disks create example-disk-debugging \
       --source-snapshot debug-disk-snapshot
    
  5. 创建没有外部 IP 地址的新调试实例:

    gcloud compute instances create debugger \
       --network debug-network \
       --no-address
    
  6. 将调试磁盘挂接到实例:

    gcloud compute instances attach-disk debugger \
       --disk example-disk-debugging
    
  7. 按照说明使用堡垒主机连接到虚拟机

  8. 登录调试程序实例后,排查实例问题。例如,您可以查看实例日志:

    sudo su -
    
    mkdir /mnt/VM_NAME
    
    mount /dev/disk/by-id/scsi-0Google_PersistentDisk_example-disk-debugging /mnt/VM_NAME
    
    cd /mnt/VM_NAME/var/log
    
    # Identify the issue preventing ssh from working
    ls
    

    VM_NAME 替换为无法连接的虚拟机的名称。

使用启动脚本

如果上述步骤不起作用,您可以创建启动脚本以在实例启动后立即收集信息。按照说明来运行启动脚本

之后,您还需要使用 gcloud compute instances reset 重置您的实例,然后元数据才会生效。

或者,您也可以运行诊断启动脚本来重新创建您的实例:

  1. 运行带有 --keep-disks 标志的 gcloud compute instances delete

    gcloud compute instances delete VM_NAME \
       --keep-disks boot
    

    VM_NAME 替换为无法连接的虚拟机的名称。

  2. 添加挂接了同一磁盘的新实例并指定您的启动脚本。

    gcloud compute instances create NEW_VM_NAME \
       --disk name=BOOT_DISK_NAME,boot=yes \
       --metadata startup-script-url URL
    

    替换以下内容:

    • NEW_VM_NAME 是您要创建的新虚拟机的名称
    • BOOT_DISK_NAME 是您无法连接的虚拟机中的启动磁盘的名称
    • URL 是脚本的 Cloud Storage 网址,格式为 gs://BUCKET/FILEhttps://storage.googleapis.com/BUCKET/FILE

在新实例上使用磁盘

如果您仍需要从永久性启动磁盘恢复数据,则可以分离启动磁盘,然后将该磁盘作为辅助磁盘挂接到新实例上。

  1. 删除无法连接的虚拟机并保留其启动磁盘:

    gcloud compute instances delete VM_NAME \
       --keep-disks=boot 

    VM_NAME 替换为无法连接的虚拟机的名称。

  2. 使用旧虚拟机的启动磁盘创建新的虚拟机。指定刚刚删除的虚拟机的启动磁盘名称。

  3. 使用 SSH 连接到新虚拟机:

    gcloud compute ssh NEW_VM_NAME
    

    NEW_VM_NAME 替换为新虚拟机的名称。

检查虚拟机启动磁盘是否已满

如果虚拟机启动磁盘已满,则您可能无法访问虚拟机。此情况可能很难进行问题排查,因为虚拟机连接问题是由于启动磁盘已满导致时,这种情况并不总是显而易见。如需详细了解此情况,请参阅排查由于启动磁盘已满而导致无法访问的虚拟机的问题

Windows 虚拟机的诊断方法

重置 SSH 元数据

如果您无法使用 SSH 连接到 Windows 虚拟机,请尝试取消设置 enable-windows-ssh 元数据键,然后重新启用适用于 Windows 的 SSH。

  1. enable-windows-ssh 元数据键设置为 FALSE。如需了解如何设置元数据,请参阅设置自定义元数据

    请等待几秒钟,以便更改生效。

  2. 重新启用适用于 Windows 的 SSH

  3. 重新连接到虚拟机

使用 RDP 连接到虚拟机

如果您无法诊断导致与 Windows 虚拟机的 SSH 连接失败的原因并解决问题,请使用 RDP 进行连接

与虚拟机建立连接后,请查看 OpenSSH 日志

使用 gcpdiag 调试 SSH 问题

gcpdiag 是一种开源工具,不是由官方提供支持的 Google Cloud 产品。您可以使用 gcpdiag 工具来帮助识别和修复 Google Cloud 项目问题。如需了解详情,请参阅 GitHub 上的 gcpdiag 项目

此 gcpdiag runbook 用于调查 Google Cloud 中 Windows 和 Linux 虚拟机上出现 SSH 连接问题的潜在原因,并检查以下方面:
  • 虚拟机健康状况:检查虚拟机是否正在运行以及是否有足够的资源(CPU、内存、磁盘存储空间)。
  • 权限:确保您拥有正确的 IAM 权限来配置 SSH 密钥。
  • 虚拟机设置:验证 SSH 密钥和其他元数据是否已正确配置。
  • 网络规则:查看防火墙规则,确认允许 SSH 流量。
  • 客户操作系统:查找可能阻止 SSH 的内部操作系统问题。

Google Cloud 控制台

  1. 完成然后复制以下命令。
  2. gcpdiag runbook gce/ssh --project=PROJECT_ID \
        --parameter name=VM_NAME \
        --parameter zone=ZONE \
        --parameter principal=PRINCIPAL \
        --parameter tunnel_through_iap=IAP_ENABLED \
        --parameter check_os_login=OS_LOGIN_ENABLED
  3. 打开 Google Cloud 控制台并激活 Cloud Shell。
  4. 打开 Cloud 控制台
  5. 粘贴复制的命令。
  6. 运行 gcpdiag 命令以下载 gcpdiag Docker 映像,然后执行诊断检查。如果适用,请按照输出说明修复失败的检查。

Docker

您可以使用封装容器运行 gcpdiag,以在 Docker 容器中启动 gcpdiag。必须安装 Docker 或 Podman

  1. 在本地工作站上复制并运行以下命令。
    curl https://gcpdiag.dev/gcpdiag.sh >gcpdiag && chmod +x gcpdiag
  2. 执行 gcpdiag 命令:
    ./gcpdiag runbook gce/ssh --project=PROJECT_ID \
        --parameter name=VM_NAME \
        --parameter zone=ZONE \
        --parameter principal=PRINCIPAL \
        --parameter tunnel_through_iap=IAP_ENABLED \
        --parameter check_os_login=OS_LOGIN_ENABLED

查看此 Runbook 的可用参数

替换以下内容:

  • PROJECT_ID:资源所在项目的 ID
  • VM_NAME:项目中的目标虚拟机的名称。
  • ZONE:目标虚拟机所在的可用区。
  • PRINCIPAL:启动 SSH 连接的用户或服务账号主账号。对于基于密钥的身份验证,请使用通过 Cloud Shell 命令行工具进行身份验证或登录 Google Cloud 控制台的用户。对于服务账号模拟,这应该是服务账号的电子邮件地址。
  • IAP_ENABLED:一个布尔值(true 或 false),指示是否使用 Identity-Aware Proxy 建立 SSH 连接。默认值:true
  • OS_LOGIN_ENABLED:一个布尔值(true 或 false),指示是否使用 OS Login 进行 SSH 身份验证。默认值:true

实用标志:

  • --projectPROJECT_ID
  • --universe-domain:如果适用,则为托管资源的可信合作伙伴主权云网域
  • --parameter-p:Runbook 参数

如需查看所有 gcpdiag 工具标志的列表和说明,请参阅 gcpdiag 使用说明

后续步骤