añadido kubevirt

This commit is contained in:
2025-08-12 00:32:36 +02:00
parent 1f530b9bb3
commit 4a31b62a6f
18 changed files with 512 additions and 78 deletions

View File

@@ -1,24 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubevirt-manager
namespace: kubevirt-manager
spec:
replicas: 1
selector:
matchLabels:
app: kubevirt-manager
template:
metadata:
labels:
app: kubevirt-manager
spec:
serviceAccountName: kubevirt-manager
containers:
- name: kubevirt-manager
image: kubevirtmanager/kubevirt-manager:1.4.0
ports:
- containerPort: 8001
env:
- name: BACKEND_URL
value: "http://localhost:8080"

View File

@@ -1,26 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubevirt-manager
namespace: kubevirt-manager
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
tls:
- hosts:
- kubevirt.manabo.org
secretName: kubevirt-manager-tls
rules:
- host: kubevirt.manabo.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubevirt-manager
port:
number: 80

View File

@@ -1,7 +0,0 @@
resources:
- namespace.yaml
- deployments/deployment.yaml
- services/service.yaml
# - ingress/ingress.yaml
- rbac/serviceaccount.yaml
- rbac/clusterrolebinding.yaml

View File

@@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubevirt-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubevirt-manager
namespace: kubevirt-manager

View File

@@ -1,6 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubevirt-manager
namespace: kubevirt-manager

View File

@@ -0,0 +1,36 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubevirt-manager
namespace: kubevirt
spec:
replicas: 1
selector:
matchLabels:
app: kubevirt-manager
template:
metadata:
labels:
app: kubevirt-manager
spec:
serviceAccountName: kubevirt-manager
containers:
- name: kubevirt-manager
image: kubevirtmanager/kubevirt-manager:1.4.0
ports:
- containerPort: 8001
env:
- name: BACKEND_URL
value: "http://localhost:8080"
readinessProbe:
httpGet:
path: /
port: 8001
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 8001
initialDelaySeconds: 15
periodSeconds: 20

View File

@@ -0,0 +1,51 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: iso-server
namespace: kubevirt
spec:
replicas: 1
selector:
matchLabels:
app: iso-server
template:
metadata:
labels:
app: iso-server
spec:
containers:
- name: httpd
image: httpd:2.4
ports:
- containerPort: 80
volumeMounts:
- name: iso-storage
mountPath: /usr/local/apache2/htdocs
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
- name: samba
image: dperson/samba
args: ["-p", "-s", "isos;/share;yes;no"]
ports:
- containerPort: 445
securityContext:
runAsUser: 0
volumeMounts:
- name: iso-storage
mountPath: /share
volumes:
- name: iso-storage
persistentVolumeClaim:
claimName: iso-pvc

View File

@@ -0,0 +1,27 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubevirt-manager
namespace: kubevirt
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
# nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.0.0/24,192.168.254.0/24"
spec:
ingressClassName: nginx
tls:
- hosts:
- kubevirt.c2et.net
secretName: kubevirt-c2et-net-tls
rules:
- host: kubevirt.c2et.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubevirt-manager
port:
number: 80

View File

@@ -0,0 +1,24 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: iso-server
namespace: kubevirt
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- isoserver.c2et.net
secretName: isoserver-c2et-net-tls
rules:
- host: isoserver.c2et.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: iso-server-http
port:
number: 80

View File

@@ -0,0 +1,14 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kubevirt
resources:
- rbac/serviceaccount.yaml
- rbac/clusterrolebinding.yaml
- deployments/dashboard.yaml
- services/service-dashboard.yaml
- ingress/ingress-dashboard.yaml
- pvc/iso-pvc.yaml
- deployments/isoserver.yaml
- services/service-http.yaml
- services/service-samba.yaml
- ingress/ingress-isoserver.yaml

12
kubevirt/pvc/iso-pvc.yaml Normal file
View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: iso-pvc
namespace: kubevirt
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 800Gi
storageClassName: ceph-rbd

View File

@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubevirt-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubevirt-manager
namespace: kubevirt

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubevirt-manager
namespace: kubevirt

300
kubevirt/readme.md Normal file
View File

@@ -0,0 +1,300 @@
# 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)
---

View File

@@ -2,7 +2,7 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: kubevirt-manager name: kubevirt-manager
namespace: kubevirt-manager namespace: kubevirt
spec: spec:
selector: selector:
app: kubevirt-manager app: kubevirt-manager
@@ -10,5 +10,4 @@ spec:
- port: 80 - port: 80
targetPort: 8001 targetPort: 8001
protocol: TCP protocol: TCP
nodePort: 30081 # <--- puedes elegir el puerto, debe estar entre 30000-32767 type: ClusterIP
type: NodePort

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: iso-server-http
namespace: kubevirt
spec:
type: ClusterIP
selector:
app: iso-server
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: iso-server-samba
namespace: kubevirt
spec:
type: LoadBalancer
loadBalancerIP: 192.168.0.105
selector:
app: iso-server
ports:
- name: samba
port: 445
targetPort: 445
protocol: TCP