Back y Arquitectura

Conociendo KubeVirt

KubeVirt es una extensión de Kubernetes que permite ejecutar y gestionar máquinas virtuales (VM) junto con contenedores en un clúster de Kubernetes. Su objetivo es proporcionar una plataforma unificada para la administración de cargas de trabajo tanto de contenedores como de máquinas virtuales, integrando las capacidades de virtualización con las de contenedores.

KubeVirt permite gestionar, por tanto, gestionar las máquinas virtuales de manera similar a los pods de Kubernetes, ofreciendo características como escalabilidad, orquestación y administración centralizada.

Características

Las características principales de KubeVirt son:

  1. Orquestación de máquinas virtuales en Kubernetes: permite ejecutar y gestionar máquinas virtuales (VM) como si fueran contenedores en un clúster de Kubernetes, aprovechando la infraestructura de orquestación de Kubernetes para la administración de VM.
  2. Compatibilidad con KVM (Kernel-based Virtual Machine): KubeVirt utiliza KVM para la virtualización, lo que permite ejecutar VM en nodos que tienen soporte para KVM.
  3. Integración con el ecosistema de Kubernetes: al estar basado en Kubernetes, KubeVirt se integra con otras herramientas de Kubernetes, como Helm, Prometheus, y otras soluciones de monitoreo y gestión de redes.
  4. Escalabilidad y alta disponibilidad: KubeVirt permite escalar las máquinas virtuales de manera automática, como se hace con los contenedores, y ofrece opciones para asegurar la alta disponibilidad de las VM.
  5. Gestión de infraestructura unificada: ofrece un solo plano de control para gestionar tanto aplicaciones basadas en contenedores como máquinas virtuales, facilitando la administración de ambos tipos de cargas de trabajo desde un único lugar.
  6. Compatibilidad con carga de trabajo híbrida: soporta cargas de trabajo híbridas que pueden ser contenedores y máquinas virtuales, lo que es útil en entornos de migración o cuando se tienen aplicaciones heredadas que requieren VM.
  7. Persistencia de volúmenes y almacenamiento: KubeVirt permite el uso de volúmenes persistentes para máquinas virtuales, asegurando que los datos se mantengan disponibles a través de reinicios o migraciones de las VM.
  8. Interfaz de usuario y APIs: proporciona interfaces de usuario basadas en Kubernetes (como kubectl) y APIs RESTful que permiten la gestión de las máquinas virtuales de manera programática y a través de interfaces gráficas.
  9. Gestión de redes virtuales: permite configurar redes virtuales para las máquinas virtuales, con opciones de conectividad avanzadas y soporte para redes virtuales de Kubernetes.
  10. Migración en tiempo real de máquinas virtuales: KubeVirt soporta la migración en vivo de máquinas virtuales, lo que permite moverlas entre nodos sin interrumpir su funcionamiento, similar a las migraciones de contenedores en Kubernetes.

Estas características permiten combinar lo mejor de las máquinas virtuales y los contenedores dentro de un solo ecosistema, facilitando la modernización de infraestructuras heredadas y la gestión de diferentes tipos de cargas de trabajo.

Despliegue de KubeVirt en entorno RKE2

Sin querer meternos en mucho detalle, a continuación vamos a ver cómo desplegar KubeVirt. Así, en primer lugar será necesario lanzar los siguientes comandos:

# Establecer la ultima versión de KubeVirt
export RELEASE=$(curl https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)

# Desplegar KubeVirt Operator en su ultima versión stable
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml

# Desplegar KubeVirt CR en su ultima versión stable
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml

Para que levante todo de manera correcta, será necesario poner SELinux en modo permisivo sin que bloquee ninguna acción, ya que si no, virt-handler no levantara:

# Aplicar en cada maquina
sudo setenforce 0

KubeVirt despliega los siguientes elementos:

  • Deployments:
    • virt-api: sirve para exponer el API server de KubeVirt que maneja las solicitudes relacionadas con máquinas virtuales y recursos asociados, permitiendo interactuar con la infraestructura de virtualización.
    • virt-controller: sirve para administrar el ciclo de vida de las máquinas virtuales en el clúster, como crear, iniciar, detener y gestionar las instancias de VM
    • virt-operator: sirve para gestionar la instalación, configuración y actualización de KubeVirt en el clúster, actuando como el operador principal que coordina el despliegue de los recursos de KubeVirt.
  • DaemonSets:
    • virt-handler: se ejecuta en cada nodo del clúster y es responsable de interactuar directamente con los hipervisores (como KVM) para gestionar las máquinas virtuales en ese nodo.

Creación de una maquina virtual con KubeVirt

Vamos a poder crear una maquina virtual con KubeVirt a través del siguiente YAML:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: fedora-vm
  namespace: default
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/vm: fedora-vm
    spec:
      domain:
        devices:
          disks:
            - disk:
                bus: virtio
              name: mydisk
        resources:
          requests:
            memory: 2Gi   # 2 GB de RAM
            cpu: 1        # 1 núcleo de CPU
      volumes:
        - name: mydisk
          containerDisk:
            image: quay.io/kubevirt/fedora-cloud-registry-disk-demo:latest  # Imagen base de Fedora Cloud
        - name: cloudinit
          cloudInitNoCloud:
            userData: |
              #cloud-config
              users:
                - name: fedora # Nombre del usuario
                  sudo: ALL=(ALL) NOPASSWD:ALL
                  shell: /bin/bash
                  plain_text_passwd: fedora # Contraseña del usuario
                  lock_passwd: false
              chpasswd:
                expire: false

Una vez creado el YAML, vamos a ejecutarlo mediante el siguiente comando:

kubectl apply -f fedora-vm.yaml

Por defecto, la máquina virtual creada tendrá 2 GB de RAM y 1 núcleo de CPU. Para acceder a ella, se hará a través de fedora mediante el siguiente comando:

kubectl get pod -l kubevirt.io/vm=fedora-vm -o wide

El acceso a la maquina puede ser a través de SSH, o con el binario de virtctl.

Creación de una maquina virtual con disco adicional

Para crear una máquina con un disco adicional de 50GB, será necesario crear los siguientes YAML:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: fedora-vm
  namespace: default
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/vm: fedora-vm
    spec:
      domain:
        devices:
          disks:
            - name: mydisk
              disk:
                bus: virtio
            - name: additional-disk
              disk:
                bus: virtio
        resources:
          requests:
            memory: 2Gi   # 2 GB de RAM
            cpu: 1        # 1 núcleo de CPU
      volumes:
        - name: mydisk
          containerDisk:
            image: quay.io/kubevirt/fedora-cloud-registry-disk-demo:latest  # Imagen base de Fedora Cloud
        - name: additional-disk
          persistentVolumeClaim:
            claimName: pvc-fedora-vm  # El PVC que creamos anteriormente
        - name: cloudinit
          cloudInitNoCloud:
            userData: |
              #cloud-config
              users:
                - name: fedora
                  sudo: ALL=(ALL) NOPASSWD:ALL
                  shell: /bin/bash
                  plain_text_passwd: fedora
                  lock_passwd: false
              chpasswd:
                expire: false

Además, será necesario la creación de un PV:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: kubevirt-disk-pv
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 50Gi
  hostPath:
    path: /datadrive/onesaitplatform/kubevirt/disk1
  storageClassName: 'local-storage'

Y la creación de un PVC asociado a ese PV:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: kubevirt-disk-pvc
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
  volumeMode: Filesystem
  volumeName: kubevirt-disk-pv

Para poder crearla, aplicaremos el YAML creado con el siguiente comando:

kubectl apply -f disk-pv.yaml
kubectl apply -f disk-pvc.yaml
kubectl apply -f fedora-vm.yaml

Una vez accedamos a nuestra maquina recién creada, podremos ver como el disco de 50GB que acabamos de crear aparece pero sin formato y sin montar:

Acceso a la máquina mediante SSH

Se puede acceder a la maquina mediante uno de los nodos que componen el clúster. Para ello, necesitamos saber la IP que se le ha asignado a la máquina virtual:

kubectl get pod -l kubevirt.io/vm=fedora-vm -o wide

Dentro del worker, por ejemplo, accedemos mediante:

ssh fedora@<ipMaquina>

Comprobamos cómo la maquina tiene 1 VCPU y 1 GB de RAM.

Acceso a la máquina mediante virtctl

Para instalar virtctl, será necesario lanzar los siguientes comandos:

# Descargar el binario de virtctl:
curl -LO https://github.com/kubevirt/kubevirt/releases/download/v0.56.0/virtctl-linux-amd64

# Dar permisos al binario de virtctl:
chmod +x virtctl-linux-amd64

# Mover el binario a la ubicacion correcta:
sudo mv virtctl-linux-amd64 /usr/local/bin/virtctl

Para poder acceder a la máquina, se tendrá que ejecutar el siguiente comando:

virtctl console fedora-vm

¿Cómo acceder desde fuera a la maquina?

Sera necesario crear un servicio tipo NodePort o en clouds del tipo de Azure, Amazon o Google. Se podría crear un servicio tipo balanceador que redirija las peticiones a esa maquina.

En el siguiente ejemplo se vera como acceder vía un servicio tipo NodePort. Para ello, deberemos aplicar el siguiente YAML:

apiVersion: v1
kind: Service
metadata:
  name: fedora-vm-nodeport
  namespace: default
spec:
  selector:
    kubevirt.io/vm: fedora-vm  # Nombre de la máquina virtual
  ports:
    - protocol: TCP
      port: 22        # Puerto al que accederás (en este caso SSH)
      targetPort: 22   # Puerto dentro de la VM
      nodePort: 30022  # Puerto que se expondrá en los nodos
  type: NodePort

Aplicamos mediante el siguiente comando:

kubectl apply -f service-nodeport.yaml

Una vez creado, ya podríamos acceder a la maquina desde cualquier sitio con acceso a internet a través de la IP de máquina del nodo worker y el puerto NodePort que se haya expuesto:

ssh fedora@<ipWorker> -p 30022

Otros comandos de interés

Para ir terminando, os dejamos otros comandos que consideramos interesante conocer:

Parar la máquina

virtctl pause vm fedora-vm

Encencer la máquina

virtctl unpause vm fedora-vm

Borrar la maquina

kubectl delete vm fedora-vm

Imagen de cabecera: KubeVirt + Onesait Platform

✍🏻 Author(s)

Deja una respuesta