Deploy vCluster in an air-gapped environment
This feature is an Enterprise feature. See our pricing plans or contact our sales team for more information.
This document explains how to deploy vCluster in environments without internet access, known as air-gapped environments.
Prerequisites​
- OCI-compliant private registry with a
/charts
folder - A private registry accessible to both the Kubernetes host cluster and a separate, internet-connected machine. - An offline license key for vCluster - A LoftLabs license key is required to enable enterprise features.
info
Contact sales@loft.sh to purchase an offline license key or request a trial license key for offline use.
Overview​
When deploying vCluster, there are artifacts that are typically accessed using an internet connection, but without access to internet, these artifacts need to be available to the Kubernetes cluster through a private registry:
- vCluster Helm chart—Typically retrieved from the LoftLabs Helm chart repository.
- Container images referenced in the Helm chart—Usually pulled from various public container registries.
After populating your private registry with the artifacts, you'll create the configuration file (vcluster.yaml
) of your vCluster. Finally, you'll prep your host cluster to deploy your vCluster.
When using virtual clusters in air-gapped environments, the
config.experimental.deploy.vcluster.helm
configuration setting does not work with external Helm repositories since they cannot be accessed. This means custom Helm charts from repositories like charts.bitnami.com
cannot be used for virtual cluster deployments.
Populate images to a private registry​
Each vCluster release includes multiple assets to help you upload the images to your private registry.
vcluster-images.txt
- The images to run vCluster, which includes multiple Kubernetes versions and distributions.download-images.sh
- A bash script that quickly iterates over all the images files to pull them and package them into a tarball to a machine that has internet access.push-images.sh
- A bash script that takes the tarball generated from the download script to push them to your private registry.
Prerequisites​
- Access to the internet
- Ability to push to your OCI-compliant private registry
- Logged in to GitHub Container Registry
wget
installeddocker
installed
Pull and push images​
Set environment variables for the version of vCluster that you want to deploy and the private registry.
Export environment variablesexport VCLUSTER_VERSION=0.24.0 # Replace with the desired version
export REGISTRY=ecr.io/myteam # This should be a prefix; do not include any image pathsDownload the assets from the vCluster GitHub release and make the scripts executable.
The
vcluster-images.txt
file contain multiple Kubernetes versions and distributions. You can edit the file and remove the images for any unwanted Kubernetes versions and distributions.Download assets and prepare scriptswget https://github.com/loft-sh/vcluster/releases/download/v"${VCLUSTER_VERSION}"/images.txt
wget https://github.com/loft-sh/vcluster/releases/download/v"${VCLUSTER_VERSION}"/download-images.sh
wget https://github.com/loft-sh/vcluster/releases/download/v"${VCLUSTER_VERSION}"/push-images.sh
chmod +x ./download-images.sh
chmod +x ./push-images.shRun
download-images.sh
to pull all images and create a tarball of the images.Review the output to confirm all images were pulled successfully and packaged in the tarball.
Download and package images./download-images.sh --image-list vcluster-images.txt
Run
push-images.sh
to upload all required images to your private registry.When pushing images into your private registry, the public private registry is removed and only the repository and image name are pushed. This allows vCluster to set your private registry to use for all images used in deploying vCluster.
Push images to private registry./push-images.sh --registry ${REGISTRY}
Populate the vCluster Helm chart to a private registry​
You need to push the vCluster Helm chart to your OCI-compliant private registry.
Prerequisites​
- Access to the internet
- Ability to push to your OCI-compliant private registry
helm
installed: Helm v3.10+
Pull and push the vCluster Helm chart​
Optional: if you haven’t already set the environment variables, set them now before continuing.
The private registry assumes having a
/charts
folder, which is where to push all the Helm charts.Export environment variablesexport VCLUSTER_VERSION=0.24.0 # Replace with the desired version
export REGISTRY=ecr.io/myteam # A charts folder is expectedPull the vCluster Helm chart and push it into your private registry with the OCI protocol.
Pull and push the Helm chart to your private registryhelm pull vcluster --repo https://charts.loft.sh --version ${VCLUSTER_VERSION}
helm push vcluster-${VCLUSTER_VERSION}.tgz oci://${REGISTRY}/charts
Configure vCluster​
The vcluster.yaml
file contains all configuration settings for your vCluster deployment.
Use a private registry without credentials
Set the default private registry that doesn't have authentication.
controlPlane:
advanced:
defaultImageRegistry: ecr.io/myteam # Replace with your private registry
Use an authenticated private registry
For registries that require authentication, create a Kubernetes secret in the namespace where you deploy the vCluster. Assign the secret as an image pull secret for the vCluster control plane to access required images.
Optionally, you can use the same image pull secret for workloads inside the vCluster that pull from the same registry.
controlPlane:
advanced:
defaultImageRegistry: ecr.io/myteam # Replace with your private image registry
serviceAccount:
imagePullSecrets: # Uses credentials for the vCluster control plane
- name: registry-credentials-secret-name # Replace with the name of the secret deployed on the host cluster of where the vCluster is deployed
workloadServiceAccount: # Uses credentials for any workloads created in the vCluster
imagePullSecrets:
- name: registry-credentials-secret-name # Replace with the name of the secret deployed on the host cluster of where your vCluster is deployed
Replace the alpine image
If you use the sync.toHost.pods.rewriteHosts
feature, manually replace the full path of the alpine image with your private registry path.
The defaultImageRegistry
setting does not apply to this image.
sync:
toHost:
pods:
rewriteHosts:
initContainer:
image: your-registry/library/alpine:3.20
Enable enterprise features with the license key
The apiKey
is required to reference the license key to enable enterprise features in vCluster.
Although the config appears similar to when connecting a virtual cluster to the platform, the apiKey
secret's actual value is your air-gapped license key.
external:
platform:
apiKey:
# The air-gapped license key provided by Loft has to be the data
# under the first key (name does not matter) of the secret.
secretName:
# Namespace to search for the secret. If undefined,
# it searches the namespace that the vCluster is deployed in.
# If different than the namespace of the vCluster deployment,
# then vCluster needs access to that namespace.
namespace:
# Default enabled to create the necessary RBAC roles
# and role bindings in order to find the secret
createRBAC: true
Deploy vCluster​
Prerequisites​
- The machine that is running the install commands must have access to pull the Helm chart from the private registry.
- The host cluster where the vCluster is being deployed on must have access to pull images from the private registry.
-
Administrator access to a Kubernetes cluster: See Accessing Clusters with kubectl for more information. Your current kube-context must have administrative privileges, which you can verify with
kubectl auth can-i create clusterrole -A
infoTo obtain a kube-context with admin access, ensure you have the necessary credentials and permissions for your Kubernetes cluster. This typically involves using
kubectl config
commands or authenticating through your cloud provider's CLI tools. -
helm
installed: Helm v3.10 is required for deploying the platform. Refer to the Helm Installation Guide if you need to install it. -
kubectl
installed: Kubernetes command-line tool for interacting with the cluster. See Install and Set Up kubectl for installation instructions.
Set up the host cluster and deploy​
On the host cluster, create the namespace for the vCluster, where the secrets and vCluster control plane pod are to be deployed in.
Create vCluster namespaceexport VCLUSTER_NAMESPACE=vcluster-my-vcluster # Replace with the name of the namespace you want to deploy your vCluster into
kubectl create namespace ${VCLUSTER_NAMESPACE}Create the secret to validate the license.
Create a Kubernetes secret using the LoftLabs license key in the namespace where you deploy the vCluster.
noteThe license secret is already base64-encoded.
Create a Kubernetes secret for license Key# Set the license key as an environment variable (already base64 encoded)
export VCLUSTER_LICENSE_KEY="YOUR_BASE64_ENCODED_LICENSE_KEY_HERE"
# Create secret
kubectl create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: vcluster-platform-license-key
namespace: ${VCLUSTER_NAMESPACE}
type: Opaque
data:
license: ${VCLUSTER_LICENSE_KEY}
EOFOptional: Create a secret to authenticate to your private registry.
If your private registry requires authentication, create a Kubernetes secret that stores your login credentials. Place this secret in the same namespace where the vCluster is deployed so the control plane can pull the required container images.
Create Kubernetes secret for login credentialskubectl create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: registry-credentials-secret-name
namespace: ${VCLUSTER_NAMESPACE}
type: Opaque
data:
# Credentials based on your private registry
EOFReview your
vcluster.yaml
file.vcluster.yaml configurationcontrolPlane:
advanced:
defaultImageRegistry: ecr.io/myteam # Replace with your private image registry
serviceAccount:
imagePullSecrets:
- name: registry-credentials-secret-name # Replace with the name of the registry credentials secret
workloadServiceAccount:
imagePullSecrets:
- name: registry-credentials-secret-name # Replace with the name of the registry credentials secret
external:
platform:
apiKey:
secretName: vcluster-platform-license-keyDeploy vCluster into the namespace where you deployed the secrets.
Deploy vCluster with Helmexport VCLUSTER_VERSION=0.24.0 # Replace with the chart version that was pushed into your private registry
export REGISTRY=myecr.io/team # Replace with the private registry
export VCLUSTER_NAME="my-vcluster" # Replace with what you want to name your vCluster
helm upgrade --install "${VCLUSTER_NAME}" oci://${REGISTRY}/charts/vcluster:${VCLUSTER_VERSION} \
--version ${VCLUSTER_VERSION} \
--values vcluster.yaml \
--namespace ${VCLUSTER_NAMESPACE}
Air-gapped vCluster with FIPS images​
To run vCluster in a FIPS-compliant environment, you must push FIPS-compliant images to your private registry.
Push the following images, using the appropriate Kubernetes version as the tag.
Tags are listed in the images.txt
and images-optional.txt
files.
ghcr.io/loft-sh/vcluster-pro-fips
ghcr.io/loft-sh/kubernetes-fips
The steps for pulling, tagging, and pushing these images are the same as for standard images. The only difference is that you reference the FIPS-compliant images instead.
For more details on FIPS, refer to the FIPS configuration guide.
The following is an example vcluster.yaml
configuration with the FIPS compliant images.
FIPS configuration
controlPlane:
advanced:
defaultImageRegistry: ghcr.io
virtualScheduler:
enabled: true
backingStore:
etcd:
embedded:
enabled: true
coredns:
embedded: true
distro:
k8s: # FIPS support is only available for the k8s distribution
version: v1.28.14
enabled: true
apiServer:
image:
repository: loft-sh/kubernetes-fips
controllerManager:
image:
repository: loft-sh/kubernetes-fips
scheduler:
image:
repository: loft-sh/kubernetes-fips
hostPathMapper:
enabled: true
statefulSet:
image:
repository: loft-sh/vcluster-pro-fips
resources:
limits:
cpu: 2
memory: 4Gi
requests:
cpu: 0
memory: 0
scheduling:
podManagementPolicy: OrderedReady
external:
platform:
apiKey:
secretName: license
policies:
limitRange:
enabled: false
podSecurityStandard: privileged
resourceQuota:
enabled: false
pro: true
external:
platform:
apiKey:
secretName: vcluster-platform-api-key