After successful VM migration with kubectl-mtv, the migrated VMs become full KubeVirt virtual machines that can be managed using the broader KubeVirt ecosystem. This chapter covers the seamless integration between kubectl-mtv and virtctl, enabling complete VM lifecycle management from migration through ongoing operations.
Overview: Relationship between kubectl-mtv and virtctl
kubectl-mtv and virtctl form a complete virtualization management solution:
| Tool |
Primary Focus |
Key Capabilities |
| kubectl-mtv |
Migration |
Provider management, inventory discovery, migration planning, execution, monitoring |
| virtctl |
VM Operations |
VM lifecycle, console access, resource management, advanced KubeVirt features |
Migration to Operations Workflow
graph LR
A[Source VMs] --> B[kubectl-mtv Migration]
B --> C[KubeVirt VMs]
C --> D[virtctl Management]
D --> E[Ongoing Operations]
The integration provides:
- Seamless Transition: Migrated VMs are immediately manageable with virtctl
- Shared Resources: Common KubeVirt objects (DataVolumes, InstanceTypes, etc.)
- Consistent Experience: Similar CLI patterns and Kubernetes-native operations
- Advanced Features: Access to full KubeVirt capabilities post-migration
Resource Continuity
Resources created during migration are compatible with virtctl operations:
- DataVolumes: Created by kubectl-mtv, manageable with virtctl
- Instance Types: Applied during migration, usable in virtctl operations
- Network Attachments: Configured in mapping, accessible via virtctl
- Storage Classes: Used in migration, available for new operations
VirtCtl Installation
Option 1: Binary Installation
1
2
3
4
5
6
7
8
9
10
| # Get latest release version
export VERSION=$(curl -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)
# Download and install virtctl
wget https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-linux-amd64
chmod +x virtctl-${VERSION}-linux-amd64
sudo mv virtctl-${VERSION}-linux-amd64 /usr/local/bin/virtctl
# Verify installation
virtctl version
|
Option 2: Kubectl Plugin (Krew)
1
2
3
4
5
6
7
8
9
| # Install via Krew
kubectl krew install virt
# Use as kubectl plugin
kubectl virt version
# Create alias for convenience
echo 'alias virtctl="kubectl virt"' >> ~/.bashrc
source ~/.bashrc
|
Option 3: Package Manager Installation
1
2
3
4
5
6
7
8
| # Ubuntu/Debian (if available in repos)
sudo apt update && sudo apt install virtctl
# RHEL/CentOS/Fedora (if available in repos)
sudo dnf install virtctl
# Verify installation
virtctl version
|
Verification of Integration
1
2
3
4
5
6
7
8
9
10
11
| # Check both tools are available
kubectl mtv version
virtctl version
# Verify cluster access
kubectl get vms
kubectl get virtualmachines
# Check MTV and KubeVirt resources
kubectl get providers.forklift.konveyor.io
kubectl get kubevirt -n kubevirt
|
Post-Migration VM Management
VM Lifecycle Operations
Starting and Stopping VMs
After migration, use virtctl for VM power management:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # List migrated VMs
kubectl get vms -l migration.forklift.konveyor.io/plan=production-migration
# Start a migrated VM
virtctl start web-server-01 -n production
# Stop VM gracefully (default 30 second grace period)
virtctl stop database-primary -n production
# Stop VM with custom grace period
virtctl stop web-server-02 -n production --grace-period 60
# Force stop VM immediately (emergency use)
virtctl stop problematic-vm -n production --force
# Restart VM
virtctl restart cache-server -n production
|
Advanced Power Management
1
2
3
4
5
6
7
8
9
10
11
| # Pause VM (freeze execution)
virtctl pause web-server-01 -n production
# Unpause VM (resume execution)
virtctl unpause web-server-01 -n production
# Soft reboot VM guest OS
virtctl soft-reboot database-primary -n production
# Dry run operations for testing
virtctl restart test-vm --dry-run
|
VM Status and Monitoring
Health and Status Checks
1
2
3
4
5
6
7
8
9
10
11
| # Get detailed VM status
kubectl describe vm web-server-01 -n production
# Check VM conditions
kubectl get vm web-server-01 -n production -o yaml | grep -A 10 conditions
# Monitor VM events
kubectl get events -n production | grep web-server-01
# Watch VM status changes
kubectl get vms -n production -w
|
Resource Utilization
1
2
3
4
5
6
7
8
| # Get VM resource usage
kubectl top vm web-server-01 -n production
# Monitor all VMs in namespace
kubectl top vms -n production
# Get detailed resource information
virtctl vmexport get web-server-01 -n production --include-secret
|
Console and Remote Access
Serial Console Access
1
2
3
4
5
6
7
| # Access VM serial console (text-based)
virtctl console web-server-01 -n production
# Exit console: Ctrl+]
# Console with specific timeout
virtctl console database-primary -n production --timeout 300
|
VNC Console Access
1
2
3
4
5
6
7
8
| # Access VM graphical console via VNC
virtctl vnc web-server-01 -n production
# VNC with specific local port
virtctl vnc web-server-01 -n production --port 5901
# VNC with proxy configuration
virtctl vnc web-server-01 -n production --proxy-only
|
SSH Access
Direct SSH to VMs
1
2
3
4
5
6
7
8
9
10
11
| # SSH to VM (requires guest agent and SSH setup)
virtctl ssh user@web-server-01 -n production
# SSH with specific identity file
virtctl ssh -i ~/.ssh/vm_key user@web-server-01 -n production
# SSH with port forwarding
virtctl ssh user@web-server-01 -n production -L 8080:localhost:80
# SSH with command execution
virtctl ssh user@web-server-01 -n production "systemctl status nginx"
|
SSH Key Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Inject SSH key during VM creation (post-migration)
virtctl create vm new-vm \
--image registry.company.com/ubuntu:20.04 \
--ssh-key "$(cat ~/.ssh/id_rsa.pub)" \
--user admin
# Add SSH authorized keys to running VM
virtctl addauthorizedkey web-server-01 -n production \
--user admin \
--key "$(cat ~/.ssh/new_key.pub)"
# Remove SSH authorized keys
virtctl removeauthorizedkey web-server-01 -n production \
--user admin \
--key "$(cat ~/.ssh/old_key.pub)"
|
Advanced VM Operations
Live Migration
1
2
3
4
5
6
7
8
9
10
11
| # Migrate VM to another node
virtctl migrate web-server-01 -n production
# Migrate to specific node
virtctl migrate database-primary -n production --node worker-node-3
# Dry run migration
virtctl migrate test-vm -n test --dry-run
# Cancel ongoing migration
virtctl migrate-cancel web-server-01 -n production
|
VM Cloning and Expansion
1
2
3
4
5
6
7
8
9
10
11
12
13
| # Create VM from existing DataVolume (created during migration)
virtctl create vm cloned-web-server \
--source-pvc web-server-01-disk-0 \
--instancetype medium \
--namespace production
# Expand VM disk (if supported by storage class)
virtctl expand web-server-01 -n production --size 100Gi
# Create VM snapshot
virtctl snapshot create web-server-01-snapshot \
--vm web-server-01 \
--namespace production
|
Resource Management
Memory and CPU Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # Hot-plug CPU (if supported)
virtctl cpu hot-plug web-server-01 -n production --cores 4
# Hot-plug memory (if supported)
virtctl memory hot-plug web-server-01 -n production --size 8Gi
# Add additional disk
virtctl add-volume web-server-01 \
--volume-name additional-storage \
--pvc-name additional-pvc \
--namespace production
# Remove volume
virtctl remove-volume web-server-01 \
--volume-name additional-storage \
--namespace production
|
Integration Workflows
Complete Migration to Operations Workflow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| #!/bin/bash
# complete-migration-workflow.sh - End-to-end migration and operations setup
PLAN_NAME="production-web-tier"
NAMESPACE="production"
echo "=== Phase 1: Migration with kubectl-mtv ==="
# 1. Create and execute migration
kubectl mtv create plan "$PLAN_NAME" \
--source vsphere-prod \
--target openshift-prod \
--vms "web-01,web-02,web-03" \
--target-namespace "$NAMESPACE" \
--migration-type warm
kubectl mtv start plan "$PLAN_NAME" \
--cutover "$(date -d '+2 hours' --iso-8601=seconds)"
# 2. Monitor migration completion
echo "Waiting for migration completion..."
while true; do
STATUS=$(kubectl mtv get plan "$PLAN_NAME" -o jsonpath='{.status.phase}')
if [ "$STATUS" = "Succeeded" ]; then
echo "Migration completed successfully"
break
elif [ "$STATUS" = "Failed" ]; then
echo "Migration failed"
exit 1
fi
sleep 30
done
echo "=== Phase 2: Post-Migration Operations with virtctl ==="
# 3. Verify migrated VMs
kubectl get vms -n "$NAMESPACE" -l "forklift.konveyor.io/plan=$PLAN_NAME"
# 4. Start migrated VMs
for vm in web-01 web-02 web-03; do
echo "Starting VM: $vm"
virtctl start "$vm" -n "$NAMESPACE"
done
# 5. Wait for VMs to be ready
echo "Waiting for VMs to start..."
for vm in web-01 web-02 web-03; do
while true; do
if kubectl get vm "$vm" -n "$NAMESPACE" -o jsonpath='{.status.ready}' | grep -q true; then
echo "VM $vm is ready"
break
fi
sleep 10
done
done
# 6. Validate VM connectivity
for vm in web-01 web-02 web-03; do
echo "Testing connectivity to $vm..."
virtctl ssh admin@"$vm" -n "$NAMESPACE" "echo 'VM $vm is accessible via SSH'" || echo "SSH not ready for $vm"
done
echo "=== Migration and operations setup complete ==="
|
Monitoring and Health Checks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| #!/bin/bash
# vm-health-monitor.sh - Comprehensive VM health monitoring
NAMESPACE="production"
echo "=== VM Health Dashboard ==="
# VM Status Overview
echo "1. VM Status Overview:"
kubectl get vms -n "$NAMESPACE" -o custom-columns="NAME:.metadata.name,STATUS:.status.ready,AGE:.metadata.creationTimestamp"
echo
# Resource Utilization
echo "2. Resource Utilization:"
kubectl top vms -n "$NAMESPACE" 2>/dev/null || echo "Metrics not available"
echo
# Network Connectivity
echo "3. Network Connectivity Tests:"
for vm in $(kubectl get vms -n "$NAMESPACE" -o jsonpath='{.items[*].metadata.name}'); do
echo "Testing VM: $vm"
# Check VM is running
if kubectl get vm "$vm" -n "$NAMESPACE" -o jsonpath='{.status.ready}' | grep -q true; then
echo " [OK] VM is running"
# Test SSH connectivity
if virtctl ssh admin@"$vm" -n "$NAMESPACE" "echo 'SSH OK'" &>/dev/null; then
echo " [OK] SSH accessible"
else
echo " [FAIL] SSH not accessible"
fi
# Test application ports (example)
if virtctl ssh admin@"$vm" -n "$NAMESPACE" "nc -z localhost 80" &>/dev/null; then
echo " [OK] HTTP service responding"
else
echo " [FAIL] HTTP service not responding"
fi
else
echo " [FAIL] VM not running"
fi
echo
done
# Recent Events
echo "4. Recent VM Events:"
kubectl get events -n "$NAMESPACE" --sort-by='.metadata.creationTimestamp' | tail -10
|
Backup and Disaster Recovery
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| #!/bin/bash
# vm-backup-restore.sh - VM backup and restore operations
NAMESPACE="production"
BACKUP_NAMESPACE="backups"
backup_vm() {
local vm_name="$1"
local backup_name="${vm_name}-backup-$(date +%Y%m%d-%H%M%S)"
echo "Creating backup for VM: $vm_name"
# Create VM snapshot
virtctl snapshot create "$backup_name" \
--vm "$vm_name" \
--namespace "$NAMESPACE"
# Export VM configuration
kubectl get vm "$vm_name" -n "$NAMESPACE" -o yaml > "${backup_name}-config.yaml"
echo "Backup created: $backup_name"
}
restore_vm() {
local backup_name="$1"
local new_vm_name="$2"
echo "Restoring VM from backup: $backup_name"
# Restore from snapshot
virtctl snapshot restore "$backup_name" \
--vm "$new_vm_name" \
--namespace "$NAMESPACE"
echo "VM restored as: $new_vm_name"
}
# Backup critical VMs
for vm in web-01 database-primary cache-server; do
backup_vm "$vm"
done
# Restore example (when needed)
# restore_vm "web-01-backup-20240115-140000" "web-01-restored"
|
Operational Workflows
Daily Operations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # Morning health check routine
#!/bin/bash
echo "=== Daily VM Health Check ==="
# 1. Check all VM status
kubectl get vms --all-namespaces | grep -v Running | head -20
# 2. Check resource utilization
kubectl top vms --all-namespaces | head -10
# 3. Check for failed migrations
kubectl mtv get plans --all-namespaces | grep Failed
# 4. Test critical VM connectivity
for vm in critical-db web-primary cache-main; do
virtctl ssh admin@"$vm" -n production "uptime" || echo "ALERT: $vm not accessible"
done
|
Maintenance Procedures
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # Planned maintenance workflow
maintenance_vm() {
local vm_name="$1"
local namespace="$2"
echo "Starting maintenance for $vm_name"
# 1. Create pre-maintenance snapshot
virtctl snapshot create "${vm_name}-pre-maintenance" \
--vm "$vm_name" --namespace "$namespace"
# 2. Migrate to maintenance node (if needed)
virtctl migrate "$vm_name" -n "$namespace" --node maintenance-node
# 3. Perform maintenance operations
virtctl ssh admin@"$vm_name" -n "$namespace" "sudo apt update && sudo apt upgrade -y"
# 4. Restart VM
virtctl restart "$vm_name" -n "$namespace"
# 5. Verify health
sleep 60
virtctl ssh admin@"$vm_name" -n "$namespace" "systemctl status nginx" || echo "Service check failed"
echo "Maintenance completed for $vm_name"
}
|
Resource Optimization
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # VM performance optimization
optimize_vm() {
local vm_name="$1"
local namespace="$2"
echo "Optimizing performance for $vm_name"
# Check current resource usage
kubectl top vm "$vm_name" -n "$namespace"
# Optimize based on usage patterns
# (These operations require VM restart)
# Hot-plug additional CPU if needed
if [ $(kubectl top vm "$vm_name" -n "$namespace" | awk 'NR==2 {print $2}' | sed 's/%//') -gt 80 ]; then
echo "High CPU usage detected, consider scaling up"
# virtctl cpu hot-plug "$vm_name" -n "$namespace" --cores 4
fi
# Hot-plug additional memory if needed
if [ $(kubectl top vm "$vm_name" -n "$namespace" | awk 'NR==2 {print $3}' | sed 's/%//') -gt 80 ]; then
echo "High memory usage detected, consider scaling up"
# virtctl memory hot-plug "$vm_name" -n "$namespace" --size 8Gi
fi
}
|
Storage Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| # VM storage operations
manage_vm_storage() {
local vm_name="$1"
local namespace="$2"
echo "Managing storage for $vm_name"
# Check disk usage via SSH
virtctl ssh admin@"$vm_name" -n "$namespace" "df -h" | grep -E "(Filesystem|/dev/)"
# Add additional storage if needed
# virtctl add-volume "$vm_name" \
# --volume-name extra-storage \
# --pvc-name "${vm_name}-extra-pvc" \
# --namespace "$namespace"
# Create new PVC for expansion
# kubectl apply -f - <<EOF
# apiVersion: v1
# kind: PersistentVolumeClaim
# metadata:
# name: ${vm_name}-extra-pvc
# namespace: $namespace
# spec:
# accessModes: [ReadWriteOnce]
# resources:
# requests:
# storage: 50Gi
# EOF
}
|
Security and Access Control
VM Security Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # VM security hardening
secure_vm() {
local vm_name="$1"
local namespace="$2"
echo "Applying security hardening to $vm_name"
# Update SSH configuration
virtctl ssh admin@"$vm_name" -n "$namespace" "
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl reload sshd
"
# Apply security updates
virtctl ssh admin@"$vm_name" -n "$namespace" "
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
"
# Configure firewall
virtctl ssh admin@"$vm_name" -n "$namespace" "
sudo ufw --force enable
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
"
echo "Security hardening completed for $vm_name"
}
|
User and Access Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # VM user management
manage_vm_users() {
local vm_name="$1"
local namespace="$2"
echo "Managing users for $vm_name"
# List current users
virtctl ssh admin@"$vm_name" -n "$namespace" "cat /etc/passwd | grep -E '/bin/(bash|sh)$'"
# Add new SSH key for user
virtctl addauthorizedkey "$vm_name" -n "$namespace" \
--user admin \
--key "$(cat ~/.ssh/new_team_member.pub)"
# Remove old SSH key
virtctl removeauthorizedkey "$vm_name" -n "$namespace" \
--user admin \
--key "$(cat ~/.ssh/departed_member.pub)"
echo "User management completed for $vm_name"
}
|
Troubleshooting Integration Issues
Common Issues and Solutions
VM Not Starting After Migration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # Troubleshoot VM startup issues
debug_vm_startup() {
local vm_name="$1"
local namespace="$2"
echo "Debugging startup issues for $vm_name"
# Check VM status
kubectl describe vm "$vm_name" -n "$namespace" | grep -A 20 "Status:"
# Check VMI events
kubectl get events -n "$namespace" | grep "$vm_name"
# Check DataVolume status
kubectl get datavolumes -n "$namespace" | grep "$vm_name"
# Check pod logs (if VM is running)
if kubectl get pod -n "$namespace" -l "kubevirt.io/vm=$vm_name" &>/dev/null; then
kubectl logs -n "$namespace" -l "kubevirt.io/vm=$vm_name"
fi
# Attempt to start VM
virtctl start "$vm_name" -n "$namespace"
}
|
SSH Connectivity Issues
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # Troubleshoot SSH connectivity
debug_ssh_connectivity() {
local vm_name="$1"
local namespace="$2"
echo "Debugging SSH connectivity for $vm_name"
# Check VM IP address
VM_IP=$(kubectl get vm "$vm_name" -n "$namespace" -o jsonpath='{.status.interfaces[0].ipAddress}')
echo "VM IP: $VM_IP"
# Test network connectivity
kubectl run debug-pod --rm -i --tty --image=nicolaka/netshoot -- \
ping -c 3 "$VM_IP"
# Check if SSH service is running via console
echo "Checking SSH service via console..."
virtctl console "$vm_name" -n "$namespace" --timeout 30 <<EOF
systemctl status sshd
exit
EOF
# Test SSH port specifically
kubectl run debug-pod --rm -i --tty --image=nicolaka/netshoot -- \
nc -zv "$VM_IP" 22
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # Debug VM performance issues
debug_vm_performance() {
local vm_name="$1"
local namespace="$2"
echo "Analyzing performance for $vm_name"
# Check resource allocation
kubectl describe vm "$vm_name" -n "$namespace" | grep -A 10 "Resources:"
# Check current usage
kubectl top vm "$vm_name" -n "$namespace"
# Check node resources
NODE=$(kubectl get vm "$vm_name" -n "$namespace" -o jsonpath='{.status.nodeName}')
kubectl describe node "$NODE" | grep -A 10 "Allocated resources:"
# Check VM internal performance
virtctl ssh admin@"$vm_name" -n "$namespace" "
top -bn1 | head -20
free -h
df -h
iostat -x 1 3
"
}
|
Summary: Complete Virtualization Management
The integration of kubectl-mtv and virtctl provides comprehensive virtualization management:
Migration Phase (kubectl-mtv)
- Discover and assess source environments
- Plan and execute migrations
- Monitor migration progress
- Handle migration-specific configurations
Operations Phase (virtctl)
- Manage VM lifecycle (start/stop/restart)
- Provide console and SSH access
- Handle resource management and optimization
- Implement backup and disaster recovery
- Maintain security and compliance
Continuous Integration
Both tools work with the same Kubernetes resources, enabling:
- Seamless handoff from migration to operations
- Consistent resource management
- Unified monitoring and alerting
- Integrated backup and disaster recovery
This complete toolchain enables organizations to migrate from traditional virtualization platforms to Kubernetes while maintaining operational excellence throughout the VM lifecycle.
Previous: Chapter 19: Model Context Protocol (MCP) Server Integration
Next: Chapter 21: Command Reference