Version: 2.0.0 Date: 2026-01-30 Platform: OpenShift 4.10 - 4.16
Hyper2KVM Operator automates VM migration from VMware vSphere to OpenShift Virtualization/KVM. This guide covers deployment on OpenShift Container Platform with platform-specific optimizations.
cluster-admin (for installation)Operator:
Webhook:
Worker Pods (per worker):
Install directly from OpenShift OperatorHub with automatic updates and lifecycle management.
Configure installation:
stable (recommended) or previewA specific namespace on the cluster (recommended)All namespaces on the clusterhyper2kvm-system (or custom)Automatic or Manual# Check operator subscription
oc get subscription -n hyper2kvm-system
# Check CSV (ClusterServiceVersion)
oc get csv -n hyper2kvm-system
# Check operator pod
oc get pods -n hyper2kvm-system -l app.kubernetes.io/name=hyper2kvm-operator
# Check CRDs
oc get crd | grep hyper2kvm
Expected output:
migrationjobs.hyper2kvm.io
jobtemplates.hyper2kvm.io
oc apply -f - <<EOF
apiVersion: hyper2kvm.io/v1alpha1
kind: MigrationJob
metadata:
name: example-migration
namespace: default
spec:
operation: inspect
image:
path: /data/input/example.vmdk
format: vmdk
priority: 50
EOF
Install using Helm with full customization capabilities.
helm repo add hyper2kvm https://ssahani.github.io/hyper2kvm
helm repo update
# values-openshift.yaml
global:
namespace: hyper2kvm-system
# Enable OpenShift-specific features
openshift:
enabled: true
autoDetect: true
# Routes for external access
route:
enabled: true
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
# SecurityContextConstraints
scc:
create: true
name: hyper2kvm-worker-scc
# OAuth proxy for authenticated metrics
oauth:
enabled: true
# Operator configuration
operator:
replicaCount: 2 # HA deployment
leaderElection:
enabled: true
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# Webhook configuration
webhook:
enabled: true
replicaCount: 2 # HA deployment
# Monitoring
monitoring:
prometheus:
enabled: true
grafana:
enabled: true
# Create namespace
oc new-project hyper2kvm-system
# Install operator
helm install hyper2kvm-operator hyper2kvm/hyper2kvm-operator \
--namespace hyper2kvm-system \
--values values-openshift.yaml
# Check installation
oc get all -n hyper2kvm-system
# Get metrics route URL
METRICS_URL=$(oc get route hyper2kvm-operator-metrics -n hyper2kvm-system -o jsonpath='{.spec.host}')
echo "Metrics: https://$METRICS_URL/metrics"
# Access via browser (requires authentication via OpenShift OAuth)
curl -k https://$METRICS_URL/metrics
Deploy using raw Kubernetes manifests.
oc apply -f k8s/operator/crds/
oc apply -f - <<EOF
apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
name: hyper2kvm-worker-scc
allowPrivilegedContainer: true
allowHostNetwork: false
allowHostPorts: false
allowHostPID: false
allowHostIPC: false
requiredDropCapabilities:
- KILL
- MKNOD
- SETUID
- SETGID
allowedCapabilities:
- SYS_ADMIN
- SYS_MODULE
- SYS_RAWIO
seLinuxContext:
type: MustRunAs
runAsUser:
type: RunAsAny
fsGroup:
type: RunAsAny
supplementalGroups:
type: RunAsAny
volumes:
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- projected
- secret
- hostPath
priority: 10
EOF
# Create namespace
oc new-project hyper2kvm-system
# Apply operator manifests
oc apply -f k8s/operator/
Routes provide external access to operator services.
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: hyper2kvm-metrics
namespace: hyper2kvm-system
spec:
to:
kind: Service
name: hyper2kvm-operator-metrics
port:
targetPort: metrics
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
Workers require privileged access for NBD, mount, and LVM operations.
Grant SCC to ServiceAccount:
oc adm policy add-scc-to-user hyper2kvm-worker-scc \
-z hyper2kvm-worker \
-n hyper2kvm-workers
Verify SCC Assignment:
oc describe scc hyper2kvm-worker-scc
oc get pod <worker-pod> -n hyper2kvm-workers -o yaml | grep scc
Enable OAuth proxy for authenticated metrics access.
Configuration:
openshift:
oauth:
enabled: true
image:
repository: quay.io/openshift/origin-oauth-proxy
tag: "4.14"
resources:
limits:
cpu: 100m
memory: 64Mi
Access Metrics:
# Get route
ROUTE=$(oc get route hyper2kvm-operator-metrics -o jsonpath='{.spec.host}')
# Access with OpenShift token
TOKEN=$(oc whoami -t)
curl -k -H "Authorization: Bearer $TOKEN" https://$ROUTE/metrics
Operator metrics integrate with OpenShift’s built-in monitoring stack.
Enable ServiceMonitor:
monitoring:
prometheus:
enabled: true
Access Metrics in Console:
hyper2kvm_operator_reconciliation_duration_secondsCreate Alerts:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: hyper2kvm-alerts
namespace: hyper2kvm-system
spec:
groups:
- name: hyper2kvm
interval: 30s
rules:
- alert: MigrationJobFailed
expr: hyper2kvm_operator_job_failures_total > 5
for: 5m
labels:
severity: warning
annotations:
summary: "High migration job failure rate"
description: "More than 5 jobs have failed in the last 5 minutes"
Operator appears in OpenShift Console with custom UI.
Features:
Use internal OpenShift registry for operator images.
# Tag and push to internal registry
oc tag ghcr.io/ssahani/hyper2kvm:2.0.0-operator \
hyper2kvm-operator:2.0.0 \
--reference-policy=local
# Update deployment to use internal image
oc set image deployment/hyper2kvm-operator \
operator=image-registry.openshift-image-registry.svc:5000/hyper2kvm-system/hyper2kvm-operator:2.0.0
Full support for disconnected OpenShift clusters.
Step 1: Mirror Images
# Mirror operator images
oc image mirror \
ghcr.io/ssahani/hyper2kvm:2.0.0-operator=internal-registry.example.com/hyper2kvm/operator:2.0.0 \
ghcr.io/ssahani/hyper2kvm:2.0.0-worker=internal-registry.example.com/hyper2kvm/worker:2.0.0
Step 2: Create ImageContentSourcePolicy
apiVersion: operator.openshift.io/v1alpha1
kind: ImageContentSourcePolicy
metadata:
name: hyper2kvm-mirror
spec:
repositoryDigestMirrors:
- mirrors:
- internal-registry.example.com/hyper2kvm
source: ghcr.io/ssahani
Step 3: Deploy Bundle
operator-sdk run bundle internal-registry.example.com/hyper2kvm/bundle:v2.0.0
Operator pods run with restricted security context:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
Worker pods require elevated privileges (via SCC):
securityContext:
privileged: true
capabilities:
add:
- SYS_ADMIN
- SYS_MODULE
- SYS_RAWIO
Operator requires cluster-wide permissions:
Restrict network traffic to operator pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: hyper2kvm-operator
namespace: hyper2kvm-system
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: hyper2kvm-operator
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector: {}
Operator Metrics:
hyper2kvm_operator_reconciliation_duration_seconds - Reconciliation durationhyper2kvm_operator_job_total - Total jobshyper2kvm_operator_job_failures_total - Failed jobshyper2kvm_operator_worker_count - Active workershyper2kvm_operator_is_leader - Leader election statusAccess Metrics:
# Port-forward to metrics endpoint
oc port-forward -n hyper2kvm-system svc/hyper2kvm-operator-metrics 8080:8080
# Query metrics
curl http://localhost:8080/metrics
Import pre-built Grafana dashboard:
oc apply -f k8s/monitoring/dashboards/
Dashboard Panels:
Configure alerts in OpenShift Alertmanager:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: hyper2kvm-alerts
namespace: hyper2kvm-system
spec:
groups:
- name: hyper2kvm
rules:
- alert: OperatorDown
expr: up{job="hyper2kvm-operator"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Hyper2KVM Operator is down"
Symptoms: Operator pod in CrashLoopBackOff
Debug:
# Check pod logs
oc logs -n hyper2kvm-system -l app.kubernetes.io/name=hyper2kvm-operator
# Check events
oc get events -n hyper2kvm-system --sort-by='.lastTimestamp'
# Check pod describe
oc describe pod -n hyper2kvm-system -l app.kubernetes.io/name=hyper2kvm-operator
Common Causes:
Symptoms: Worker pods stuck in CreateContainerConfigError
Debug:
# Check SCC assignment
oc get pod <worker-pod> -o yaml | grep openshift.io/scc
# List SCCs for ServiceAccount
oc describe scc hyper2kvm-worker-scc
Fix:
# Grant SCC to worker ServiceAccount
oc adm policy add-scc-to-user hyper2kvm-worker-scc \
-z hyper2kvm-worker \
-n hyper2kvm-workers
Symptoms: Cannot access metrics route
Debug:
# Check route
oc get route -n hyper2kvm-system
# Check route status
oc describe route hyper2kvm-operator-metrics -n hyper2kvm-system
# Check router logs
oc logs -n openshift-ingress -l app=router
Fix:
# Recreate route
oc delete route hyper2kvm-operator-metrics -n hyper2kvm-system
oc apply -f helm/hyper2kvm-operator/templates/openshift-route.yaml
Symptoms: Admission webhook failing with TLS errors
Debug:
# Check webhook configuration
oc get validatingwebhookconfiguration,mutatingwebhookconfiguration | grep hyper2kvm
# Check certificate secret
oc get secret -n hyper2kvm-system | grep webhook-certs
Fix:
# Regenerate certificates
./scripts/generate-webhook-certs.sh hyper2kvm-system hyper2kvm-webhook
# Get all hyper2kvm resources
oc get all -n hyper2kvm-system -l app.kubernetes.io/part-of=hyper2kvm
# Check MigrationJobs
oc get migrationjobs --all-namespaces
# Describe specific job
oc describe migrationjob <job-name> -n <namespace>
# Check worker registry
oc logs -n hyper2kvm-system -l app.kubernetes.io/component=operator | grep "Worker registered"
# Check leader election
oc get lease -n hyper2kvm-system
Automatic Upgrades (if enabled):
# Check current version
oc get csv -n hyper2kvm-system
# Check available updates
oc get subscription hyper2kvm-operator -n hyper2kvm-system -o yaml
Manual Upgrades:
# Update Helm repo
helm repo update
# Check available versions
helm search repo hyper2kvm/hyper2kvm-operator --versions
# Upgrade to latest
helm upgrade hyper2kvm-operator hyper2kvm/hyper2kvm-operator \
--namespace hyper2kvm-system \
--values values-openshift.yaml
# Rollback if needed
helm rollback hyper2kvm-operator -n hyper2kvm-system
Breaking Changes:
Migration Steps:
oc get migrationjobs --all-namespaces -o yaml > migrationjobs-backup.yaml
oc get crd migrationjobs.hyper2kvm.io -o yaml
Cleanup CRDs (optional - deletes all jobs!):
oc delete crd migrationjobs.hyper2kvm.io
oc delete crd jobtemplates.hyper2kvm.io
# Uninstall operator
helm uninstall hyper2kvm-operator -n hyper2kvm-system
# Delete namespace
oc delete project hyper2kvm-system
# Delete CRDs (optional)
oc delete crd migrationjobs.hyper2kvm.io jobtemplates.hyper2kvm.io
# Delete operator deployment
oc delete -f k8s/operator/
# Delete CRDs
oc delete -f k8s/operator/crds/
# Delete SCC
oc delete scc hyper2kvm-worker-scc
# Delete namespace
oc delete project hyper2kvm-system
Support: https://github.com/ssahani/hyper2kvm/issues License: MIT