Skip to content

15-Minute Quickstart

This guide gets you up and running with VirtRigaud v0.3.8 in 15 minutes using either a vSphere or Libvirt provider.

Prerequisites

  • Kubernetes cluster (1.26+)
  • kubectl configured
  • Helm 3.8+
  • Access to a vSphere or Libvirt/KVM host

API

All resources use infra.virtrigaud.io/v1beta1. This is the stable API for all new deployments.

Step 1: Install VirtRigaud

helm repo add virtrigaud https://projectbeskar.github.io/virtrigaud
helm repo update virtrigaud

helm install virtrigaud virtrigaud/virtrigaud \
  --version 0.3.11 \
  --namespace virtrigaud-system \
  --create-namespace

Providers are disabled by default in v0.3.8

As of v0.3.8 the chart deploys only the manager by default. Provider Deployments are opt-in — set providers.<type>.enabled=true to deploy a templated provider alongside the manager, or manage providers independently as Provider CRs. This is a secure-by-default change; see the Upgrade Guide if you relied on auto-deployed providers in v0.3.7.

To enable specific providers at install time:

helm install virtrigaud virtrigaud/virtrigaud \
  --version 0.3.11 \
  --namespace virtrigaud-system \
  --create-namespace \
  --set providers.vsphere.enabled=true \
  --set providers.libvirt.enabled=true

To skip CRDs if you manage them separately:

helm install virtrigaud virtrigaud/virtrigaud \
  --version 0.3.11 \
  --namespace virtrigaud-system \
  --create-namespace \
  --skip-crds

Using Kustomize

git clone https://github.com/projectbeskar/virtrigaud.git
cd virtrigaud
kubectl apply -k config/default

Step 2: Verify Installation

# Manager pod is running
kubectl get pods -n virtrigaud-system

# All 10 CRDs are installed
kubectl get crds | grep virtrigaud.io

# Manager is at v0.3.8
kubectl logs -n virtrigaud-system deployment/virtrigaud-manager | head -5

After the manager starts, confirm v0.3.8 is running via the metrics endpoint:

kubectl port-forward -n virtrigaud-system svc/virtrigaud-manager 8080:8080 &
curl -s http://localhost:8080/metrics | grep '^virtrigaud_build_info'
# virtrigaud_build_info{component="manager",...,version="v0.3.8"} 1

The virtrigaud_circuit_breaker_state and virtrigaud_provider_tasks_inflight families are seeded to 0 at boot for every Provider CR. Reconcile metrics now include kind="VMClone" and kind="VMSet" series. See the Observability Guide for the full metrics surface.

Step 3: Configure a Provider

Option A: vSphere Provider

kubectl create secret generic vsphere-credentials \
  --namespace default \
  --from-literal=endpoint=https://vcenter.example.com \
  --from-literal=username=administrator@vsphere.local \
  --from-literal=password=your-password \
  --from-literal=insecure=false
apiVersion: infra.virtrigaud.io/v1beta1
kind: Provider
metadata:
  name: vsphere-prod
  namespace: default
spec:
  type: vsphere
  endpoint: https://vcenter.example.com
  credentialSecretRef:
    name: vsphere-credentials
    namespace: default
  runtime:
    mode: Remote
    image: "ghcr.io/projectbeskar/virtrigaud/provider-vsphere:v0.3.11"
    service:
      port: 9090
      tls:
        enabled: true
        secretRef:
          name: provider-vsphere-tls
        insecureSkipVerify: false

mTLS required

Every Provider CR must include a spec.runtime.service.tls block. A Provider without it will not reconcile (TLSConfigured=False, Reason=TLSBlockMissing). See the upgrade guide for remediation steps. Images are multi-arch (linux/amd64 + linux/arm64) — no action required for arm64 clusters.

Option B: Libvirt Provider

kubectl create secret generic libvirt-credentials \
  --namespace default \
  --from-literal=uri=qemu+ssh://root@libvirt-host.example.com/system \
  --from-literal=privateKey="$(cat ~/.ssh/id_rsa)"
apiVersion: infra.virtrigaud.io/v1beta1
kind: Provider
metadata:
  name: libvirt-lab
  namespace: default
spec:
  type: libvirt
  endpoint: qemu+ssh://root@libvirt-host.example.com/system
  credentialSecretRef:
    name: libvirt-credentials
    namespace: default
  runtime:
    mode: Remote
    image: "ghcr.io/projectbeskar/virtrigaud/provider-libvirt:v0.3.11"
    service:
      port: 9090
      tls:
        enabled: true
        secretRef:
          name: provider-libvirt-tls
        insecureSkipVerify: false
kubectl apply -f provider.yaml

Circuit breaker on first deploy

If the provider pod is unreachable on first deploy (e.g. SSH tunnel not yet up for a libvirt provider), the circuit breaker will trip after 10 failed RPCs and virtrigaud_circuit_breaker_state{provider="libvirt-lab"} will read 2 (Open). This is working as designed. See Resilience for the recovery path.

Step 4: Create a VM Class

apiVersion: infra.virtrigaud.io/v1beta1
kind: VMClass
metadata:
  name: small
  namespace: default
spec:
  cpu: 2
  memory: 2Gi
kubectl apply -f vmclass.yaml

Step 5: Create a VM Image

vSphere

apiVersion: infra.virtrigaud.io/v1beta1
kind: VMImage
metadata:
  name: ubuntu-22
  namespace: default
spec:
  source:
    vsphere:
      templateName: ubuntu-22.04-template

Libvirt

apiVersion: infra.virtrigaud.io/v1beta1
kind: VMImage
metadata:
  name: ubuntu-22
  namespace: default
spec:
  source:
    libvirt:
      url: https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
kubectl apply -f vmimage.yaml

Step 6: Create Your First VM

apiVersion: infra.virtrigaud.io/v1beta1
kind: VirtualMachine
metadata:
  name: my-first-vm
  namespace: default
spec:
  providerRef:
    name: vsphere-prod   # or libvirt-lab
    namespace: default
  classRef:
    name: small
    namespace: default
  imageRef:
    name: ubuntu-22
    namespace: default
  powerState: "On"
  userData:
    cloudInit:
      inline: |
        #cloud-config
        users:
          - name: ubuntu
            sudo: ALL=(ALL) NOPASSWD:ALL
            ssh_authorized_keys:
              - ssh-rsa AAAAB3... your-public-key
  networks:
  - name: default
    networkRef:
      name: default-network
      namespace: default
kubectl apply -f vm.yaml

Step 7: Monitor VM Creation

# Watch VM status
kubectl get vm my-first-vm -w

# Detailed status including phase and IPs
kubectl describe vm my-first-vm

# Events
kubectl get events --field-selector involvedObject.name=my-first-vm

Phase column

The phase status field (PendingProvisioningRunning) may be empty for VMs that were auto-adopted by the VMAdoption controller (watching Provider CRs annotated virtrigaud.io/adopt-vms: "true"). Adopted VMs arrive with status.ips already populated; the phase field is a known gap for this path (issue I2).

Step 8: Access Your VM

# Get VM IP address
kubectl get vm my-first-vm -o jsonpath='{.status.ips[0]}'

# Get console URL (if supported by the provider)
kubectl get vm my-first-vm -o jsonpath='{.status.consoleURL}'

# SSH once the VM has an IP
ssh ubuntu@<vm-ip>

Step 9: Advanced operations

Create a Snapshot

apiVersion: infra.virtrigaud.io/v1beta1
kind: VMSnapshot
metadata:
  name: my-vm-snapshot
  namespace: default
spec:
  vmRef:
    name: my-first-vm
  nameHint: "pre-update-snapshot"
  memory: true

Clone a VM

VMClone is functional in v0.3.8 (vSphere and Proxmox; libvirt returns Unimplemented):

apiVersion: infra.virtrigaud.io/v1beta1
kind: VMClone
metadata:
  name: my-first-vm-clone
  namespace: default
spec:
  source:
    vmRef:
      name: my-first-vm
      namespace: default
  targetName: my-first-vm-clone-target
  classRef:
    name: small
    namespace: default
  options:
    type: Full

VMSet (stub — not functional in v0.3.8)

VMSet controller not yet active

The VMSet CRD is installed but the controller is a stub. Any VMSet resource will immediately show Ready=False / Reason=ControllerNotImplemented. Do not use VMSet in production in v0.3.8.

apiVersion: infra.virtrigaud.io/v1beta1
kind: VMSet
metadata:
  name: web-servers
  namespace: default
spec:
  replicas: 3
  template:
    spec:
      providerRef:
        name: vsphere-prod
        namespace: default
      classRef:
        name: small
        namespace: default
      imageRef:
        name: ubuntu-22
        namespace: default
      powerState: "On"

Step 10: Clean Up

kubectl delete vm my-first-vm
kubectl delete vmsnapshot my-vm-snapshot
kubectl delete vmclone my-first-vm-clone

# Uninstall VirtRigaud (optional)
helm uninstall virtrigaud -n virtrigaud-system
kubectl delete namespace virtrigaud-system

Next Steps

Troubleshooting

  1. Check provider status: kubectl get providers -A
  2. Check manager logs: kubectl logs -n virtrigaud-system deployment/virtrigaud-manager
  3. Check circuit breaker: curl -s http://localhost:8080/metrics | grep circuit_breaker_state
  4. File an issue: github.com/projectbeskar/virtrigaud/issues