Migrate to the vCluster Rancher operator
The built-in Rancher integration was removed in vCluster Platform v4.9.0. This migration guide walks you through moving your existing tenant clusters from the built-in Rancher integration to the vCluster Rancher operator, the supported replacement.
If you've upgraded to v4.9.0 or later and had tenant clusters with the Rancher integration enabled, those clusters are stuck in Terminating when you try to delete them. See the upgrade guide to resolve this before proceeding.
If you're on v4.8 or lower, use the v4.8 migration guide, which includes additional steps for disabling the integration at the platform level before cleaning up individual tenant clusters. Alternatively, upgrade to v4.9.0 first and then follow this guide.
Before you begin​
This guide requires kubectl access to the control plane cluster with vCluster Platform installed.
Step 1 connects to individual tenant clusters using vcluster connect. You don't need a direct kubeconfig for each tenant cluster.
Work through the steps in order. Step 1 cleans up each tenant cluster. Step 2 removes the corresponding cluster entries from Rancher. Step 3 installs the replacement operator on the control plane cluster. If you upgraded from v4.8 or lower, complete the cleanup section at the end before using the new operator.
Step 1: Clean up each tenant cluster​
Complete both sub-steps on one tenant cluster before moving to the next. Repeat for every tenant cluster that had the integration enabled.
Connect to the tenant cluster and delete the
cattle-systemnamespace. This removes the Rancher cluster agent and all Rancher-related workloads that were injected into the tenant cluster.Modify the following with your specific values to generate a copyable command:vcluster connect my-tenant-cluster -n p-my-project
kubectl delete namespace cattle-system --ignore-not-foundRemove the cluster-level RBAC resources that Rancher created:
# List what will be removed — verify before deleting
kubectl get clusterrole,clusterrolebinding | grep cattle
# Remove them
kubectl delete clusterrole,clusterrolebinding \
$(kubectl get clusterrole,clusterrolebinding \
--no-headers -o custom-columns=":metadata.name" \
| grep cattle) \
--ignore-not-found
Step 2: Delete the Rancher cluster entries​
Each tenant cluster imported into Rancher has a corresponding cluster entry. Before deleting, verify that the cluster shows as Unavailable or Disconnected in the Rancher UI. This confirms the agent has been removed and Rancher has lost contact with the cluster. Don't delete the entry if it still shows as Active. This may indicate the cattle-system namespace wasn't fully removed in the previous step.
Once the cluster shows as Disconnected, go to Cluster Management in the Rancher UI, find each tenant cluster entry, and delete it. If a deletion hangs, Rancher force-removes the entry once it confirms the agent is gone.
Step 3: Install the vCluster Rancher operator​
With the old integration fully removed, install the new vCluster Rancher operator on the control plane cluster. The operator runs independently of vCluster Platform and manages tenant cluster registration with Rancher directly. Follow the installation guide for full setup instructions.
Clean up stale Platform state​
If you upgraded from v4.8 or lower, your tenant clusters and projects carry stale metadata from the old integration. Complete this cleanup before using the new operator.
Remove the import label from tenant clusters:
kubectl get virtualclusterinstances -A \
-o json | jq -r '
.items[]
| select(.metadata.labels["loft.sh/import-rancher"] == "true")
| "\(.metadata.namespace) \(.metadata.name)"
' | while read ns name; do
kubectl label virtualclusterinstance "$name" -n "$ns" loft.sh/import-rancher-
done
Remove stale Rancher conditions from projects:
kubectl get projects.management.loft.sh -o json | jq -r '
.items[]
| select(
.status.conditions[]?
| select(.type == "RancherIntegrationSynced")
)
| .metadata.name
' | while read project; do
idx=$(kubectl get project.management.loft.sh "$project" -o json | jq '
.status.conditions | to_entries[]
| select(.value.type == "RancherIntegrationSynced")
| .key')
kubectl patch project.management.loft.sh "$project" \
--type=json --subresource=status \
-p="[{\"op\":\"remove\",\"path\":\"/status/conditions/${idx}\"}]"
done