14 KiB
Idea 3 — Supporto ESXi per le Build VM
Stato: proposta / valutazione. Modello: host CI (Windows o Linux) continua a fare orchestrazione ma le build VM girano su un server ESXi remoto invece che in VMware Workstation locale.
1. Obiettivo
Permettere a Invoke-CIJob di usare un host ESXi (o cluster vCenter)
come backend di virtualizzazione, mantenendo:
- workflow YAML invariati (eventualmente con nuovo label
windows-build:esxi) - transport WinRM/SSH verso i guest invariato
- formato artifact e flusso
clone → start → wait → build → collect → destroyidentico
Cambia: come si fa clone/start/stop/delete della VM, dove vivono i dischi, come si determina l'IP del guest, come si autenticano i comandi di management.
2. Fattibilità
2.1 API di management ESXi
| Opzione | Pro | Contro | Verdetto |
|---|---|---|---|
| A. pyVmomi (Python SDK ufficiale) | API completa (cloni, snapshot, power ops, GuestOps); supportata; va anche contro singolo host ESXi senza vCenter. | Solo Python. Curva di apprendimento (managed object reference, task tracking). | Raccomandata se si va Python (Idea 1). |
B. PowerCLI (VMware.PowerCLI PSGallery) |
Idiomatica per PowerShell; comandi New-VM, Get-Snapshot, ecc. molto leggibili. |
Modulo grosso (~2 GB), Windows-friendly ma installazione richiede Install-Module. Performance avvio cmdlet non sempre rapida. |
Buona se si resta in PowerShell. |
C. ovftool + REST API ESXi (vSphere API REST) |
Standard moderno; copre la maggior parte delle operazioni in vSphere 7+. | API REST single-host ha gap rispetto a SOAP/pyVmomi; complicata gestione task. | Sconsigliata come strato unico. |
D. govc (VMware/govmomi CLI) |
Binario Go portabile, scriptabile da shell qualsiasi. | Meno espressivo per logiche complesse (loop, error handling); diventa un "second-class" tooling. | Buona per script ad-hoc, non per orchestratore. |
Le due strade realistiche sono A (pyVmomi) o B (PowerCLI), in funzione dell'esito dell'Idea 1.
2.2 Mappa di adattamento
| Operazione | Workstation oggi | ESXi domani (pyVmomi) |
|---|---|---|
| Linked clone | vmrun clone ... linked -snapshot=BaseClean |
vim.VirtualMachineCloneSpec con linkedClone=True e snapshot ref |
| Start VM | vmrun start <vmx> |
VirtualMachine.PowerOn() (Task) |
| Stop VM | vmrun stop <vmx> hard |
VirtualMachine.PowerOff() (Task) |
| Delete VM | vmrun deleteVM <vmx> |
VirtualMachine.Destroy_Task() |
| List snapshots | vmrun listSnapshots |
VirtualMachine.snapshot.rootSnapshotList (tree) |
| Get guest IP | vmrun getGuestIPAddress (errore #10) |
VirtualMachine.guest.ipAddress (richiede VMware Tools attivi) |
| Test running | vmrun list + path search |
VirtualMachine.runtime.powerState == 'poweredOn' |
| Trasferimento file pre-WinRM/SSH | non usato | GuestOperationsManager (FileManager + ProcessManager) — opzionale, oggi non serve |
Il transport _Transport.psm1 (SSH) e le sessioni WinRM non cambiano:
una volta che la VM è up con IP raggiungibile, l'host CI parla direttamente
col guest come oggi.
2.3 Architettura proposta
┌──────────────┐ ┌─────────────────────────────┐
│ Gitea │ │ ESXi host(s) │
│ act_runner │ │ ├─ Template Windows (snap BaseClean) │
│ │ │ ├─ Template Linux (snap BaseClean-Linux) │
└──────┬───────┘ │ └─ Datastore: ci-builds │
│ └──────────▲──────────────────┘
│ orchestrate │ vSphere API (443)
▼ │
┌──────────────────┐ │
│ CI orchestrator │──────────────┘
│ (host Win o Lin)│
└─────┬────────────┘
│ WinRM/SSH (network L3 ammessa)
▼
Build VM efimera su ESXi
L'host CI continua a esistere come "control plane". Può essere lo stesso hardware di oggi (Windows 11) oppure migrato a Linux (Idea 2). Le build VM non girano più localmente.
2.4 Nuove configurazioni richieste
- ESXi host raggiungibile da host CI sulla 443/TCP.
- Account di servizio ESXi (
ci-runner@vsphere.localolocal usercon ruolo custom): permessi minimi su datastore, folder, snapshot, power ops. - Datastore dedicato (SSD/NVMe) per cloni e template; quota / monitoring.
- Resource pool dedicato
ci-buildscon CPU/memory limits. - Portgroup di rete con DHCP raggiungibile (o assegnazione IP statica via cloud-init / Sysprep).
- Snapshot dei template identico al setup attuale (
BaseClean/BaseClean-Linux) — convertire VMX→VMX-su-ESXi via OVF (ovftool).
2.5 Rischi specifici
| Rischio | Severità | Mitigazione |
|---|---|---|
| Linked clone su ESXi standalone (senza vCenter) ha limitazioni rispetto a Workstation | Alta | Validare in PoC: alcune versioni ESXi free non supportano CloneVM_Task via API senza license. |
| Licenza ESXi: la versione free non espone le API write (solo read-only) — bug noto vSphere | Critica | Serve almeno vSphere Essentials o licenza valutativa. Verificare PRIMA di pianificare. |
| Throughput linked clone su NFS/iSCSI datastore inferiore a SSD locale Workstation | Media | Datastore VMFS su NVMe locale o vSAN; benchmark con Test-CapacityBurnIn. |
| Tempo medio "clone → IP raggiungibile" più alto rispetto a Workstation locale | Media | Misurare con Measure-CIBenchmark; ottimizzare warm pool template (Backup-CITemplate non più utile, sostituire con template VM in folder dedicata). |
| Gestione concorrente cloni: race su nome VM o snapshot revert | Media | Lock per JobId lato orchestrator; oppure naming con suffisso UUID. |
| Determinazione IP: VMware Tools deve essere attivo e DHCP funzionante | Bassa | Già un prerequisito attuale (Wait-VMReady). Documentare in AGENTS.md nuova versione. |
| Errore #11 (machine-id identico sui clone Linux) si ripropone identico su ESXi | Bassa | Stessa fix: reset machine-id pre-snapshot. Documentato. |
| Sicurezza: credenziali vCenter/ESXi nello stesso store delle credenziali guest | Media | Target Credential Manager separato (ESXiServiceAccount) o keyring + ACL. |
| Cleanup VM orfane più costoso (richiede chiamata API per ogni VM in folder) | Bassa | Riscrivere Cleanup-OrphanedBuildVMs per usare folder-scoped query. |
2.6 Sequenza di implementazione consigliata
- PoC manuale: clonare manualmente un template su ESXi via UI/PowerCLI, avviare, fare WinRM da host CI. Misurare tempi.
- PoC scriptato: una versione minimale di
New-BuildVM-ESXi.ps1(onew_build_vm_esxi.py) che fa clone+start. Validare race conditions. - Astrazione
IVmBackend: introdurre nei moduli_Common/vmrun.pyun'interfaccia a 2 implementazioni (Workstation,ESXi), selezionata via env var (GITEA_CI_VM_BACKEND=workstation|esxi). In questo modo si può fare canary deploy job-per-job. - Migrazione template (export OVF da Workstation, import su ESXi datastore).
- Workflow YAML aggiornati con label
windows-build:esxiaccanto awindows-build:host. - Capacity burn-in concorrente sull'host ESXi.
3. Stima volumi / sforzo (relativa)
| Area | Indicatori dimensione | Complessità |
|---|---|---|
| Setup hardware/licenze ESXi | 1 host fisico + licenza Essentials | Variabile (acquisto) |
| PoC clone/start/stop via pyVmomi o PowerCLI | ~200 righe | Media |
Astrazione backend (IVmBackend con 2 impl) |
refactor di _Common, New-BuildVM, Remove-BuildVM, Wait-VMReady |
Media |
| Export OVF dei template + import ESXi + ri-validazione snapshot | 3 template | Media |
| Riconfigurazione network/DHCP per build VM su ESXi | 1 portgroup + DHCP scope | Media |
Adattamento Cleanup-OrphanedBuildVMs, Watch-DiskSpace (datastore-aware) |
~300 righe | Bassa |
Documentazione (HOST-SETUP.md nuovo capitolo ESXi, OPTIMIZATION.md) |
2-3 file md | Bassa |
| Validazione e2e + benchmark vs Workstation | piano test esistente esteso | Alta |
4. Pro / Contro
Pro
- Scalabilità: un ESXi con CPU/RAM adeguate ospita facilmente 8-16 job concorrenti
vs ~4 con Workstation locale (limite testato in
Test-CapacityBurnIn). - Disaccoppia host CI (control plane) da hardware di build (data plane).
- Resource pool / shares / reservation: QoS per i job CI.
- Backup template / DR via snapshot ESXi nativi o appliance Veeam.
- Permette di avere host CI Linux (Mint) senza dover usare KVM (Idea 2 + Idea 3 sinergiche).
- Multi-runner futuro più semplice (più host CI puntano allo stesso ESXi).
Contro
- Costo licenza vSphere (la free non basta per le API write).
- Hardware aggiuntivo dedicato (o ri-uso di un server esistente).
- Latenza di rete in più rispetto a in-process locale.
- Throughput clone dipende da datastore; può essere peggio se non si ha SSD locale ESXi.
- Backup VMDK template (
Backup-CITemplate.ps1) va riprogettato (usare snapshot ESXi nativi o export OVF schedulato). - Disaster scenario: se ESXi è giù, tutte le pipeline si fermano. Con Workstation locale il guasto era confinato all'host CI.
5. Sinergia con altre idee
- Idea 1 (Python): forte sinergia.
pyVmomiè Python-only; restando in PowerShell si è costretti aVMware.PowerCLI, che ha overhead di caricamento e dimensioni notevoli. - Idea 2 (host Linux): complementare. Idea 3 sposta il "dove girano le VM"
ma non vincola il "dove gira l'orchestrator". Si può:
- Win host + ESXi backend: minima migrazione lato CI script (resta PS).
- Linux host + ESXi backend: massima modernizzazione, ma somma i rischi delle due migrazioni. Solo dopo Idee 1+2 stabilizzate.
- Con Idea 3 implementata, l'utilità di Idea 2 (host Linux con KVM locale) cala: la VM locale serve solo per debug, non più per CI in production.
6. Decision checklist
Procedere solo se almeno 3 dei seguenti sono veri:
- È disponibile (o pianificato) hardware ESXi + licenza Essentials.
- Si prevede di superare i 4 job concorrenti regolarmente.
- Si vuole disaccoppiare hardware CI da hardware build (es. CI in ufficio, build in rack).
- Si è pianificata l'Idea 1 (Python) o si è disposti a usare PowerCLI.
- Disaster recovery / backup datastore è un requisito esplicito.
Se la concorrenza richiesta è ≤4 job e l'hardware attuale (i9 + 64GB) regge, l'investimento ESXi non si ripaga rispetto a Workstation locale.
7. Path incrementale "minimo": ESXi opzionale
Anziché migrazione totale, supportare entrambi i backend in parallelo:
- Lasciare default
windows-build:host(Workstation locale, situazione attuale). - Aggiungere label
windows-build:esxiper job specifici (es. burn-in pesanti, regression suite notturna). - Naming dei job e folder ESXi prefissati con
ci-per filtering. - Eventuale rollback semplice (basta disabilitare il label).
Sforzo ~50% rispetto a migrazione totale, debito tecnico controllato perché
l'astrazione IVmBackend è già lì per design.