Skip to content

Repository files navigation

KubeVirt Lab Environment

Scalable Browser-Based Ubuntu Desktop VMs for Training

Ephemeral VM infrastructure with web-based VNC access - perfect for workshops, training sessions, and lab environments.


🎯 What This Does

Provides 20 concurrent students with full Ubuntu desktop environments accessible through a web browser. No VNC client installation needed. Each student gets an isolated, fresh VM that resets after use.

Use Cases:

  • Training workshops
  • Coding bootcamps
  • University lab sessions
  • Hands-on demonstrations
  • Testing environments

🏗️ Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                         Kubernetes Cluster                          │
│                                                                     │
│  ┌──────────────────────────────────────────────────────────────┐ │
│  │         Golden Image (ubuntu-golden-rootdisk PVC)            │ │
│  │  📦 Ubuntu 24.04 + Desktop + Firefox + Tools (20GB)          │ │
│  │  ✓ Created once, shared by all VMs                           │ │
│  │  ✓ Read-only base layer                                      │ │
│  └────────────┬─────────────────────────────────────────────────┘ │
│               │                                                     │
│      ┌────────┴────────┬──────────┬──────────┬─────────────┐      │
│      ▼                 ▼          ▼          ▼             ▼      │
│  ┌──────┐         ┌──────┐   ┌──────┐   ┌──────┐     ┌──────┐   │
│  │ VM 1 │         │ VM 2 │   │ VM 3 │   │ ...  │     │ VM20 │   │
│  │student1│       │student2│ │student3│ │      │     │student20│ │
│  │      │         │      │   │      │   │      │     │      │   │
│  │ 📝 Overlay     │ 📝 Overlay│📝 Overlay│ ...        │📝 Overlay│ │
│  │ (ephemeral)   │ (ephemeral)│(ephemeral)│           │(ephemeral)│ │
│  │ 2-5GB         │ 2-5GB     │ 2-5GB    │            │ 2-5GB    │ │
│  └──┬───┘         └──┬───┘   └──┬───┘   └──┬───┘     └──┬───┘   │
│     │                │          │          │             │        │
│     │ KubeVirt       │          │          │             │        │
│     │ VNC API        │          │          │             │        │
│     ▼                ▼          ▼          ▼             ▼        │
│  ┌──────┐         ┌──────┐   ┌──────┐               ┌──────┐    │
│  │ VNC  │         │ VNC  │   │ VNC  │               │ VNC  │    │
│  │Proxy │         │Proxy │   │Proxy │      ...      │Proxy │    │
│  │ Pod  │         │ Pod  │   │ Pod  │               │ Pod  │    │
│  │      │         │      │   │      │               │      │    │
│  │virtctl│         │virtctl│  │virtctl│              │virtctl│   │
│  │websockify│      │websockify│websockify│           │websockify││
│  │noVNC │         │noVNC │   │noVNC │               │noVNC │    │
│  └──┬───┘         └──┬───┘   └──┬───┘               └──┬───┘    │
│     │                │          │                       │         │
└─────┼────────────────┼──────────┼───────────────────────┼─────────┘
      │ :30080         │ :30081   │ :30082         :30099 │
      │ NodePort       │ NodePort │ NodePort       NodePort│
      ▼                ▼          ▼                       ▼
  ┌────────┐      ┌────────┐  ┌────────┐           ┌────────┐
  │Browser │      │Browser │  │Browser │           │Browser │
  │Student1│      │Student2│  │Student3│           │Student20│
  └────────┘      └────────┘  └────────┘           └────────┘
      👤              👤          👤                     👤

🔑 Key Concepts

1. Golden Image (Base Disk)

  • Single PVC containing fully configured Ubuntu desktop
  • Created once, shared by all VMs
  • Read-only to prevent corruption
  • Contains: OS + Desktop Environment + Applications

2. Ephemeral Overlays (Copy-on-Write)

┌─────────────────────────────────────────────┐
│  Student creates file "homework.txt"        │
│             ↓                               │
│  Writes to student1's overlay only          │
│             ↓                               │
│  student2 cannot see this file              │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│  Student reads /usr/bin/firefox             │
│             ↓                               │
│  Check overlay → Not found                  │
│             ↓                               │
│  Read from golden image → Return binary     │
└─────────────────────────────────────────────┘

Benefits:

  • ✅ Each VM is isolated
  • ✅ Changes are temporary (ephemeral)
  • ✅ Delete VM → fresh start
  • ✅ Storage efficient (20GB + 20×3GB = 80GB, not 400GB)

3. VNC Access Flow

Student opens browser
       ↓
http://node-ip:30080/vnc.html
       ↓
NodePort Service (30080)
       ↓
VNC Proxy Pod
       ↓
┌───────────────────────────┐
│  1. virtctl vnc           │  ← Connects to KubeVirt API
│     --proxy-only          │  ← Gets VNC stream from VM
│     :5900                 │  ← Creates local VNC proxy
│                           │
│  2. websockify            │  ← Converts VNC → WebSocket
│     :8080 → :5900         │  ← Wraps VNC for browser
│                           │
│  3. noVNC (HTML5 client)  │  ← Renders in browser
│     /vnc.html             │  ← No client install needed
└───────────────────────────┘
       ↓
KubeVirt VNC API
       ↓
VM's VNC Server (in guest OS)
       ↓
Desktop Display

Why this architecture?

  • ❌ VMs don't expose VNC on network (security)
  • ✅ KubeVirt provides VNC via API (authenticated)
  • ✅ Proxy pod handles protocol conversion
  • ✅ Browser-native experience (no VNC client)

📊 Resource Breakdown

Storage Efficiency

Traditional Approach:
20 VMs × 20GB each = 400GB total

Our Approach:
┌──────────────────────────────────────┐
│ Golden Image:        20GB  (shared)  │
│ VM 1 Overlay:        3GB             │
│ VM 2 Overlay:        3GB             │
│ ...                                  │
│ VM 20 Overlay:       3GB             │
│ ─────────────────────────────────    │
│ Total:              ~70GB            │
└──────────────────────────────────────┘

💾 Space Saved: 82%

Compute Resources

Per VM:
├─ CPU: 2 cores
├─ RAM: 2GB
└─ Disk: ~3GB (overlay) + shared 20GB base

For 20 VMs:
├─ CPU: 40 cores
├─ RAM: 40GB
└─ Disk: 70GB

Network Ports

NodePort Range: 30080-30099
├─ student1  → :30080
├─ student2  → :30081
├─ student3  → :30082
│    ...
└─ student20 → :30099

🚀 Quick Start

Prerequisites

  • Kubernetes cluster (1.24+)
  • KubeVirt installed
  • Docker or container runtime

Option A: Using Makefile (Recommended)

# See all available commands
make help

# Build VNC proxy image
make build-vnc

# Create golden image (one-time setup)
make create-golden-dv
make install-desktop
# Wait for cloud-init to complete (~10 min)
make finalize-golden

# Create and deploy VMs
make create-vms NUM_STUDENTS=20
make deploy-proxies

# Get access URLs
make urls

Option B: Manual Steps

# 1. Clone repository
git clone <repo-url>
cd kubevirt-lab

# 2. Build VNC proxy image
docker build -t vnc-proxy:v1 .

# 3. Create golden image (one-time, ~10 minutes)
kubectl apply -f golden-image-dv.yaml
kubectl wait --for=condition=Ready dv/ubuntu-golden-rootdisk --timeout=15m

# 4. Create 20 VMs
for i in {1..20}; do
  sed "s/STUDENT_NAME/student$i/g; s/GOLDEN_IMAGE_NAME/ubuntu-golden-rootdisk/g" student-vm-template.yaml | kubectl apply -f -
done

# 5. Deploy VNC proxies
./deploy-vnc-proxies.sh all

Access

Share with students:
http://<your-node-ip>:30080/vnc.html  (student1)
http://<your-node-ip>:30081/vnc.html  (student2)
...

Login: student / ubuntu

🔄 Lifecycle & Operations

VM Lifecycle

┌─────────────────────────────────────────────────────┐
│                                                     │
│  [CREATE] → [RUNNING] → [STOPPED] → [DELETED]      │
│      ↑                       ↓                      │
│      └───────── [RESET] ─────┘                      │
│                                                     │
│  When VM deleted:                                   │
│  ✓ Overlay deleted (ephemeral storage)             │
│  ✓ Golden image untouched                          │
│  ✓ Next boot is fresh                              │
│                                                     │
└─────────────────────────────────────────────────────┘

Common Operations

Start a session:

kubectl apply -f vm-template.yaml  # Creates VM
./deploy-vnc-proxies.sh student1   # Exposes VNC

End a session (reset VM):

kubectl delete vm student1         # Deletes VM + overlay
# Student gets fresh VM on next create

Update golden image:

# 1. Stop all VMs
kubectl delete vm --all

# 2. Create temporary VM from golden image
# 3. Install updates/software
# 4. Stop temporary VM
# 5. Recreate golden image from updated disk

Scale to more students:

# Edit deploy-vnc-proxies.sh START_PORT if needed
for i in {21..40}; do
  sed "s/student1/student$i/g" vm-template.yaml | kubectl apply -f -
done
./deploy-vnc-proxies.sh all

🎨 Components

1. Golden Image DataVolume

File: golden-image-dv.yaml

Purpose: Download and prepare base Ubuntu disk
Creates: PVC with Ubuntu 24.04 + Desktop
Size: 10-20GB
Build Time: 5-10 minutes

2. VM Template

File: vm-template.yaml

Purpose: Define VM configuration
Disk Mode: Ephemeral (references golden PVC)
Cloud-init: Sets hostname, user, password

3. VNC Proxy Container

Files: Dockerfile, start-vnc-proxy.sh

Purpose: Provide browser-based VNC access
Contains:
  - virtctl (KubeVirt CLI)
  - websockify (VNC→WebSocket converter)
  - noVNC (HTML5 VNC client)

4. Automation Script

File: deploy-vnc-proxies.sh

Purpose: Deploy VNC proxies for all VMs
Creates:
  - RBAC (ServiceAccount, ClusterRole)
  - Service (NodePort per VM)
  - Deployment (Proxy pod per VM)

⚙️ Configuration

Adjust VM Resources

Edit vm-template.yaml:

resources:
  requests:
    memory: 2Gi    # Increase for heavy workloads
cpu:
  cores: 2         # Increase for compute-intensive tasks

Change Login Credentials

Edit vm-template.yaml cloud-init section:

users:
  - name: student
    plain_text_passwd: ubuntu  # Change password here

Modify Port Range

Edit deploy-vnc-proxies.sh:

START_PORT=30080  # Change to different range

Add Software to Golden Image

Edit golden-image-dv.yaml or create VM, install software, export disk.


🔒 Security Considerations

  • ✅ VMs isolated from each other (network namespaces)
  • ✅ VNC not exposed directly (API-based access)
  • ✅ RBAC controls API access
  • ✅ NodePorts can be firewalled to internal network
  • ⚠️ Default password (change in production)
  • ⚠️ No encryption on VNC stream (use ingress with TLS)

Production recommendations:

  • Use Ingress with TLS for HTTPS access
  • Implement authentication (OAuth2, LDAP)
  • Change default passwords
  • Use NetworkPolicies for VM isolation
  • Enable audit logging

📈 Monitoring

# Check VM status
kubectl get vm,vmi

# Check VNC proxy status
kubectl get pods | grep vnc

# View VM console
virtctl console student1

# View proxy logs
kubectl logs -l app=vnc-student1

# Check resource usage
kubectl top nodes
kubectl top pods

🐛 Troubleshooting

VM won't start

kubectl describe vmi student1
# Look for: Image pull errors, resource constraints

Can't access VNC in browser

# Check proxy pod
kubectl logs -l app=vnc-student1

# Check service
kubectl get svc vnc-student1

# Test from inside cluster
kubectl run test --rm -it --image=curlimages/curl -- curl http://vnc-student1:8080/vnc.html

Desktop not loading

# Check cloud-init completed
virtctl console student1
sudo cloud-init status --long

# Check disk space
df -h

📚 Learn More


About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages