Documentation Index
Fetch the complete documentation index at: https://mintlify.com/loft-sh/vcluster/llms.txt
Use this file to discover all available pages before exploring further.
In addition to native Kubernetes resources, vCluster can sync Custom Resources (CRs) between the virtual and host clusters. This is essential when using operators or custom controllers that extend Kubernetes functionality.
Overview
vCluster supports syncing custom resources through two mechanisms:
- Built-in integrations for popular operators (cert-manager, ExternalSecrets, Istio, KubeVirt)
- Generic custom resource syncing via plugins or experimental proxy feature
Built-in Integrations
vCluster includes native support for several popular CRD ecosystems.
External Secrets Operator
Reuses a host cluster’s External Secrets Operator installation:
integrations:
externalSecrets:
enabled: true
webhook:
enabled: false
sync:
toHost:
externalSecrets:
selector:
matchLabels: {}
stores:
enabled: false
selector:
matchLabels: {}
fromHost:
clusterStores:
enabled: false
selector:
matchLabels: {}
What gets synced:
ExternalSecrets → Virtual to Host (with label selector)
SecretStores → Virtual to Host, then bidirectional (optional)
ClusterSecretStores → Host to Virtual (optional)
Example configuration:
integrations:
externalSecrets:
enabled: true
webhook:
enabled: true # Reuse host webhooks
sync:
toHost:
externalSecrets:
selector:
matchLabels:
sync: "true" # Only sync labeled ExternalSecrets
fromHost:
clusterStores:
enabled: true # Import ClusterSecretStores
Cert-Manager
Reuses a host cluster’s cert-manager installation:
integrations:
certManager:
enabled: true
sync:
toHost:
certificates:
enabled: true
issuers:
enabled: true
fromHost:
clusterIssuers:
enabled: true
selector:
labels: {}
What gets synced:
Certificates → Virtual to Host
Issuers → Virtual to Host
ClusterIssuers → Host to Virtual (read-only)
Example configuration:
integrations:
certManager:
enabled: true
sync:
toHost:
certificates:
enabled: true
issuers:
enabled: true
fromHost:
clusterIssuers:
enabled: true
selector:
labels:
vcluster-accessible: "true"
Istio
Syncs Istio resources from virtual to host:
integrations:
istio:
enabled: true
sync:
toHost:
destinationRules:
enabled: true
gateways:
enabled: true
virtualServices:
enabled: true
What gets synced:
DestinationRules → Virtual to Host
Gateways → Virtual to Host
VirtualServices → Virtual to Host
KubeVirt
Reuses a host cluster’s KubeVirt installation:
integrations:
kubeVirt:
enabled: true
webhook:
enabled: true
sync:
virtualMachines:
enabled: true
virtualMachineInstances:
enabled: true
virtualMachinePools:
enabled: true
virtualMachineClones:
enabled: true
virtualMachineInstanceMigrations:
enabled: true
dataVolumes:
enabled: false
Generic Custom Resource Syncing
For custom resources not covered by built-in integrations, you have two options:
Option 1: Experimental Proxy Feature
The experimental proxy feature allows syncing arbitrary custom resources:
experimental:
proxy:
customResources:
# Format: "kind.apiGroup/version"
"MyCRD.example.com/v1":
enabled: true
direction: toHost # or fromHost, or bidirectional
Note: This feature is experimental and may change in future versions.
Option 2: vCluster Plugins
vCluster plugins provide the most flexible way to sync custom resources. Plugins are external binaries that extend vCluster’s syncing capabilities.
Plugin configuration:
plugins:
my-plugin:
image: my-registry/vcluster-plugin:latest
# Plugin-specific configuration
config:
# ...
Creating a plugin:
Plugins must implement the vCluster plugin SDK. See the vCluster SDK documentation for details on building plugins.
Syncing Architecture
Generic Syncer Pattern
Custom resource syncing follows the same pattern as native resources. Each syncer implements the Syncer interface (pkg/syncer/types/syncer.go:20):
type Syncer interface {
Object
synccontext.Mapper
Syncer() Sync[client.Object]
}
type Sync[T client.Object] interface {
SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[T]) (ctrl.Result, error)
Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[T]) (ctrl.Result, error)
SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[T]) (ctrl.Result, error)
}
Name Translation
Custom resources synced to the host cluster use the same name translation as native resources:
Virtual: my-certificate (namespace: default)
Host: my-vcluster-default-my-certificate-x-default-x-my-vcluster
Annotations track the relationship:
annotations:
vcluster.loft.sh/name: my-certificate
vcluster.loft.sh/namespace: default
vcluster.loft.sh/uid: "abc123..."
vcluster.loft.sh/kind: "certificates.cert-manager.io/v1"
Configuration Examples
Complete Cert-Manager Setup
integrations:
certManager:
enabled: true
sync:
toHost:
certificates:
enabled: true
issuers:
enabled: true
fromHost:
clusterIssuers:
enabled: true
selector:
labels:
# Only import ClusterIssuers with this label
vcluster.loft.sh/allowed: "true"
Usage in virtual cluster:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-app-tls
namespace: default
spec:
secretName: my-app-tls
issuerRef:
name: letsencrypt-prod # ClusterIssuer from host
kind: ClusterIssuer
dnsNames:
- my-app.example.com
Complete ExternalSecrets Setup
integrations:
externalSecrets:
enabled: true
webhook:
enabled: true
sync:
toHost:
externalSecrets:
selector:
matchLabels:
sync-to-host: "true"
stores:
enabled: true
selector:
matchLabels: {}
fromHost:
clusterStores:
enabled: true
selector:
matchLabels: {}
Usage in virtual cluster:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-secret
namespace: default
labels:
sync-to-host: "true" # Required for sync
spec:
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: my-app-secret
data:
- secretKey: api-key
remoteRef:
key: /secret/data/api-key
Istio Service Mesh Setup
integrations:
istio:
enabled: true
sync:
toHost:
destinationRules:
enabled: true
gateways:
enabled: true
virtualServices:
enabled: true
Usage in virtual cluster:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-service
namespace: default
spec:
hosts:
- my-service.example.com
gateways:
- my-gateway
http:
- route:
- destination:
host: my-service
port:
number: 80
Requirements
CRDs Must Exist in Host Cluster
For custom resource syncing to work, the CRDs must be installed in the host cluster. vCluster does not install CRDs automatically.
Example: Installing cert-manager CRDs in host cluster:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.crds.yaml
RBAC Permissions
vCluster needs appropriate RBAC permissions to read and write custom resources. These permissions are typically added automatically when using built-in integrations.
Manual RBAC configuration (if needed):
rbac:
clusterRole:
enabled: true
extraRules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates", "issuers"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]
- apiGroups: ["cert-manager.io"]
resources: ["clusterissuers"]
verbs: ["get", "list", "watch"]
Troubleshooting
Custom Resources Not Syncing
-
Verify integration is enabled:
helm get values my-vcluster -n vcluster-my-vcluster | grep -A 10 integrations
-
Check CRDs exist in host cluster:
kubectl get crd certificates.cert-manager.io
-
Verify RBAC permissions:
kubectl get clusterrole vc-my-vcluster -o yaml
-
Check vCluster logs:
kubectl logs -n vcluster-my-vcluster deploy/my-vcluster -f | grep -i certificate
Webhooks Not Working
If using custom resource webhooks:
-
Enable webhook integration:
integrations:
externalSecrets:
webhook:
enabled: true
-
Verify webhook service exists:
kubectl get svc -A | grep webhook
-
Check ValidatingWebhookConfiguration:
kubectl get validatingwebhookconfiguration
Label Selectors Not Matching
When using label selectors, ensure resources have the required labels:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-cert
labels:
sync-to-host: "true" # Must match selector
Advanced Configuration
Selective Syncing with Labels
Use label selectors to control which resources sync:
integrations:
certManager:
enabled: true
sync:
fromHost:
clusterIssuers:
enabled: true
selector:
labels:
environment: production
vcluster-allowed: "true"
Bidirectional Syncing
Some resources support bidirectional syncing (e.g., SecretStores):
integrations:
externalSecrets:
enabled: true
sync:
toHost:
stores:
enabled: true # Sync to host, then sync status back
Best Practices
- Install CRDs first: Ensure CRDs exist in the host cluster before enabling syncing
- Use label selectors: Control which resources sync to avoid conflicts
- Start with read-only: Import ClusterIssuers/ClusterStores before syncing user resources
- Monitor RBAC: Ensure vCluster has necessary permissions
- Test thoroughly: Validate custom resource syncing in development before production
- Document dependencies: Keep track of which operators are required in the host cluster
Limitations
- CRDs must pre-exist: vCluster doesn’t install CRDs in the host cluster
- No CRD syncing: The CRD definitions themselves are not synced
- Webhook complexity: Some webhooks may require additional configuration
- Version compatibility: Ensure CRD versions match between virtual and host clusters
- Cluster-scoped resources: Limited support for cluster-scoped custom resources
Next Steps