Problema

Los entusiastas de los homelabs suelen enfrentarse a una decisión estructural: ¿construir la infraestructura directamente sobre Kubernetes o usar un hipervisor como Proxmox y desplegar Kubernetes (u otros servicios) dentro de máquinas virtuales? La duda no es solo de preferencia personal; impacta en la gestión de recursos, la complejidad operativa y la capacidad de soportar workloads mixtos (VMs y contenedores). En un entorno doméstico con hardware limitado (por ejemplo, varios HP EliteDesk) y una lista de servicios que incluye desde Jellyfin hasta bases de datos y VMs ocasionales, la elección determina cuántas capas de abstracción se añaden y cómo se manejan los fallos.

Causa

  1. Modelo de aislamiento diferente

    • Kubernetes está pensado para orquestar contenedores. Cada pod comparte el kernel del nodo, lo que reduce overhead pero limita la capacidad de ejecutar sistemas operativos completos.
    • Proxmox es un hipervisor basado en KVM/LXC que permite ejecutar tanto máquinas virtuales completas como contenedores ligeros, ofreciendo aislamiento a nivel de hardware.
  2. Gestión de recursos en hardware limitado
    Ejecutar Kubernetes directamente sobre el metal implica que cada nodo sea un host Linux con kubelet, kube-proxy, etc. Si el nodo también necesita ejecutar VMs, el kernel debe compartir CPU y RAM entre los contenedores y la capa de virtualización, lo que puede generar sobre‑commit inesperado.

  3. Curva de mantenimiento y backups

    • En Kubernetes, los objetos declarativos (Deployments, StatefulSets) facilitan la recuperación, pero los volúmenes persistentes requieren un provisioner externo.
    • Proxmox incluye snapshots y backups integrados para VMs y LXC, lo que simplifica la protección de sistemas que no pueden ser “stateless”.
  4. Necesidad de servicios que sólo corren como VM
    Algunas aplicaciones (por ejemplo, versiones de Windows, software con licencia que verifica el hipervisor) no pueden empaquetarse como contenedores y obligan a crear una VM.

  5. Experiencia del equipo
    Un ingeniero familiarizado con Kubernetes puede subestimar la complejidad de operar un hipervisor y viceversa. La falta de conocimientos profundos en una de las capas suele generar configuraciones frágiles.

Solución

Adoptar una arquitectura hipervisor‑first (Proxmox) y desplegar Kubernetes dentro de una o dos VMs dedicadas es la opción más flexible para la mayoría de los homelabs. Este enfoque permite:

  • Aislamiento claro: los servicios que requieren VM quedan en Proxmox, mientras que los workloads “cloud‑native” se ejecutan en Kubernetes sin interferir con la capa de virtualización.
  • Escalabilidad modular: agregar nodos Proxmox es tan sencillo como crear un nuevo host físico y unirlo al cluster; Kubernetes puede escalar añadiendo más VMs o usando Proxmox LXC como nodos ligeros.
  • Backups unificados: Proxmox gestiona snapshots de VMs y contenedores LXC, mientras que Kubernetes mantiene su propio estado declarativo. La combinación permite restaurar rápidamente tanto la VM de control plane como los pods críticos.
  • Uso eficiente de recursos: asignar CPU/RAM a cada VM permite controlar el over‑commit de forma explícita; los contenedores dentro de la VM comparten solo los recursos asignados, evitando sorpresas en el host.

Pasos prácticos

  1. Instalar Proxmox VE en cada máquina física. Configura ZFS o LVM‑thin según el espacio disponible; habilita la red de puente (vmbr0) para que las VMs tengan acceso directo a la LAN.
  2. Crear una VM “control‑plane” con al menos 2 vCPU y 4 GiB de RAM. Instala una distribución Linux ligera (Ubuntu Server, Debian) y sigue la guía oficial de kubeadm para inicializar el cluster.
  3. Añadir nodos worker como VMs o LXC. Si el hardware lo permite, usar LXC reduce overhead y mantiene la gestión dentro de Proxmox.
  4. Configurar storage: usa un datastore compartido (NFS, Ceph, o ZFS over iSCSI) para los PersistentVolumes de Kubernetes. Proxmox puede exponer el mismo datastore a los nodos worker.
  5. Desplegar servicios críticos (ArgoCD, Prometheus, Grafana) en Kubernetes. Mantén aplicaciones que requieren VM (Windows, software con licencia) directamente en Proxmox.
  6. Automatizar backups: programa snapshots de la VM de control‑plane y de los LXC críticos. Usa vzdump de Proxmox y velero dentro de Kubernetes para una cobertura completa.

Cuándo aplicar esta solución

  • Hardware heterogéneo: si tienes máquinas con diferentes capacidades (CPU, RAM) y necesitas asignar recursos de forma granular.
  • Mix de workloads: cuando la lista de servicios incluye tanto contenedores como VMs que no pueden migrarse a contenedores.
  • Necesidad de alta disponibilidad ligera: Proxmox ofrece HA a nivel de VM; Kubernetes aporta HA a nivel de aplicación. La combinación cubre ambos frentes.
  • Experiencia con Kubernetes: si ya dominas k8s, la capa extra de Proxmox no representa una carga significativa y aporta flexibilidad.

Escenarios donde NO aplicar

  • Homelab ultra‑ligero (una sola máquina con <8 GiB RAM) donde la sobrecarga de una VM para Kubernetes no justifica el beneficio.
  • Solo contenedores: si todos los servicios pueden empaquetarse como containers y no se necesita aislamiento de hardware, instalar Kubernetes directamente sobre el host simplifica la arquitectura.
  • Entorno de pruebas temporales: para pruebas rápidas, usar kind o k3s en el host puede ser más rápido que montar Proxmox.

Código

# Proxmox: crear datastore ZFS (ejemplo)
zpool create rpool /dev/sdb
zfs create -o mountpoint=none rpool/data
pvesm add zfspool data --pool rpool/data

# Proxmox: crear VM para control plane (ID 101)
qm create 101 --name k8s-master --memory 4096 --cores 2 --net0 virtio,bridge=vmbr0
qm importdisk 101 /path/to/ubuntu.qcow2 local-lvm
qm set 101 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-101-disk-0
qm set 101 --boot c --bootdisk scsi0
qm start 101

# Dentro de la VM: iniciar cluster con kubeadm
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Verificación

  1. Proxmox

    • Accede a la UI (https://<host>:8006) y verifica que la VM k8s-master está en estado Running.
    • Ejecuta pvesh get /nodes/<node>/qemu/101/status/current y confirma que los recursos asignados coinciden con lo planeado.
  2. Kubernetes

    • En la VM, kubectl get nodes debe listar el master como Ready.
    • kubectl get pods -A muestra los pods del CNI (Flannel) en estado Running.
    • Despliega un pod de prueba: kubectl run hello --image=nginx --restart=Never y verifica kubectl get pods y curl <node-ip>:<nodePort>.
  3. Backup

    • Ejecuta vzdump 101 --mode snapshot y confirma que el archivo de backup se genera en el datastore.
    • Dentro de Kubernetes, velero backup create test-backup --include-namespaces default y luego velero backup get para validar el snapshot.

Notas adicionales

  • Red de puente vs VLAN: si planeas separar tráfico de gestión (SSH, API) del tráfico de datos (media streaming), crea una VLAN adicional en vmbr0 y asigna la etiqueta a los VMs que lo requieran.
  • CPU pinning: en Proxmox, habilita NUMA y asigna cores dedicados a la VM de control plane para evitar contención con otros VMs.
  • LXC como nodo worker: los contenedores LXC pueden actuar como nodos k8s sin necesidad de un hipervisor completo, pero requieren que el kernel del host tenga los módulos necesarios (cgroup v2, iptables‑nf).
  • Actualizaciones: actualiza primero Proxmox, luego la VM de Kubernetes. Evita actualizar el kernel del host mientras los nodos LXC están activos, ya que pueden perder conectividad.
  • Monitorización unificada: configura Prometheus con node_exporter tanto en Proxmox (via pve-exporter) como en los nodos k8s para una vista completa del consumo de recursos.