Air-Gapped Installation of Apache Spark on Kubernetes
Vous trouverez ci-dessous un guide étape par étape pour l’installation ilum dans un environnement hors ligne (air-gaped). Ce guide est conçu pour être indépendant de votre distribution Kubernetes et couvre les deux approches de gestion des images de conteneur : à l’aide de conteneurd (avec le Ctr outil) ou Docker . Les instructions supposent que vous avez :
- Un poste de travail connecté à Internet pour télécharger le graphique Helm et les images de conteneur requis.
- Méthode (telle qu’une clé USB ou un serveur de fichiers interne) pour transférer des fichiers du poste de travail en ligne vers votre environnement hors ligne.
- Un cluster Kubernetes fonctionnel (n’importe quelle distribution) dans votre environnement hors ligne.
- Helm installé et configuré pour se connecter à votre cluster hors connexion.
- Sufficient Disk Space: At least 60GB free on both the download and offline machines (for handling large image tarballs).
- Recommended Resources: 12 CPU and 18GB RAM (or more depending on workload).
Architecture Overview: Spark on Kubernetes in Air-Gapped Environments
When deploying Apache Spark on Kubernetes in an air-gapped environment, the driver and executor processes run as containerized processes 100% managed within infrastructure devoid of public connectivity. All container images and dependencies, along with configuration files, are hosted internally and do not need external network access.
In this environment, we deploy Spark components as containerized applications on Kubernetes. Spark driver and executors operate as pods. Scheduling, resource allocation, and scaling are handled by Kubernetes. The setup uses native Kubernetes features like resource limits, Horizontal Pod Autoscaling, and node selectors for smooth and reliable functioning. For general details on how Ilum manages these resources, see the Architecture Overview.
Un local image registry is a key part of this architecture. Instead of manually loading images on every node, you push them into a registry within your infrastructure. Whether using a basic deployment with registre :2 or a robust solution like Harbor, the registry must be backed by persistent storage to retain images after restarts. Once images are in the registry, individual nodes can pull them on demand.
Networking and security are critical. Air-gapped environments use network policies to control pod communication. These policies limit interactions to necessary components using Kubernetes' security controls (RBAC, service accounts), ensuring compliance with strict no-ingress rules.
This structure supports complex jobs including Spark Core, Spark SQL, Spark Streaming, and MLlib applications. Integrated with tools like kubectl , Helm, Prometheus, and Grafana, this setup makes deployment, monitoring, and debugging efficient even without internet access. You can run jobs via REST API ou Spark Submit once the cluster is operational.
1. Preparation and Downloads
Le processus se décompose en plusieurs étapes :
1.1. Download Ilum Helm Chart for Offline Use
Le graphique Ilum est fourni via un dépôt Helm public, exécutez :
helm repo add ilum https://charts.ilum.cloud
Mise à jour du référentiel Helm
helm pull ilum/ilum #(vous pouvez ajouter --version <desired_version> pour spécifier une version d’ilum)
Cela créera un fichier ilum-<version>.tgz .
Pourboire: Vous pouvez extraire et modifier le
valeurs.yamlplus tard si vous souhaitez modifier les références du référentiel d’images.
1.2. Identify and Download Required Docker Images
Below is the list of images(version 6.6.1 of ilum):
Click to view required images list
alpine/kubectl:1.34.1apache/airflow:3.0.2apache/nifi:2.5.0apache/superset :dockerizebitnamilegacy/postgresql:16bitnami/git:latestcurlimages/curl :8.5.0docker.io/bitnamilegacy/minio:2025.3.12-debian-12-r0docker.io/bitnamilegacy/os-shell:11-debian-11-r72docker.io/bitnamilegacy/postgresql:16.1.0-debian-11-r25docker.io/bitnamilegacy/redis:7.0.10-debian-11-r4docker.io/ilum/mongodb:6.0.5ghcr.io/projectnessie/nessie:0.105.1gitea/gitea :1.22.3ilum/airflow:3.1.1ilum/core:6.6.1Ilum/Ruche :3.1.3ilum/kyuubi :1.10.0-étincelleilum/mageai:0.9.76ilum/mongodb :6.0.5ilum/spark:3.5.7-deltailum/lance-étincelles :spark-3.5.3ilum/sparkmagic:0.23.3ilum/streamlit-example:1.0.0ilum/superset:4.1.0.1ilum/ui:6.6.1jpgouin/openldap:2.6.9-fixminio/mc:RELEASE.2025-04-16T18-13-26Zregistry.k8s.io/git-sync/git-sync:v4.3.0trinodb/trino:477
1.3. Enregistrez chaque image en tant qu’archive tar
Vous pouvez scripter ce processus. Par exemple, créez un fichier nommé pull_and_save.sh :
# !/bin/bash
IMAGES=(
"alpine/kubectl:1.34.1"
"apache/airflow:3.0.2"
"apache/nifi:2.5.0"
« apache/superset :dockerize »
"bitnamilegacy/postgresql:16"
"bitnami/git:latest"
« curlimages/curl :8.5.0 »
"docker.io/bitnamilegacy/minio:2025.3.12-debian-12-r0"
"docker.io/bitnamilegacy/os-shell:11-debian-11-r72"
"docker.io/bitnamilegacy/postgresql:16.1.0-debian-11-r25"
"docker.io/bitnamilegacy/redis:7.0.10-debian-11-r4"
« docker.io/ilum/mongodb:6.0.5 »
"ghcr.io/projectnessie/nessie:0.105.1"
« gitea/gitea :1.22.3 »
"ilum/airflow:3.1.1"
"ilum/core:6.6.1"
« ilum/ruche :3.1.3 »
« ilum/kyuubi :1.10.0-étincelle »
"ilum/mageai:0.9.76"
« ilum/mongodb :6.0.5 »
"ilum/spark:3.5.7-delta"
« ilum/lance-étincelles :spark-3.5.3 »
"ilum/sparkmagic:0.23.3"
"ilum/streamlit-example:1.0.0"
"ilum/superset:4.1.0.1"
"ilum/ui:6.6.1"
"jpgouin/openldap:2.6.9-fix"
"minio/mc:RELEASE.2025-04-16T18-13-26Z"
"registry.k8s.io/git-sync/git-sync:v4.3.0"
"trinodb/trino:477"
)
pour l’image dans « ${IMAGES[@]} » ; faire
echo « Tirer $image... »
docker pull « $image »
filename=$(echo « $image » | tr '/ :' '__')
echo « Enregistrement de $image dans ${filename}.tar... »
docker save « $image » -o « ${filename}.tar »
fait
Exécutez le script :
chmod +x pull_and_save.sh
./pull_and_save.sh
Cela produit un ensemble de .goudron fichiers contenant vos images.
2. Transfert d’artefacts vers l’environnement hors ligne
Utilisez votre méthode préférée (clé USB, serveur de fichiers interne, scp, etc.) pour copier les éléments suivants de votre machine en ligne vers l’environnement hors ligne :
- Le package de cartes Helm (par exemple,
ilum-<version>.tgz) - Toutes les archives d’images (par exemple,
apache_superset_dockerize.tar,ilum_hive_3.1.3.tar, etc.)
3. Import Container Images (Docker & Containerd)
Lorsque vous utilisez un registre local, vous n’ont pas besoin pour charger les images manuellement sur chaque nœud. Au lieu de cela, vous pouvez les pousser dans votre registre local, puis tous les nœuds extrairont les images du registre si nécessaire. Vous trouverez ci-dessous des instructions pour préparer les images avant de les insérer dans votre registre.
Managing Disk Space: If you are short on disk space, consider processing images sequentially (load one, push it, then delete the tarball) instead of copying all tarballs at once.
- Option A: containerd (ctr)
- Option B: Docker
3A.1. Importer les archives de l’image (sur une machine)
Sur une machine qui peut accéder à votre registre local, importez la ou les archives :
sudo ctr -n k8s.io images import /path/to/<image_tarball>.tar
Par exemple:
sudo ctr -n k8s.io images import /opt/offline-images/ilum_hive_3.1.3.tar
3A.2. Baliser l’image pour le registre local
Balisez l’image avec le point de terminaison de votre registre local (par exemple, si votre registre est accessible à l’adresse localhost :5000 ):
sudo ctr -n k8s.io images tag ilum/hive :3.1.3 localhost :5000/ilum/hive :3.1.3
3A.3. Envoyer l’image au registre local
Poussez l’image balisée :
sudo ctr -n k8s.io images push --plain-http localhost :5000/ilum/hive :3.1.3
(Utilisation --plain-http si votre registre est configuré sans TLS.)
3B.1. Chargez l’archive de l’image (si nécessaire)
Si vous souhaitez vérifier localement avant d’appuyer (facultatif), vous pouvez charger une image sur votre machine d’administration :
docker load -i /chemin/vers/<image_tarball>.tar
Par exemple:
docker load -i /opt/offline-images/ilum_hive_3.1.3.tar
3B.2. Étiquetez l’image pour votre registre local
Balise docker ilum/hive :3.1.3 localhost :5000/ilum/hive :3.1.3
3B.3. Envoyer l’image au registre local
docker push localhost :5000/ilum/hive :3.1.3
Note: Une fois que les images se trouvent dans votre registre local, chaque nœud de votre cluster peut les extraire automatiquement si nécessaire. Il n’est pas nécessaire de précharger les images sur chaque nœud.
4. Setup Local Image Registry (Preferred)
L’utilisation d’un registre local est fortement recommandée, car elle simplifie la gestion des images et s’adapte bien aux clusters plus grands ou dynamiques. Bien que vous puissiez exécuter un registre de base à l’aide de registre :2 , envisagez des alternatives robustes telles que Port , Nexus Repository Manager ou Quay. Par exemple Port offre un contrôle d’accès basé sur les rôles, une analyse des vulnérabilités, une réplication d’images et une interface utilisateur Web conviviale.
Important: Assurez-vous que le registre que vous choisissez est configuré avec un volume persistant attaché (ou un stockage persistant). Cela garantit que vos images restent disponibles même si le conteneur de registre est redémarré ou mis à jour.
Exemple : Configuration d’un registre de base avec stockage persistant (Docker)
-
Créez un répertoire pour les données de registre :
Create Directorymkdir -p /opt/donnees-de-registre -
Exécutez le conteneur de registre avec un volume :
Start Registrydocker run -d \
-p 5000:5000 \
--name registre \
-v /opt/registry-data :/var/lib/registry \
registre :2
Exemple : Utilisation de Harbor
Pour une solution plus robuste, téléchargez le programme d’installation hors ligne de Harbor à partir du Page des versions de GitHub Harbor et suivez la documentation fournie. Harbor vous demande de configurer le stockage persistant (à l’aide de volumes) dans le cadre de son installation.
5. Configure Helm for Local Registry
Pour s’assurer que ilum extrait des images de votre registre local plutôt que de dépôts publics, mettez à jour les références du référentiel d’images dans le graphique Helm. Par exemple, si les valeurs par défaut ont :
ilum-core :
image : "ilum/core:6.6.1"
Changez-le en :
ilum-core :
image : "localhost:5000/ilum/core:6.6.1"
Vous pouvez modifier la valeur par défaut du graphique valeurs.yaml ou fournissez un fichier de remplacement. Par exemple, créez valeurs-de-registre-local.yaml :
ilum-core :
image : "localhost:5000/ilum/core:6.6.1"
ilum-ui :
image : "localhost:5000/ilum/ui:6.6.1"
# Ajoutez des remplacements similaires pour d’autres composants (par exemple, ilum/airflow, ilum/hive, etc.)
Ensuite, installez (ou mettez à niveau) à l’aide de :
helm install ilum /chemin/vers/ilum-<version>.tgz --namespace ilum --create-namespace -f valeurs-de-registre-local.yaml
6. Installer ilum à l’aide de Helm
Assurez-vous que votre kubeconfig est configuré pour votre cluster hors connexion, puis installez le graphique Helm :
helm install ilum /chemin/vers/ilum-<version>.tgz --namespace ilum --create-namespace
(Incluez le fichier de remplacement si vous en utilisez un.)
7. Vérifier et dépanner
7.1. Vérifier le déploiement
-
Vérifiez l’état de la version de Helm :
Helm Statushelm status ilum --namespace ilum -
Liste des pods :
Get Podskubectl get pods -n ilum -
Inspecter les références d’image du pod :
Par exemple:
Describe Podkubectl describe pod <pod_name> -n ilum | grep Image :Vérifiez que les chemins d’accès aux images font référence à votre registre local (par exemple,
localhost :5000/ilum/hive :3.1.3).
7.2. Dépannage
Click to view troubleshooting steps
- Erreurs ImagePullBackOff :
Vérifiez que les images sont disponibles dans le registre local et que tous les nœuds peuvent accéder au registre. - Accès au registre :
Assurez-vous que tous les paramètres de registre non sécurisés requis (si vous utilisez HTTP) sont configurés sur vos nœuds. - Stockage persistant :
Vérifiez que le répertoire de données du registre local est correctement monté afin que les images persistent lors des redémarrages du conteneur.
TLS interception with an internal CA
When an internal Certificate Authority signs outbound traffic, configure ilum-core.security.trustStoredans single mode. In addition to populating the JVM truststore, the mode mounts the CA secret into the main ilum-core container and exports SSL_CERT_FILE, CURL_CA_BUNDLEet REQUESTS_CA_BUNDLE so that native TLS code paths trust the same CA as the JVM. Refer to the corporate MITM proxy walkthrough in CA Management for a step-by-step example.
DuckDB extensions in restricted environments
Ilum images ship with the httpfs, iceberg , postgres_scanneret ducklake extensions pre-populated in DuckDB's local extension cache (~/.duckdb/extensions/), and with the hive_metastoreet duck_lineage extensions staged under /duckdbExt. The DuckDB calls used internally never reach extensions.duckdb.org. To support additional extensions in restricted environments without rebuilding the image, mount them through ilum-core.sql.duckdb.extraExtensions. Refer to DuckDB Extension Management for details.
Frequently Asked Questions (FAQ)
Can I run Apache Spark on Kubernetes without internet access?
Yes. By using an air-gapped installation method, all necessary dependencies (Docker images, Helm charts) are downloaded on an online machine, transferred to the offline environment, and hosted in a local registry.
Do I need a local image registry for air-gapped installation?
While you can technically load images manually onto every node using docker loadou ctr image import, setting up a local registry (like Harbor or the basic Docker Registry) is strongly recommended. It simplifies scaling, image management, and ensures all nodes can pull images reliably.
How do I handle Spark dependencies in an offline cluster?
For Spark jobs that require external libraries (Maven/PyPI), you must pre-download these artifacts. You can either build custom Docker images containing these libraries or host a local Maven/PyPI mirror (e.g., using Sonatype Nexus or JFrog Artifactory) inside your air-gapped network.
What is the advantage of using Ilum in an air-gapped setup?
Ilum simplifies the management of Spark on Kubernetes by providing a unified control plane. In air-gapped environments, its ability to manage interactive sessions and jobs without reaching out to external cloud services makes it an ideal orchestrator for secure, on-prem data platforms.