Files
kubernetes/kubevirt/readme.md
2025-08-12 00:32:36 +02:00

8.0 KiB

KubeVirt en Kubernetes (SUSE) con Dashboard y ISO Server

Entorno: 4 nodos SUSE con Flannel + Multus, containerd con SystemdCgroup=true, kubelet con cgroupDriver: systemd.

Dominios: kubevirt.c2et.net (dashboard) y isoserver.c2et.net (HTTP para imágenes).

Storage: ceph-rbd (RWO) para el PVC del ISO server.


0) Prerrequisitos y comprobaciones

En cada nodo:

# Virtualización (debe devolver > 0)
egrep -o 'vmx|svm' /proc/cpuinfo | wc -l

# Cargar módulos KVM (Intel o AMD)
sudo modprobe kvm
sudo modprobe kvm_intel   # o kvm_amd

# Persistir módulos al arranque
printf "kvm\nkvm_intel\n" | sudo tee /etc/modules-load.d/kvm.conf  # (o kvm_amd)

# Verificar /dev/kvm y AppArmor
ls -l /dev/kvm
sudo aa-status | head -n 5

# containerd: SystemdCgroup=true
sudo grep -n "SystemdCgroup" /etc/containerd/config.toml

# kubelet: cgroupDriver: systemd
grep -i cgroup /var/lib/kubelet/config.yaml

PSA (opcional) si usas Pod Security Admission:

kubectl create ns kubevirt --dry-run=client -o yaml | kubectl apply -f -
kubectl label ns kubevirt \
  pod-security.kubernetes.io/enforce=privileged \
  pod-security.kubernetes.io/audit=privileged \
  pod-security.kubernetes.io/warn=privileged --overwrite

kubectl create ns cdi --dry-run=client -o yaml | kubectl apply -f -
kubectl label ns cdi \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=baseline \
  pod-security.kubernetes.io/warn=baseline --overwrite

1) Instalar KubeVirt y CDI (versionado recomendado)

Recomendación: fija versiones (no uses latest) para reproducibilidad.

# Elige versiones estables (ejemplos; ajusta según tu política)
export KUBEVIRT_VERSION=v1.6.0
export CDI_VERSION=v1.62.0

# KubeVirt (operator + CR)
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml

# CDI (operator + CR)
kubectl apply -f https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VERSION}/cdi-operator.yaml
kubectl apply -f https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VERSION}/cdi-cr.yaml

Checks mínimos:

kubectl -n kubevirt get kv kubevirt -o jsonpath='{.status.phase}'; echo  # Debería: Deployed
kubectl -n kubevirt get pods
kubectl -n cdi get pods

2) Instalar virtctl (CLI)

curl -L -o virtctl \
  https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/virtctl-${KUBEVIRT_VERSION}-linux-amd64
chmod +x virtctl && sudo mv virtctl /usr/local/bin/
virtctl version

3) Dashboard (kubevirt-manager) en kubevirt.c2et.net

Estructura (kustomize) sugerida dentro de tu repo kubernetes/kubevirt/:

.
├─ deployments/
│  └─ dashboard.yaml           # Deployment (image kubevirtmanager/kubevirt-manager:1.4.0)
├─ services/
│  └─ service-dashboard.yaml   # Service ClusterIP (80 → 8001)
├─ ingress/
│  └─ ingress-dashboard.yaml   # Ingress (class nginx, LE prod)
├─ rbac/
│  ├─ serviceaccount.yaml      # SA kubevirt-manager
│  └─ clusterrolebinding.yaml  # CRB a cluster-admin
└─ kustomization.yaml

Puntos clave:

  • Namespace: kubevirt.
  • Service ClusterIP exponiendo port: 80targetPort: 8001.
  • Ingress con ingressClassName: nginx, cert-manager.io/cluster-issuer: letsencrypt-prod, host kubevirt.c2et.net.
  • RBAC: ClusterRoleBinding a cluster-admin para la SA del dashboard.

Aplicación y verificación:

kubectl apply -k kubernetes/kubevirt
kubectl -n kubevirt get deploy,svc,ingress | grep kubevirt-manager

Acceso: https://kubevirt.c2et.net/


4) ISO Server en isoserver.c2et.net (HTTP) + Samba (LB 192.168.0.105)

Estructura (kustomize) en el mismo módulo kubernetes/kubevirt/:

.
├─ pvc/
│  └─ iso-pvc.yaml             # PVC ceph-rbd (RWO)
├─ deployments/
│  └─ isoserver.yaml           # Pod con httpd:2.4 + dperson/samba
├─ services/
│  ├─ service-http.yaml        # Service ClusterIP (para Ingress)
│  └─ service-samba.yaml       # Service LoadBalancer (LB IP 192.168.0.105)
├─ ingress/
│  └─ ingress-isoserver.yaml   # Ingress (host isoserver.c2et.net)
└─ kustomization.yaml

PVC (ceph-rbd) — ¡Importante!

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: iso-pvc
  namespace: kubevirt
spec:
  accessModes: [ReadWriteOnce]    # RBD es RWO
  resources:
    requests:
      storage: 800Gi
  storageClassName: ceph-rbd

Deployment

  • httpd:2.4 monta /usr/local/apache2/htdocs
  • dperson/samba exporta /share
  • Ambos montan el mismo PVC (iso-pvc) → lo que subes por Samba se sirve por HTTP.

Services

  • iso-server-httpClusterIP port: 80 (backend de Ingress)

  • iso-server-sambaLoadBalancer loadBalancerIP: 192.168.0.105 port: 445

    • Asegura que 192.168.0.105 está dentro de un pool de MetalLB.

Ingress (HTTP/HTTPS)

  • Host: isoserver.c2et.net
  • Cert: letsencrypt-prod
  • Sin force-ssl-redirect para poder usar HTTP con CDI si tu CA no es de confianza.

Aplicación y verificación:

kubectl apply -k kubernetes/kubevirt
kubectl -n kubevirt get pods | grep iso-server
kubectl -n kubevirt get svc iso-server-http iso-server-samba -o wide
kubectl -n kubevirt get ingress iso-server

Acceso:

  • Samba: \\192.168.0.105\isos (guest por defecto; puedes parametrizar usuarios)
  • HTTP: http://isoserver.c2et.net/

Sugerencias de seguridad (opcionales):

  • Añade credenciales a Samba: args: ["-p","-u","iso;TuPass","-s","isos;/share;yes;no"]
  • Limita el Ingress por rangos: nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.0.0/24"

5) Uso con CDI: importar imágenes/ISOs

5.1 Subir ficheros al ISO server

# Linux (guest)
sudo mkdir -p /mnt/isos
sudo mount -t cifs //192.168.0.105/isos /mnt/isos -o guest,vers=3.0
cp ./ubuntu-24.04.qcow2 /mnt/isos/

# Ver por HTTP
curl -I http://isoserver.c2et.net/ubuntu-24.04.qcow2

5.2 Crear un DataVolume desde URL (HTTP)

apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: dv-ubuntu-24
  namespace: default
spec:
  source:
    http:
      url: "http://isoserver.c2et.net/ubuntu-24.04.qcow2"
  pvc:
    storageClassName: ceph-rbd
    accessModes: ["ReadWriteOnce"]
    resources:
      requests:
        storage: 20Gi
kubectl apply -f dv-ubuntu-24.yaml
kubectl -n default get dv,pvc
kubectl -n cdi get pods -w     # verás el importer hasta Succeeded

HTTPS también funciona. Si usas CA propia, puedes inyectar la CA en el DV (campo certConfigMap) o usar virtctl image-upload --insecure en pruebas.

5.3 Usar el PVC en una VM

# Fragmento de spec de VirtualMachine
volumes:
  - name: rootdisk
    dataVolume:
      name: dv-ubuntu-24

disks:
  - name: rootdisk
    disk: { bus: virtio }

Para ISOs, crea un DV de la ISO y móntalo como cdrom: { readonly: true }.


6) Comprobaciones y troubleshooting

# KubeVirt / CDI
kubectl -n kubevirt get kv kubevirt -o jsonpath='{.status.phase}'; echo
kubectl -n kubevirt get deploy,ds,pods | egrep 'virt-|kubevirt-'
kubectl -n cdi get pods

# Dashboard
kubectl -n kubevirt get endpoints kubevirt-manager

# ISO server
kubectl -n kubevirt get endpoints iso-server-http
smbclient -L 192.168.0.105 -N
curl -I http://isoserver.c2et.net/

MetalLB asigna otra IP → asegúrate de que 192.168.0.105 está en el pool. Puedes recrear el Service o patch:

kubectl -n kubevirt patch svc iso-server-samba -p '{"spec":{"loadBalancerIP":"192.168.0.105"}}'

CDI falla con HTTPS → usa HTTP o confía la CA (o certConfigMap en el DV).


7) Referencias rápidas

  • Namespace: kubevirt
  • Dashboard host: kubevirt.c2et.net (Ingress nginx, TLS LE)
  • ISO server host: isoserver.c2et.net (HTTP para CDI; TLS opcional)
  • Samba LB: 192.168.0.105 (MetalLB)
  • StorageClass ISO PVC: ceph-rbd (RWO)