Tutorial: Desplegar una VM en un clúster con el entorno de ejecución de máquinas virtuales en GDC


En este documento se proporciona una guía detallada para desplegar una carga de trabajo basada en máquinas virtuales en una instalación de Google Distributed Cloud (solo software) en hardware desnudo mediante VM Runtime en GDC. La carga de trabajo que se usa en esta guía es la aplicación de punto de venta de ejemplo. Esta aplicación representa una terminal de punto de venta típica que se ejecuta en hardware local en una tienda.

En este documento, migrarás esta aplicación de una máquina virtual a un clúster y accederás al frontend web de la aplicación. Para migrar una VM a un clúster, primero se debe crear una imagen de disco de esa VM. A continuación, la imagen debe estar alojada en un repositorio al que pueda acceder el clúster. Por último, la URL de esa imagen se puede usar para crear la VM. El tiempo de ejecución de máquinas virtuales en GDC espera que las imágenes tengan el formato qcow2. Si proporciona un tipo de imagen diferente, se convertirá automáticamente al formato qcow2. Para evitar conversiones repetitivas y permitir la reutilización, puedes convertir una imagen de disco virtual y alojar la imagen qcow2.

En este documento se usa una imagen preparada de una instancia de máquina virtual de Compute Engine en la que la carga de trabajo se ejecuta como un servicio systemd. Puedes seguir los mismos pasos para implementar tu propia aplicación.

Objetivos

Antes de empezar

Para completar este documento, necesitas los siguientes recursos:

  • Acceso a un clúster de bare metal con la versión 1.12.0 o posterior que se haya creado siguiendo la guía Instalar con balanceador de carga manual. En este documento se configuran los recursos de red para que puedas acceder a la carga de trabajo que se ejecuta en la VM a través de un navegador. Si no necesitas ese comportamiento, puedes seguir este documento con cualquier instalación de Google Distributed Cloud en Bare Metal.
  • Una estación de trabajo que cumpla los siguientes requisitos:
    • Tiene acceso a tu clúster mediante la CLI bmctl.
    • Tiene acceso a tu clúster mediante la CLI de kubectl.

Habilitar el tiempo de ejecución de máquinas virtuales en GDC e instalar el complemento virtctl

La definición de recursos personalizados de VM Runtime en GDC forma parte de todos los clústeres Bare Metal desde la versión 1.10. Una instancia del recurso personalizado VMRuntime ya se crea durante la instalación. Sin embargo, está inhabilitada de forma predeterminada.

  1. Habilita el tiempo de ejecución de máquinas virtuales en GDC:

    sudo bmctl enable vmruntime --kubeconfig KUBECONFIG_PATH
    
    • KUBECONFIG_PATH: ruta del archivo kubeconfig del clúster de usuario.
  2. Valida que VMRuntime esté habilitado:

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

    La VMRuntime puede tardar unos minutos en estar lista. Si no está listo, comprueba el estado varias veces con intervalos cortos. En el siguiente ejemplo de salida se muestra que VMRuntime está listo:

    vmruntime.vm.cluster.gke.io/vmruntime condition met
    
  3. Instala el complemento virtctl para kubectl:

    sudo -E bmctl install virtctl
    

    En el siguiente ejemplo de salida se muestra que el proceso de instalación del complemento virtctl se ha completado:

    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. Verifica la instalación del complemento virtctl:

    kubectl virt
    

    En el siguiente ejemplo de resultado se muestra que el complemento virtctl está disponible para usarlo con 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.
    ...
    

Desplegar la carga de trabajo basada en máquinas virtuales

Cuando despliegas una VM en una instalación de Google Distributed Cloud (solo software) en Bare Metal, VM Runtime en GDC espera una imagen de VM. Esta imagen sirve como disco de arranque de la máquina virtual implementada.

En este tutorial, migrarás una carga de trabajo basada en una VM de Compute Engine a un clúster. Se ha creado esta VM de Compute Engine y se ha configurado la aplicación de punto de venta (PdV) de ejemplo para que se ejecute como un servicio de systemd. Se creó una imagen de disco de esta VM junto con la carga de trabajo de la aplicación PoS en Google Cloud. A continuación, la imagen se exportó a un segmento de Cloud Storage como una imagen qcow2. Usarás esta imagen qcow2 preparada en los pasos siguientes.

El código fuente de este documento está disponible en el repositorio anthos-samples de GitHub. Usarás los recursos de este repositorio para completar los pasos que se indican a continuación.

  1. Despliega un MySQL StatefulSet. La aplicación de punto de venta espera conectarse a una base de datos MySQL para almacenar información de inventario y de pago. El repositorio de punto de venta tiene un manifiesto de ejemplo que despliega un StatefulSet de MySQL, configura un ConfigMap asociado y un Service de Kubernetes. El ConfigMap define las credenciales de la instancia de MySQL, que son las mismas credenciales que se transfieren a la aplicación del punto de venta.

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/point-of-sale/main/k8-manifests/common/mysql-db.yaml
    
  2. Despliega la carga de trabajo de la VM con la imagen qcow2 preparada previamente:

    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
    

    Este comando crea un archivo YAML con el nombre de la VM (google-virtctl/pos-vm.yaml). Puedes inspeccionar el archivo para ver la definición de VirtualMachine y VirtualMachineDisk. En lugar de usar el complemento virtctl, podrías haber desplegado la carga de trabajo de la VM con definiciones de Kubernetes Resource Model (KRM), como se muestra en el archivo YAML creado.

    Cuando el comando se ejecuta correctamente, genera un resultado como el siguiente ejemplo, en el que se explican los diferentes recursos que se han creado:

    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. Comprueba el estado de la creación de la VM.

    El recurso VirtualMachine se identifica mediante el recurso vm.cluster.gke.io/v1.VirtualMachine en el tiempo de ejecución de máquinas virtuales de GDC. La forma abreviada es gvm.

    Cuando creas una VM, se crean los dos recursos siguientes:

    • Un VirtualMachineDisk es el disco persistente en el que se importan los contenidos de la imagen de la VM.
    • Un VirtualMachine es la instancia de VM propiamente dicha. El DataVolume se monta en la VirtualMachine antes de que se inicie la VM.

    Comprueba el estado de VirtualMachineDisk. VirtualMachineDisk crea internamente un recurso DataVolume. La imagen de VM se importa a DataVolume, que se monta en la VM:

    kubectl get datavolume
    

    En el siguiente ejemplo de salida se muestra el inicio de la importación de la imagen:

    NAME              PHASE             PROGRESS   RESTARTS   AGE
    pos-vm-boot-dv    ImportScheduled   N/A                   8s
    
  4. Comprueba el estado de la VirtualMachine. El VirtualMachine está en el estado Provisioning hasta que se importa por completo el DataVolume:

    kubectl get gvm
    

    En el siguiente ejemplo de salida se muestra cómo se aprovisiona el VirtualMachine:

    NAME      STATUS         AGE     IP
    pos-vm    Provisioning   1m
    
  5. Espera a que la imagen de VM se importe por completo en DataVolume. Para ver el progreso de la importación de la imagen, sigue estos pasos:

    kubectl get datavolume -w
    

    En el siguiente ejemplo de salida se muestra la imagen de disco que se está importando:

    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
    ...
    

    Cuando se complete la importación y se cree el DataVolume, el siguiente ejemplo de salida muestra el PHASE de Succeeded :

    kubectl get datavolume
    
    NAME              PHASE             PROGRESS   RESTARTS   AGE
    pos-vm-boot-dv    Succeeded         100.0%                14m18s
    
  6. Confirma que el VirtualMachine se ha creado correctamente:

    kubectl get gvm
    

    Si la creación se ha realizado correctamente, STATUS muestra RUNNING, como se muestra en el siguiente ejemplo, junto con la dirección IP de la VM:

    NAME      STATUS    AGE     IP
    pos-vm    Running   40m     192.168.3.250
    

Conéctate a la VM y comprueba el estado de la aplicación

La imagen usada en la VM incluye la aplicación de ejemplo de punto de venta. La aplicación está configurada para iniciarse automáticamente al arrancar como servicio de systemd. Puedes ver los archivos de configuración de los servicios de systemd en el directorio pos-systemd-services.

  1. Conéctate a la consola de la VM. Ejecuta el siguiente comando y pulsa Intro⏎ después de ver el mensaje Successfully connected to pos-vm…:

    kubectl virt console pos-vm
    

    Este comando genera el siguiente resultado de ejemplo, que te pide que introduzcas los detalles de inicio de sesión:

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

    Usa la siguiente cuenta de usuario y contraseña. Esta cuenta se configuró en la máquina virtual original desde la que se creó la imagen del entorno de ejecución de máquinas virtuales en GDC VirtualMachine.

    • Nombre de usuario de inicio de sesión: abmuser
    • Contraseña: abmworks
  2. Comprueba el estado de los servicios de la aplicación de punto de venta. La aplicación de punto de venta incluye tres servicios: API, Inventario y Pagos. Todos estos servicios se ejecutan como servicios del sistema.

    Los tres servicios se conectan entre sí a través de localhost. Sin embargo, la aplicación se conecta a la base de datos MySQL mediante un servicio de Kubernetes mysql-db que se creó en el paso anterior. Este comportamiento significa que la máquina virtual se conecta automáticamente a la misma red que Pods y Services, lo que permite una comunicación fluida entre las cargas de trabajo de la máquina virtual y otras aplicaciones en contenedores. No tienes que hacer nada más para que Kubernetes Services sea accesible desde las VMs desplegadas con VM Runtime en GDC.

    sudo systemctl status pos*
    

    En el siguiente ejemplo de salida se muestra el estado de los tres servicios y del servicio del sistema raíz, 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. Salir de la máquina virtual. Para salir de la conexión de la consola, usa la secuencia de escape ^] pulsando Ctrl + ].

Acceder a la carga de trabajo basada en máquinas virtuales

Si has configurado tu clúster siguiendo la guía Instalar con balanceador de carga manual, ya se habrá creado un recurso Ingress llamado pos-ingress. Este recurso dirige el tráfico desde la dirección IP externa del balanceador de carga de Ingress al servicio del servidor de la API de la aplicación de ejemplo del punto de venta.

  1. Si tu clúster no tiene este recurso Ingress, créalo aplicando el siguiente manifiesto:

    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. Crea un Service de Kubernetes que dirija el tráfico a la VM. El recurso Ingress dirige el tráfico a este Service:

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

    El siguiente ejemplo de salida confirma la creación de un servicio:

    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. Obtén la dirección IP externa del balanceador de carga Ingress. El Ingress Loadbalancer enruta el tráfico en función de las reglas de recursos de Ingress. Ya tienes una regla pos-ingress para reenviar solicitudes al servidor de la API Service. Este Service reenvía las solicitudes a la VM:

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

    En el siguiente ejemplo de salida se muestra la dirección IP del balanceador de carga Ingress:

    172.29.249.159 # you might have a different IP address
    
  4. Accede a la aplicación mediante la dirección IP del balanceador de carga de Ingress en un navegador. En las siguientes capturas de pantalla se muestra el quiosco del punto de venta con dos artículos. Puedes hacer clic en los artículos (más de una vez si quieres pedir varios) y hacer un pedido con el botón Pagar. Esta experiencia demuestra que has desplegado correctamente una carga de trabajo basada en una VM en un clúster mediante el entorno de ejecución de VMs en GDC.

Interfaz de usuario de la aplicación de punto de venta
Interfaz de usuario de la aplicación de punto de venta (haz clic en la imagen para ampliarla)

Limpieza

Puedes eliminar todos los recursos creados en este tutorial o solo la máquina virtual y conservar los recursos reutilizables. En Eliminar una VM se explican las opciones disponibles con detalle.

Eliminar todos

  • Elimina el tiempo de ejecución de la VM en GDC VirtualMachine junto con todos los recursos:

    kubectl virt delete vm pos-vm --all
    

    El siguiente ejemplo de salida confirma la eliminación:

    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".
    

Eliminar solo la VM

  • Si solo eliminas la VM, se conservará el VirtualMachineDisk que se haya creado. De esta forma, se puede reutilizar la imagen de la VM y se ahorra tiempo al importar la imagen cuando se crea una VM.

    kubectl virt delete vm pos-vm
    

    El siguiente ejemplo de salida confirma la eliminación:

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

Siguientes pasos

  • La VM original que se usa en esta guía es una instancia de Compute Engine que ejecuta Ubuntu 20.04 LTS. Se puede acceder públicamente a la imagen de esta VM a través del segmento de Cloud Storage pos-vm-images. Para obtener más información sobre cómo se configuró la VM y se creó su imagen, consulta las instrucciones del repositorio de puntos de venta.
  • Cuando creas una VM en un clúster con el comando kubectl virt create vm pos-vm, se crea un archivo YAML con el nombre de la VM (google-virtctl/pos-vm.yaml). Puedes inspeccionar el archivo para ver la definición de VirtualMachine y VirtualMachineDisk. En lugar de usar el complemento virtctl, puedes desplegar una VM con definiciones de KRM, como se muestra en el archivo YAML creado.