教程:使用 VM Runtime on GDC 在集群中部署现有虚拟机

借助 VM Runtime on GDC,您可以将虚拟机 (VM) 工作负载直接部署到 Distributed Cloud 软件(仅限裸机)安装中。在本教程中,您会将一个代表零售销售终端的示例销售终端应用从 Compute Engine 虚拟机迁移到裸机集群,并访问其 Web 前端。

部署使用预先准备的磁盘映像,其中工作负载以 systemd 服务的形式运行。您还可以按照以下步骤准备和部署自己的基于虚拟机的应用。

目标

准备工作

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

  • 按照使用手动负载均衡器进行安装指南创建的 1.12.0 版或更高版本的裸金属集群的访问权限。本文档会设置网络资源,以便您可以通过浏览器访问虚拟机内运行的工作负载。如果您不需要该行为,则可以按照本文档使用 Distributed Cloud 软件(仅适用于裸金属)的任何安装部分。
  • 满足以下要求的工作站:
    • 有权使用 bmctl CLI 访问集群。
    • 有权使用 kubectl CLI 访问集群。

启用 VM Runtime on GDC 并安装 virtctl 插件

自 1.10 版起,VM Runtime on GDC 自定义资源定义是所有裸金属集群的一部分。安装后,便已创建 VMRuntime 自定义资源的实例。不过,Anthos VM Runtime 默认处于停用状态。

  1. 启用 VM Runtime on GDC:

    sudo bmctl enable vmruntime --kubeconfig KUBECONFIG_PATH
    
    • KUBECONFIG_PATH:用户集群 kubeconfig 文件的路径。
  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.
    ...
    

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

将虚拟机部署到 Distributed Cloud 裸机纯软件安装中时,VM Runtime on GDC 需要虚拟机映像。此映像用作已部署虚拟机的启动磁盘。

如需将现有虚拟机迁移到集群中,必须先创建该虚拟机的磁盘映像。然后,该映像必须托管在集群可以访问的仓库中。最后,该映像的网址可用于创建虚拟机。 VM Runtime on GDC 要求映像采用 qcow2 格式。如果您提供其他映像类型,则会自动转换为 qcow2 格式。为避免重复转换并启用重复使用功能,您可以转换虚拟磁盘映像并托管 qcow2 映像。

在以下步骤中,您将使用预先准备的 qcow2 映像,其中示例 工作负载 在 Google Cloud 中创建为虚拟机磁盘映像 ,并 导出到 Cloud Storage 存储桶。

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

  1. 部署 MySQL StatefulSet。销售终端应用需要连接到 MySQL 数据库来存储商品目录和付款信息。销售终端代码库包含一个示例清单,用于部署 MySQL StatefulSet,配置关联的 ConfigMap 和 Kubernetes Service。ConfigMap 定义 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 文件。您可以检查该文件,以查看 VirtualMachine 和 VirtualMachineDisk 的定义。您可以使用 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 资源由 VM Runtime on GDC 中的 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 创建后,以下示例输出会显示 PHASE 为 Succeeded:

    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:
    

    使用以下用户账号和密码。此账号是在用于创建 VM Runtime on GDC VirtualMachine 映像的原始虚拟机中设置的。

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

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

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

如果您已按照使用手动负载均衡器进行安装指南设置集群,则该集群有已创建的 Ingress 资源(名为 pos-ingress)。此资源会将来自 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 服务器 Service 的 pos-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 GDC 成功将基于虚拟机的工作负载部署到集群中。

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

清理

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

全部删除

  • 删除 VM Runtime on GDC 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 命令在集群中创建虚拟机时,系统会创建以虚拟机 (google-virtctl/pos-vm.yaml) 命名的 YAML 文件。您可以检查该文件,以查看 VirtualMachine 和 VirtualMachineDisk 的定义。您可以使用 KRM 定义部署虚拟机,而不是使用 virtctl 插件,如已创建的 YAML 文件中所示。