301 lines
8.0 KiB
Markdown
301 lines
8.0 KiB
Markdown
# 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)
|
|
|
|
---
|
|
|