# 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**: ```bash # 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: ```bash 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. ```bash # 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:** ```bash 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) ```bash 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: 80` → `targetPort: 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: ```bash 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! ```yaml 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-http` → **ClusterIP** `port: 80` (backend de Ingress) * `iso-server-samba` → **LoadBalancer** `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: ```bash 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 ```bash # 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) ```yaml 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 ``` ```bash 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 ```yaml # 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 ```bash # 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`: ```bash 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) ---