连接到虚拟机

Google Distributed Cloud (GDC) air-gapped 使用基于密钥的 SSH 身份验证建立与 Linux 虚拟机 (VM) 实例的连接。默认情况下,系统不会为 Linux 虚拟机上的本地用户配置密码。

准备工作

在连接到虚拟机之前,您必须满足以下前提条件:

  • 启用访问权限管理。 如果未在来宾环境中启用访问权限管理,您将无法继续操作。默认情况下,新虚拟机上会启用访问权限管理。
  • 启用虚拟机外部访问权限,允许任何对等方通过传输控制协议 (TCP) 端口 22 进行访问。
    • 对于 Windows 虚拟机,请在端口 3389 上启用虚拟机外部访问权限。
  • 在虚拟机所在的项目中设置 ProjectNetworkPolicy (PNP) 自定义资源。
    • 通过在项目中设置 PNP,您可以访问项目或组织之外的虚拟机。
    • 如需诊断您是否没有 PNP,请咨询您的基础设施运营商 (IO)。
  • 集群的登录访问权限。按照登录中的 CLI 步骤登录集群。
如需使用 gdcloud 命令行界面 (CLI) 命令,请确保您已下载、安装并配置 gdcloud CLI。 Distributed Cloud 的所有命令都使用 gdcloudkubectl CLI,并且需要 Linux 环境。

获取 kubeconfig 文件路径

如需针对管理 API 服务器运行命令,请确保您拥有以下资源:

  1. 登录并生成管理 API 服务器的 kubeconfig 文件(如果您还没有)。

  2. 使用管理 API 服务器的 kubeconfig 文件路径替换这些说明中的 MANAGEMENT_API_SERVER

请求权限和访问权限

如需执行本页面中列出的任务,您必须具有 Project VirtualMachine Admin 角色。按照相关步骤验证您是否在虚拟机所在项目的命名空间中拥有 Project VirtualMachine Admin (project-vm-admin) 角色。

对于使用 GDC 控制台或 gdcloud CLI 的虚拟机操作,请让您的项目 IAM 管理员为您分配“Project VirtualMachine Admin”角色和“Project Viewer”角色 (project-viewer)。

建立虚拟机连接

本部分介绍如何建立与 Linux 和 Windows 虚拟机的连接。

连接到 Linux 虚拟机

如需建立与 Linux 虚拟机的连接,请使用 GDC 控制台、gdcloud CLI 或 Virtual Machine Manager API

控制台

  1. 在导航菜单中,依次点击 Virtual Machines > Instances

  2. 在虚拟机列表中,找到要连接的正在运行的虚拟机所在的行。在连接列中,点击 SSH

  3. 系统会打开 SSH 浏览器终端。在 shell 中输入任意命令,或点击 FTP 以浏览文件结构并上传文件。

gdcloud

通过运行 gdcloud compute ssh 命令使用 SSH 连接到虚拟机

gdcloud compute ssh VM_NAME --project=PROJECT_ID

执行以下变量替换操作:

  • VM_NAME:虚拟机的名称。
  • PROJECT_ID:包含虚拟机的项目的 ID。

如果您已为该 CLI 设置默认属性,则可以在此命令中省略 --project 标志。例如:

gdcloud compute ssh VM_NAME

API

连接到虚拟机:

  • 打开终端。
  • 创建 SSH 密钥对。
  • 上传具有存留时间 (TTL) 值的公钥和用户名。

GDC 会检索 SSH 密钥和用户名,并使用该用户名创建一个用户账号。在 Linux 虚拟机上,GDC 会将公钥存储在虚拟机上您用户的 ~/.ssh/authorized_keys 文件中。

如需通过命令行连接到虚拟机,请完成以下步骤:

  1. 创建 SSH 密钥对和用户名。

    在 Linux 和 macOS 工作站上,使用 ssh-keygen 实用程序创建新的 SSH 密钥对。以下代码示例会创建 RSA (Rivest–Shamir–Adleman) 密钥对:

    ssh-keygen -t rsa -f ~/.ssh/KEY_FILENAME -C USERNAME -b 2048
    

    使用以下定义替换变量。

    变量定义
    KEY_FILENAME SSH 密钥文件的名称。例如,如果文件名为 my-ssh-key,则系统会生成一个名为 my-ssh-key 的私钥文件和一个名为 my-ssh-key.pub 的公钥文件。
    USERNAME 您在虚拟机上的用户名,例如 testusertestuser_gmail_com

    ssh-keygen 实用程序会将您的私钥文件保存到 ~/.ssh/KEY_FILENAME 路径,并将公钥文件保存到 ~/.ssh/KEY_FILENAME.pub 路径。

    用户 testuser 的公钥类似于以下示例:

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAu5kKQCPF... testuser
    
  2. 将密钥上传到虚拟机,并使用公钥、用户名和密钥的存留时间 (TTL) 值创建 Kubernetes 资源。

    以下示例使用 access_request.yaml 文件授予对具有 KEY_FILENAME 私钥的虚拟机实例的访问权限,并将 TTL 值设置为 10 分钟:

    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachineAccessRequest
    metadata:
      namespace: VM_NAMESPACE
      name: AR_NAME
    spec:
      ssh:
        key: |
          ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAu5kKQCPF... cloudysanfrancisco
        ttl: 10m
      user: USERNAME
      vm: VM_NAME
    

    使用以下定义替换变量:

    变量定义
    VM_NAMESPACE 虚拟机的命名空间。
    AR_NAME 访问请求名称。
    USERNAME 您在虚拟机上的用户名,例如 testusertestuser_gmail_com
    VM_NAME 虚拟机实例的名称。
  3. 创建密钥:

    kubectl create -f access_request.yaml --kubeconfig MANAGEMENT_API_SERVER
    
  4. 查看访问权限请求的状态:

    kubectl get virtualmachineaccessrequests.virtualmachine.gdc.goog -n VM_NAMESPACE --kubeconfig MANAGEMENT_API_SERVER
    

    VM_NAMESPACE 替换为虚拟机的命名空间。

    configured 状态表示您可以连接到虚拟机。

  5. 连接到虚拟机:

    ssh -i PATH_TO_PRIVATE_KEY USERNAME@EXTERNAL_IP
    

    替换以下值:

    • PATH_TO_PRIVATE_KEY 替换为与您添加到虚拟机的公钥对应的 SSH 私钥文件的路径。
    • USERNAME,并使用您在创建 SSH 密钥时指定的用户名。例如 cloudysanfrancisco_example_comcloudysanfrancisco
    • EXTERNAL_IP 替换为虚拟机的外部 ingress IP 地址

问题排查

本部分介绍了如何排查在创建访问请求后连接到虚拟机实例时可能出现的问题。

请按照以下步骤操作,找出可能存在的问题:

  1. 验证虚拟机是否正在运行。在以下命令中,将可修改的变量替换为您的值:

    kubectl get virtualmachines.virtualmachine.gdc.goog VM_NAME -n VM_NAMESPACE --kubeconfig MANAGEMENT_API_SERVER
    

    如果虚拟机未运行,您将无法连接或配置新请求。

  2. 验证虚拟机是否已运行几分钟。如果虚拟机刚刚启动,则 SSH 访问所需的必要服务可能尚未运行。它们通常会在启动后五分钟内运行。

  3. 验证您是否未超出访问请求的 TTL 值。时间达到 TTL 值后,系统会移除相应键。

  4. 如果您的 VirtualMachineAccessRequest 显示 configured 状态,请验证以下要求:

    1. 已在端口 22 上启用向虚拟机传输数据的功能。
    2. 您的机器路由到虚拟机。例如,您可以使用
      curl -vso /dev/null --connect-timeout 5 EXTERNAL_IP:22 命令来检查路由。
  5. 如果您的 VirtualMachineAccessRequest 显示 failed 状态,请查看完整状态并查看错误消息,了解导致请求失败的原因:

    kubectl describe virtualmachineaccessrequest.virtualmachine.gdc.goog AR_NAME -n VM_NAMESPACE --kubeconfig MANAGEMENT_API_SERVER
    

    将上述命令中的可编辑变量替换为您自己的值。

  6. 如果 VirtualMachineAccessRequest 的状态为空,则访客环境可能未在运行。

连接到 Windows 虚拟机

连接到 Windows 虚拟机需要通过远程桌面应用使用远程桌面协议 (RDP)。如需通过 RDP 访问虚拟机,您需要一个密码,该密码可从 GDC 控制台或虚拟机管理器 API 的 VirtualMachinePasswordResetRequest 自定义资源中检索。

在继续之前,您必须先安装远程桌面客户端。请点击以下链接,根据您的具体操作系统完成相应步骤。您需要连接到互联网才能访问该链接。

https://remmina.org/how-to-install-remmina/

如需建立 Windows 虚拟机连接,请完成以下步骤:

控制台

  1. 在导航菜单中,依次点击虚拟机 > 实例
  2. 在虚拟机列表中,搜索要连接的正在运行的 Windows 虚拟机。
  3. 操作列中,点击重置密码。系统会显示设置新的 Windows 密码 对话框。
  4. 用户名字段中,输入您的用户名。
  5. 点击设置。系统会显示新 Windows 密码对话框,其中包含随机生成的密码。此密码包含字母数字字符和非字母数字字符。
  6. 点击 复制
  7. 前往远程桌面客户端,然后选择您的用户名。
  8. 密码输入字段中,输入您的密码。
  9. ENTERRETURN

API

  1. 生成 RSA 密钥。您需要此密钥才能从 VirtualMachinePasswordResetRequest 资源中检索密码。

    openssl genrsa -out private-key.pem 2048
    # Get the RSA public key
    openssl rsa -in private-key.pem -outform PEM -pubout
    
  2. 创建 YAML 文件。

  3. 上传您生成的 RSA 密钥、虚拟机名称以及您为访问远程桌面客户端提供的用户名:

    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachinePasswordResetRequest
    metadata:
      namespace: VM_NAMESPACE
      name: PRR_NAME
    spec:
      vmName: VM_NAME
      user: USERNAME
      publicKey: PUBLIC_KEY
    

    使用以下定义替换变量:

    变量 定义
    VM_NAMESPACE 虚拟机所在的命名空间的名称。
    PRR_NAME 您为密码重设请求指定的名称。例如 vmprr2
    VM_NAME 虚拟机的名称。例如 vm-test
    USERNAME 您使用远程桌面客户端登录虚拟机时所用的用户名。例如 test-user
    PUBLIC_KEY 您在第 2 步中生成的 RSA 密钥。您必须以多行格式设置 PUBLIC_KEY

    以下示例展示了一个 YAML 文件,其中包含执行密码重置请求所需的值和格式:

    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachinePasswordResetRequest
    metadata:
      namespace: test-namespace
      name: vmprr2
    spec:
      vmName: vm2
      user: test-user
      publicKey: |-
       -----BEGIN PUBLIC KEY-----
    
       # Input the RSA key data in multi-line format.
    
       -----END PUBLIC KEY-----
    
  4. 应用文件中的内容:

    kubectl --kubeconfig=MANAGEMENT_API_SERVER apply -f FILENAME
    

    FILENAME 替换为密码重置请求所用文件的名称。

  5. 查看 VirtualMachinePasswordResetRequest 资源的状态。 如果虚拟机处于 Running 状态,则资源会在一分钟或更短的时间内生成密码。

    kubectl --kubeconfig=MANAGEMENT_API_SERVER describe \
      -n VM_NAMESPACE PRR_NAME
    

    找到包含生成的密码的 status.encryptedPassword 字段。

  6. 复制 status.encryptedPassword 中的值并解密生成的密码:

    echo ENCRYPTED_PASSWORD | base64 -d > PASSWORD_FILENAME
    openssl pkeyutl -decrypt -in PASSWORD_FILENAME -inkey private-key.pem \
      -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1
    

    替换以下内容:

    • ENCRYPTED_PASSWORDstatus.encryptedPassword 字段中生成的密码。
    • PASSWORD_FILENAME:用于存储 base64 解码密码的临时文件。

    之后,您会看到解密后的密码作为输出,以便通过 RDP 连接到虚拟机。

  7. 打开远程桌面客户端,然后点击远程连接配置文件。 您会看到一个连接对话框。

  8. 基本标签页中,为以下字段输入值:

    • 服务器:虚拟机外部访问状态的入站 IP 地址,并附加了虚拟机外部访问端口号。如需获取 Ingress IP 地址,请参阅 Ingress
    • 用户名:您在密码重置请求中指定的用户名。 例如 test-user
    • 密码:您从重设密码请求的状态解密出的生成的密码。
  9. 点击保存并连接