教程:使用 Google Distributed Cloud 上的 VM Runtime 在 GKE Enterprise 集群中部署现有虚拟机


本文档提供了使用 VM Runtime on Google Distributed Cloud 将基于虚拟机 (VM) 的工作负载部署到 GKE on Bare Metal 的分步指南。该指南中使用的工作负载是示例销售终端应用。此应用代表在零售店的本地硬件上运行的典型销售终端

在本文档中,您将此应用从虚拟机迁移到 GKE on Bare Metal 集群,并访问应用的 Web 前端。如需将现有虚拟机迁移到集群中,必须先创建该虚拟机的磁盘映像。然后,该映像必须托管在集群可以访问的代码库中。最后,该映像的网址可用于创建虚拟机。Google Distributed Cloud 上的 VM Runtime 要求映像采用 qcow2 格式。如果您提供其他映像类型,则会自动转换为 qcow2 格式。为避免重复转换并启用重复使用功能,您可以转换虚拟磁盘映像并托管 qcow2 映像。

本文档使用预先准备的 Compute Engine 虚拟机实例映像,其中工作负载以 systemd 服务的形式运行。您可以按照相同的步骤部署自己的应用。

目标

准备工作

如需完成本文档,您需要以下资源:

  • 对按照使用手动负载平衡器在 Compute Engine 虚拟机上运行 GKE on Bare Metal 指南创建的 GKE on Bare Metal 1.12.0 版或更高版本集群的访问权限。本文档会设置网络资源,以便您可以通过浏览器访问虚拟机内运行的工作负载。如果您不需要该行为,则可以使用任何 GKE on Bare Metal 按照本文档中的说明进行操作。
  • 满足以下要求的工作站:
    • 有权使用 bmctl CLI 访问集群。
    • 有权使用 kubectl CLI 访问集群。

在 Google Distributed Cloud 上启用 VM Runtime,并安装 virtctl 插件

自 1.10 版起,Google Distributed Cloud 自定义资源定义 (CRD) 是所有 GKE on Bare Metal 集群的一部分。安装后,便已创建 VMRuntime 自定义资源的实例。不过,Anthos VM Runtime 默认处于停用状态。

  1. 在 Google Distributed Cloud 上启用 VM Runtime:

    sudo bmctl enable vmruntime --kubeconfig KUBECONFIG_PATH
    
    • KUBECONFIG_PATH:GKE Enterprise 用户集群的 Kubernetes 配置文件的路径
  2. 验证 VMRuntime 是否已启用:

    kubectl wait --for=jsonpath='{.status.ready}'=true vmruntime vmruntime
    

    VMRuntime 可能需要几分钟才能准备就绪。如果其尚未准备就绪,请检查几次并缩短延迟时间。以下示例输出显示 VMRuntime 已准备就绪:

    vmruntime.vm.cluster.gke.io/vmruntime condition met
    
  3. kubectl 安装 virtctl 插件:

    sudo -E bmctl install virtctl
    

    以下示例输出显示 virtctl 插件安装过程已完成:

    Please check the logs at bmctl-workspace/log/install-virtctl-20220831-182135/install-virtctl.log
    [2022-08-31 18:21:35+0000] Install virtctl succeeded
    
  4. 验证 virtctl 插件的安装:

    kubectl virt
    

    以下示例输出显示 virtctl 插件可用于 kubectl

    Available Commands:
      addvolume         add a volume to a running VM
      completion        generate the autocompletion script for the specified shell
      config            Config subcommands.
      console           Connect to a console of a virtual machine instance.
      create            Create subcommands.
      delete            Delete  subcommands.
    ...
    

部署基于虚拟机的工作负载

当您将虚拟机部署到 GKE on Bare Metal 时,Google Distributed Cloud 上的 VM Runtime 需要虚拟机映像。此映像用作已部署虚拟机的启动磁盘。

在本教程中,您需要将基于 Compute Engine 虚拟机的工作负载迁移到 GKE on Bare Metal 集群。此 Compute Engine 虚拟机已创建,并且示例销售终端 (PoS) 应用已配置为作为 systemd 服务运行。Google Cloud 中已创建此虚拟机的磁盘映像以及 PoS 应用工作负载。然后该映像已作为 qcow2 映像导出到 Cloud Storage 存储桶。您可以在以下步骤中使用此预先准备的 qcow2 映像。

本文档中的源代码可在 anthos-samples GitHub 代码库中获取。您可以使用此代码库中的资源来完成后续步骤。

  1. 部署 MySQL StatefulSet。销售终端应用需要连接到 MySQL 数据库来存储商品目录和付款信息。销售终端代码库包含一个示例清单,用于部署 MySQL StatefulSet,配置关联的 ConfigMap 和 Kubernetes ServiceConfigMap 定义 MySQL 实例的凭据,这些凭据是传递到销售终端应用的凭据

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/point-of-sale/main/k8-manifests/common/mysql-db.yaml
    
  2. 使用预先准备的 qcow2 映像部署虚拟机工作负载:

    kubectl virt create vm pos-vm \
        --boot-disk-size=80Gi \
        --memory=4Gi \
        --vcpu=2 \
        --image=https://storage.googleapis.com/pos-vm-images/pos-vm.qcow2
    

    此命令会创建以虚拟机 (google-virtctl/pos-vm.yaml) 命名的 YAML 文件。您可以检查该文件,以查看 VirtualMachineVirtualMachineDisk 的定义。您可以使用 Kubernetes 资源模型 (KRM) 定义部署虚拟机工作负载,而不是使用 virtctl 插件,如已创建的 YAML 文件中所示。

    此命令成功运行后,会生成如下例所示的输出,其中说明了已创建的不同资源:

    Constructing manifest for vm "pos-vm":
    Manifest for vm "pos-vm" is saved to /home/tfadmin/google-virtctl/pos-vm.yaml
    Applying manifest for vm "pos-vm"
    Created gvm "pos-vm"
    
  3. 检查虚拟机创建状态。

    VirtualMachine 资源由 Google Distributed Cloud 上的 VM Runtime 中的 vm.cluster.gke.io/v1.VirtualMachine 资源标识。简写形式为 gvm

    创建虚拟机时,系统会创建以下两个资源:

    • VirtualMachineDisk 是在其中导入虚拟机映像内容的永久性磁盘。
    • VirtualMachine 是虚拟机实例本身。DataVolume 会在虚拟机启动之前装载到 VirtualMachine 中。

    检查 VirtualMachineDisk 的状态。VirtualMachineDisk 会在内部创建 DataVolume 资源。虚拟机映像会导入装载到虚拟机中的 DataVolume:

    kubectl get datavolume
    

    以下示例输出显示映像导入的开始:

    NAME              PHASE             PROGRESS   RESTARTS   AGE
    pos-vm-boot-dv    ImportScheduled   N/A                   8s
    
  4. 检查 VirtualMachine 的状态。VirtualMachine 处于 Provisioning 状态,直到 DataVolume 完全导入为止:

    kubectl get gvm
    

    以下示例输出显示正在预配 VirtualMachine

    NAME      STATUS         AGE     IP
    pos-vm    Provisioning   1m
    
  5. 等待虚拟机映像完全导入到 DataVolume。在映像导入期间,继续查看进度:

    kubectl get datavolume -w
    

    以下示例输出显示正在导入磁盘映像:

    NAME              PHASE              PROGRESS   RESTARTS   AGE
    pos-vm-boot-dv   ImportInProgress   0.00%                 14s
    ...
    ...
    pos-vm-boot-dv   ImportInProgress   0.00%                 31s
    pos-vm-boot-dv   ImportInProgress   1.02%                 33s
    pos-vm-boot-dv   ImportInProgress   1.02%                 35s
    ...
    

    导入完成且 DataVolume 创建后,以下示例输出会显示 PHASESucceeded

    kubectl get datavolume
    
    NAME              PHASE             PROGRESS   RESTARTS   AGE
    pos-vm-boot-dv    Succeeded         100.0%                14m18s
    
  6. 确认 VirtualMachine 已成功创建:

    kubectl get gvm
    

    如果创建成功,则 STATUS 会显示 RUNNING(如以下示例所示),虚拟机的 IP 地址也会显示:

    NAME      STATUS    AGE     IP
    pos-vm    Running   40m     192.168.3.250
    

连接到虚拟机并检查应用状态

用于虚拟机的映像包含销售终端示例应用。该应用配置为在启动时作为 systemd 服务自动启动。您可以在 pos-systemd-services 目录中查看 systemd 服务的配置文件。

  1. 连接到虚拟机控制台。运行以下命令,并在看到 Successfully connected to pos-vm… 消息后按 Enter⏎ 键:

    kubectl virt console pos-vm
    

    此命令会生成以下示例输出,提示您输入登录详细信息:

    Successfully connected to pos-vm console. The escape sequence is ^]
    
    pos-from-public-image login:
    

    使用以下用户账号和密码。此帐号是在原始虚拟机中创建的,即 Google Distributed Cloud VirtualMachine 上的虚拟机运行时的映像。

    • 登录用户名:abmuser
    • 密码:abmworks
  2. 检查销售终端应用服务的状态。销售终端应用包括三项服务:API、商品目录和付款。这些服务都作为系统服务运行。

    这三项服务都通过 localhost 相互连接。但是,应用使用在先前步骤中创建的 mysql-db Kubernetes Service 连接到 MySQL 数据库。此行为意味着虚拟机会自动连接到与 PodsServices 相同的网络,从而实现虚拟机工作负载与其他容器化应用之间的无缝通信。您无需执行任何额外操作即可从使用 Anthos VM Runtime 部署的虚拟机访问 Kubernetes Services

    sudo systemctl status pos*
    

    以下示例输出显示这三项服务和根系统服务 pos.service 的状态:

    ● pos_payments.service - Payments service of the Point of Sale Application
        Loaded: loaded (/etc/systemd/system/pos_payments.service; enabled; vendor >
        Active: active (running) since Tue 2022-06-21 18:55:30 UTC; 1h 10min ago
      Main PID: 750 (payments.sh)
          Tasks: 27 (limit: 4664)
        Memory: 295.1M
        CGroup: /system.slice/pos_payments.service
                ├─750 /bin/sh /pos/scripts/payments.sh
                └─760 java -jar /pos/jars/payments.jar --server.port=8083
    
    ● pos_inventory.service - Inventory service of the Point of Sale Application
        Loaded: loaded (/etc/systemd/system/pos_inventory.service; enabled; vendor>
        Active: active (running) since Tue 2022-06-21 18:55:30 UTC; 1h 10min ago
      Main PID: 749 (inventory.sh)
          Tasks: 27 (limit: 4664)
        Memory: 272.6M
        CGroup: /system.slice/pos_inventory.service
                ├─749 /bin/sh /pos/scripts/inventory.sh
                └─759 java -jar /pos/jars/inventory.jar --server.port=8082
    
    ● pos.service - Point of Sale Application
        Loaded: loaded (/etc/systemd/system/pos.service; enabled; vendor preset: e>
        Active: active (exited) since Tue 2022-06-21 18:55:30 UTC; 1h 10min ago
      Main PID: 743 (code=exited, status=0/SUCCESS)
          Tasks: 0 (limit: 4664)
        Memory: 0B
        CGroup: /system.slice/pos.service
    
    Jun 21 18:55:30 pos-vm systemd[1]: Starting Point of Sale Application...
    Jun 21 18:55:30 pos-vm systemd[1]: Finished Point of Sale Application.
    
    ● pos_apiserver.service - API Server of the Point of Sale Application
        Loaded: loaded (/etc/systemd/system/pos_apiserver.service; enabled; vendor>
        Active: active (running) since Tue 2022-06-21 18:55:31 UTC; 1h 10min ago
      Main PID: 751 (api-server.sh)
          Tasks: 26 (limit: 4664)
        Memory: 203.1M
        CGroup: /system.slice/pos_apiserver.service
                ├─751 /bin/sh /pos/scripts/api-server.sh
                └─755 java -jar /pos/jars/api-server.jar --server.port=8081
    
  3. 退出虚拟机。如需退出控制台连接,请按 Ctrl + ] 使用转义序列 ^]

访问基于虚拟机的工作负载

如果您的集群是按照在具有手动负载平衡器的 Compute Engine 虚拟机上运行 GKE on Bare Metal 指南中设置的,则已经创建了一个名为 pos-ingressIngress 资源。此资源会将来自 Ingress 负载均衡器公共 IP 地址的流量路由到销售终端示例应用的 API 服务器服务。

  1. 如果集群没有此 Ingress 资源,请通过应用以下清单来创建该资源:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-samples/main/anthos-bm-gcp-terraform/resources/manifests/pos-ingress.yaml
    
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: pos-ingress
    spec:
      rules:
      - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-server-svc
                port:
                  number: 8080
  2. 创建一个 Kubernetes Service 以将流量路由到虚拟机。Ingress 资源会将流量路由到此 Service

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-samples/main/anthos-vmruntime/pos-service.yaml
    

    以下示例输出会确认 Service 的创建:

    service/api-server-svc created
    
    apiVersion: v1
    kind: Service
    metadata:
      name: api-server-svc
    spec:
      selector:
        kubevirt/vm: pos-vm
      ports:
      - protocol: TCP
        port: 8080
        targetPort: 8081
  3. 获取 Ingress 负载均衡器的公共 IP 地址。Ingress Loadbalancer 会根据 Ingress 资源规则路由流量。您已拥有将请求转发到 API 服务器 Servicepos-ingress 规则。此 Service 会将请求转发到虚拟机:

    INGRESS_IP=$(kubectl get ingress/pos-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo $INGRESS_IP
    

    以下示例输出显示 Ingress 负载均衡器的 IP 地址:

    172.29.249.159 # you might have a different IP address
    
  4. 在浏览器中使用 Ingress Loadbalancer IP 地址来访问应用。以下示例屏幕截图显示了包含两件商品的简单销售终端 kiosk。如果想要订购多件商品,可以多次点击这些商品,然后使用付款按钮订购。此体验表明,您已成功使用 VM Runtime on Google Distributed Cloud 将基于虚拟机的传统工作负载部署到 Anthos 集群中。

销售终端应用界面
销售终端应用界面(点击图片可放大)

清理

您可以删除本教程中创建的所有资源,也可以仅删除虚拟机并保留可重复使用的资源。在 GKE on Bare Metal 中删除虚拟机详细介绍了可用的选项。

全部删除

  • 删除 Google Distributed Cloud 上的虚拟机运行时 VirtualMachine 以及所有资源:

    kubectl virt delete vm pos-vm --all
    

    以下示例输出会确认删除:

    vm "pos-vm" used the following resources:
        gvm: pos-vm
        VirtualMachineDisk: pos-vm-boot-dv
    Start deleting the resources:
        Deleted gvm "pos-vm".
        Deleted VirtualMachineDisk "pos-vm-boot-dv".
    

仅删除虚拟机

  • 仅删除虚拟机会保留创建的 VirtualMachineDisk。这样可以重复使用虚拟机映像,并节省在创建新虚拟机时导入映像所花费的时间。

    kubectl virt delete vm pos-vm
    

    以下示例输出会确认删除:

    vm "pos-vm" used the following resources:
        gvm: pos-vm
        VirtualMachineDisk: pos-vm-boot-dv
    Start deleting the resources:
        Deleted gvm "pos-vm".
    

后续步骤

  • 本指南中使用的原始虚拟机是运行 Ubuntu 20.04 LTS 的 Compute Engine 实例。此虚拟机的映像可通过 pos-vm-images Cloud Storage 存储桶公开访问。如需详细了解如何配置虚拟机及其映像的创建方式,请参阅销售终端代码库中的说明。
  • 使用 kubectl virt create vm pos-vm 命令在 Anthos 集群中创建虚拟机时,系统会创建以虚拟机 (google-virtctl/pos-vm.yaml) 命名的 YAML 文件。您可以检查该文件,以查看 VirtualMachineVirtualMachineDisk 的定义。您可以使用 KRM 定义部署虚拟机,而不是使用 virtctl 插件,如已创建的 YAML 文件中所示。