Ingresses
By default, this is disabled.
When enabled, sync all Ingress resources from the tenant cluster to the control plane cluster. Use this option to make a tenant cluster service available using a hostname/domain without having to configure DNS for each tenant cluster. This requires a compatible Ingress controller running on the control plane cluster, and a single shared controller can reconcile Ingress resources synced from multiple tenant clusters.
vCluster preserves a tenant's spec.ingressClassName unchanged, so a dedicated per-tenant IngressClass alone doesn't isolate tenants. A tenant can still name another tenant's class. Isolate tenants one of two ways:
- Namespace-scoped controller. Run a controller instance per tenant that only watches that tenant's own host namespace. This works regardless of which class a tenant names.
- Enforced class selection. Use
sync.fromHost.ingressClasseswith a selector, paired with control plane cluster admission. The selector alone only helps partially, since it skips the check whenspec.ingressClassNameis empty or when a tenant uses the legacykubernetes.io/ingress.classannotation. Admission needs to cover both paths, plus any classless Ingress that would fall through to a default class.
vCluster syncs a tenant's spec.rules[].host unchanged. It doesn't rewrite or scope the hostname to that tenant. If tenant clusters share a control plane cluster ingress controller, a tenant can claim a hostname belonging to another tenant or to platform infrastructure. The controller's own conflict-resolution behavior decides which rule wins, not vCluster. See Ingress and Gateway API hostname claims in the shared-node hardening guide.
For tenant traffic served by a Gateway controller on the control plane cluster, Gateway API sync is the modern alternative. It syncs Gateway, HTTPRoute, TLSRoute, ReferenceGrant, and BackendTLSPolicy, and lets tenants import host GatewayClass resources via sync.fromHost.gatewayClasses. Ingress sync remains supported for workloads that still depend on networking.k8s.io/v1 Ingress resources.
When enabled, vCluster automatically tries to detect the supported ingress version (networking.k8s.io/v1 or networking.k8s.io/v1beta1).
Sync Ingresses from the tenant to control plane cluster
sync:
toHost:
ingresses:
enabled: true
Admission webhook rejects synced Ingress
During an ingress-nginx Helm upgrade on the control plane cluster, the chart applies the ValidatingWebhookConfiguration with no caBundle set. A post-upgrade job then patches the caBundle onto it using the webhook's certificate secret. If the upgrade is interrupted before that job completes, the webhook config is left with an empty caBundle.
When vCluster then creates a synced Ingress on the control plane cluster, the webhook rejects it, returning tls: failed to verify certificate: x509: certificate signed by unknown authority. From the tenant's side, the Ingress exists but never appears on the control plane cluster. The syncer log shows the TLS rejection against the translated Ingress name.
Two ways to work around it:
- For debugging only, set
controller.admissionWebhooks.enabled: falseon the ingress-nginx chart. This disables admission validation. The controller still routes traffic. - For a lasting fix, set
controller.admissionWebhooks.certManager.enabled: trueso cert-manager manages thecaBundleinstead of the chart's Helm hook jobs. This requires cert-manager already installed in the cluster, and removes the race entirely.
This is an ingress-nginx webhook lifecycle issue, not a vCluster sync defect, and one more reason to plan a move to Gateway API sync.
Patches
Use sync.toHost.ingresses.patches to transform Ingress fields, such as spec.rules[*].host, while syncing to the control plane cluster. See Patching synced resources for syntax, directionality, and examples.
Config reference
ingresses object
Ingresses defines if ingresses created within the virtual cluster should get synced to the host cluster.
ingresses object enabled boolean false
Enabled defines if this option should be enabled.
enabled boolean false patches object[]
Patches patch the resource according to the provided specification.
patches object[] path required string
Path is the path within the patch to target. If the path is not found within the patch, the patch is not applied.
path required string expression string
Expression transforms the value according to the given JavaScript expression.
expression string reverseExpression string
ReverseExpression transforms the value according to the given JavaScript expression.
reverseExpression string reference object
Reference treats the path value as a reference to another object and will rewrite it based on the chosen mode
automatically. In single-namespace mode this will translate the name to "vxxxxxxxxx" to avoid conflicts with
other names, in multi-namespace mode this will not translate the name.
reference object apiVersion required string
APIVersion is the apiVersion of the referenced object.
apiVersion required string apiVersionPath string
APIVersionPath is optional relative path to use to determine the kind. If APIVersionPath is not found, will fallback to apiVersion.
apiVersionPath string kind required string
Kind is the kind of the referenced object.
kind required string kindPath string
KindPath is the optional relative path to use to determine the kind. If KindPath is not found, will fallback to kind.
kindPath string namePath string
NamePath is the optional relative path to the reference name within the object.
namePath string namespacePath string
NamespacePath is the optional relative path to the reference namespace within the object. If omitted or not found, namespacePath equals to the
metadata.namespace path of the object.
namespacePath string labels object
Labels treats the path value as a labels selector.
labels object