Comandi base oc e virtctl
Quick reference dei comandi più utili nel quotidiano. Pensata come la “PowerCLI cheat sheet” di chi viene da vSphere: tieni questa pagina aperta finché i comandi non entrano nelle dita.
Indice
- Setup CLI
- Login e contesto
- Navigazione del cluster
- Operazioni di base sulle VM
- Console, VNC, SSH
- Live migration
- Snapshot, restore, clone
- Manutenzione dei nodi
- Risorse, capacity, troubleshooting
- Storage e PVC
- Networking
- Output e formattazione
1. Setup CLI
Le due CLI che usi quotidianamente:
oc— la CLI di OpenShift, superset dikubectl. Per qualunque operazione “Kubernetes” generale.virtctl— la CLI specifica per le operazioni VM (start, stop, console, migrate, ssh, …).
Installazione
# oc — scaricabile dal Cluster Operator help della console, oppure:curl -L https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ | tar -xz -C ~/.local/bin oc kubectl
# virtctl — disponibile come download dalla stessa console (Help → Command Line Tools)# Su Linux/macOS:curl -L -o virtctl <URL_dalla_console>chmod +x virtctlsudo mv virtctl /usr/local/bin/Auto-completamento bash/zsh
# Bashoc completion bash | sudo tee /etc/bash_completion.d/oc
# Zshoc completion zsh > "${fpath[1]}/_oc"2. Login e contesto
Login
# Con utente/password (LDAP, htpasswd, ecc.)oc login https://api.miocluster.example.com:6443 -u admin
# Con token (consigliato per CI/CD; il token si copia da console: User → Copy Login Command)oc login --token=sha256~XXX --server=https://api.miocluster.example.com:6443
# Logoutoc logoutContesto e namespace di lavoro
# Quale cluster e namespace stai usando?oc whoamioc whoami --show-contextoc project
# Cambiare namespace (= "cd" nella folder vCenter)oc project produzione-app
# Lista namespaceoc get namespaceoc get project # in OpenShift il "project" è un namespace con annotation extraMulti-cluster con kubeconfig
# Aggiungere un cluster a kubeconfigoc login https://api.cluster-b.example.com:6443oc config get-contexts # lista contestioc config use-context <nome-contesto> # switch fra cluster3. Navigazione del cluster
Visione d’insieme
oc get nodes -o wide # lista nodi (= host ESXi)oc get vm -A # tutte le VM definiteoc get vmi -A # tutte le VM in esecuzioneoc get pods -A # tutti i pod (anche quelli che eseguono le VM)oc get co # cluster operators e loro statoCosa c’è in un namespace
oc get all -n produzione-app # vista "tutto" dello namespaceoc get vm,vmi,pvc,svc,route -n produzione-app # solo le risorse rilevanti per VM4. Operazioni di base sulle VM
Lifecycle
# Creare una VM da YAMLoc apply -f rhel9-test.yaml
# Avviare una VMvirtctl start rhel9-test -n lab-vm
# Spegnimento "soft" (chiede al qemu-ga di shutdown)virtctl stop rhel9-test -n lab-vm
# Spegnimento forzato (= power off)virtctl stop rhel9-test -n lab-vm --force --grace-period=0
# Riavviovirtctl restart rhel9-test -n lab-vm
# Pausa / ripresavirtctl pause vm rhel9-test -n lab-vmvirtctl unpause vm rhel9-test -n lab-vm
# Lista VMoc get vm -n lab-vmoc get vmi -n lab-vm -o wide # include IP e nodo
# Eliminareoc delete vm rhel9-test -n lab-vmModificare una VM
# Editing interattivo (apre $EDITOR)oc edit vm rhel9-test -n lab-vm
# Patch puntualeoc patch vm rhel9-test -n lab-vm --type=merge -p 'spec: template: spec: domain: cpu: cores: 4'💡 Modifiche a CPU/RAM richiedono di solito un restart della VM, salvo che hot-plug sia supportato dalla feature/versione.
Ispezionare lo stato
# Vista completa di una VMoc describe vm rhel9-test -n lab-vm
# Stato in esecuzione (VMI = istanza)oc get vmi rhel9-test -n lab-vm -o yaml
# Eventi della VMoc get events -n lab-vm \ --field-selector involvedObject.name=rhel9-test5. Console, VNC, SSH
Console seriale
virtctl console rhel9-test -n lab-vm# Per uscire: Ctrl-]Console VNC (utile soprattutto per Windows)
virtctl vnc rhel9-test -n lab-vm# Apre un client VNC locale collegato alla VMSSH tramite virtctl (port forwarding automatico)
virtctl ssh cloud-user@vm/rhel9-test.lab-vm
# Con chiave specificavirtctl ssh -i ~/.ssh/id_ed25519 cloud-user@vm/rhel9-test.lab-vmPort forwarding generico (di un servizio sulla VM)
# Forwarda la porta locale 8080 → porta 80 della VMvirtctl port-forward vm/rhel9-test 8080:80 -n lab-vm6. Live migration
# Avviare una migrazione manualevirtctl migrate rhel9-test -n lab-vm
# Verificare lo stato (l'oggetto si chiama VirtualMachineInstanceMigration, alias vmim)oc get vmim -n lab-vm
# Cancellare una migrazione in corso (se possibile)virtctl migrate-cancel rhel9-test -n lab-vm
# Storia delle migrazioni di una VMoc get vmim -n lab-vm -o jsonpath='{range .items[?(@.spec.vmiName=="rhel9-test")]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'7. Snapshot, restore, clone
Snapshot
# Creare una VirtualMachineSnapshotoc apply -f - <<EOFapiVersion: snapshot.kubevirt.io/v1beta1kind: VirtualMachineSnapshotmetadata: name: rhel9-test-pre-upgrade namespace: lab-vmspec: source: apiGroup: kubevirt.io kind: VirtualMachine name: rhel9-testEOF
# Listaoc get vmsnapshot -n lab-vm
# Eliminareoc delete vmsnapshot rhel9-test-pre-upgrade -n lab-vmRestore
oc apply -f - <<EOFapiVersion: snapshot.kubevirt.io/v1beta1kind: VirtualMachineRestoremetadata: name: rhel9-test-restore-001 namespace: lab-vmspec: target: apiGroup: kubevirt.io kind: VirtualMachine name: rhel9-test virtualMachineSnapshotName: rhel9-test-pre-upgradeEOF
oc get vmrestore -n lab-vm⚠️ Per il restore la VM target deve essere spenta.
Clone
# Clone con virtctl (richiede che la VM sorgente sia spenta o che il backend supporti hot clone)virtctl clone vm rhel9-test --target-name rhel9-test-clone -n lab-vmMemory dump
virtctl memory-dump get rhel9-test \ --claim-name=rhel9-test-memdump \ --create-claim \ -n lab-vm8. Manutenzione dei nodi
Maintenance mode “manuale”
# Cordon: il nodo non riceve più nuovi pod/VMoc adm cordon worker-01.example.com
# Drain: live-migrate le VM, evict i podoc adm drain worker-01.example.com \ --delete-emptydir-data \ --ignore-daemonsets \ --force
# Verifica che i pod virt-launcher siano uscitioc get pods -A --field-selector spec.nodeName=worker-01.example.com
# Quando hai finito: rimettere il nodo in serviziooc adm uncordon worker-01.example.comMaintenance dichiarativa (Node Maintenance Operator)
oc apply -f - <<EOFapiVersion: nodemaintenance.medik8s.io/v1beta1kind: NodeMaintenancemetadata: name: maint-worker-01spec: nodeName: worker-01.example.com reason: "Aggiornamento firmware NIC"EOF
# Statooc get nodemaintenance
# Uscire dalla manutenzioneoc delete nodemaintenance maint-worker-019. Risorse, capacity, troubleshooting
Uso risorse
# Top dei nodi (richiede metrics-server / monitoring stack)oc adm top nodes
# Top dei pod in un namespaceoc adm top pods -n produzione-app
# Risorse di un nodo specificooc describe node worker-01.example.com | head -50Logs di troubleshooting
# Log del pod che esegue una VM (virt-launcher)oc get pods -n lab-vm --selector kubevirt.io/vm=rhel9-testoc logs -n lab-vm <virt-launcher-pod> -c compute
# Log dell'operator OpenShift Virtualizationoc logs -n openshift-cnv -l name=virt-operator --tail=200
# Log persistenti (se hai logging stack acceso): usa la console UI o LogQLDebug di un nodo
# Apre una shell privilegiata sul nodooc debug node/worker-01.example.com# Poi dentro:chroot /hostjournalctl -u crio --since "1 hour ago"”Eventi” del cluster (analoghi al Tasks & Events di vCenter)
# Eventi del namespace, dal più recenteoc get events -n lab-vm --sort-by=.lastTimestamp
# Solo eventi di tipo Warningoc get events -n lab-vm --field-selector type=Warning10. Storage e PVC
# Lista PV / PVC / StorageClassoc get pvoc get pvc -n lab-vmoc get storageclass
# Vedere i PVC associati a una VMoc get vmi rhel9-test -n lab-vm -o jsonpath='{.spec.volumes[*].persistentVolumeClaim.claimName}{"\n"}'
# Espandere un PVC (online resize, se supportato dal driver CSI)oc patch pvc rhel9-test-root -n lab-vm --type=merge -p 'spec: resources: requests: storage: 100Gi'
# StorageProfile (capability di una StorageClass dal punto di vista delle VM)oc get storageprofile11. Networking
# NetworkAttachmentDefinitionoc get net-attach-def -n produzione-appoc describe net-attach-def pg-mgmt-vlan100 -n produzione-app
# NMState policies sui nodioc get nodenetworkconfigurationpolicyoc get nodenetworkstate worker-01.example.com -o yaml
# NetworkPolicyoc get networkpolicy -n produzione-app
# Service e Routeoc get svc -n produzione-appoc get route -n produzione-app12. Output e formattazione
Formati utili
oc get vmi -n lab-vm -o wide # tabella estesaoc get vmi -n lab-vm -o yaml # YAML completooc get vmi -n lab-vm -o json | jq '.items[].status.phase'
# Custom columnsoc get vmi -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,NODE:.status.nodeName,IP:.status.interfaces[0].ipAddress,PHASE:.status.phase'
# JSONPathoc get vmi -A -o jsonpath='{range .items[?(@.status.phase=="Running")]}{.metadata.namespace}{"/"}{.metadata.name}{" → "}{.status.nodeName}{"\n"}{end}'
# Go templateoc get vm -A -o go-template='{{range .items}}{{.metadata.namespace}}/{{.metadata.name}}: {{.spec.running}}{{"\n"}}{{end}}'Filtraggio per label
# Tutte le VM con label app=postgresoc get vm -A -l app=postgres
# Esclusioneoc get vm -A -l 'tier!=db'
# Combinazionioc get vm -A -l 'env=prod,team=pagamenti'Esportare la definizione di una VM (per riusarla altrove)
# Pulisce status e fields gestiti dal clusteroc get vm rhel9-test -n lab-vm -o yaml \ | yq 'del(.status, .metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, .metadata.generation, .metadata.managedFields)' \ > rhel9-test.yaml(Richiede yq. In alternativa puoi usare oc neat se installato come plugin.)
Mini-FAQ rapida
“Come spengo brutalmente una VM bloccata?”
virtctl stop <vm> -n <ns> --force --grace-period=0“Come trovo su che nodo gira una VM?”
oc get vmi <vm> -n <ns> -o jsonpath='{.status.nodeName}{"\n"}'“Come vedo l’IP di una VM senza dover entrare in console?”
oc get vmi <vm> -n <ns> -o jsonpath='{.status.interfaces[*].ipAddress}{"\n"}'(Funziona se il qemu-guest-agent è installato e attivo nella VM.)
“Come vedo tutte le VM accese in tutto il cluster?”
oc get vmi -A --field-selector status.phase=Running“Come cambio la default StorageClass?”
oc patch storageclass <vecchia-default> -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'oc patch storageclass <nuova-default> -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'