Air-Gapped Installation of Apache Spark on Kubernetes
Below is a step‐by‐step guide to installing ilum in an offline (air‐gapped) environment. This guide is written to be agnostic to your Kubernetes distribution and covers both approaches for managing container images—using in containerd (con il Ctr strumento) o Scaricatore. Le istruzioni presuppongono che tu abbia:
- Una workstation connessa a Internet per scaricare le immagini del diagramma Helm e del contenitore necessarie.
- Un metodo, ad esempio un'unità USB o un file server interno, per trasferire i file dalla workstation online all'ambiente offline.
- Un cluster Kubernetes funzionante (qualsiasi distribuzione) nell'ambiente offline.
- Helm installato e configurato per la connessione al cluster offline.
- 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 registro: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 o Spark Submit once the cluster is operational.
1. Preparation and Downloads
Il processo è suddiviso nei seguenti passaggi:
1.1. Download Ilum Helm Chart for Offline Use
Il grafico Ilum viene fornito tramite un repository Helm pubblico, eseguito:
helm repo Aggiungere ilum https://charts.ilum.cloud
Aggiornamento del repo Helm
helm pull ilum/ilum #(you can add --version to specify a ilum version)
Questo creerà un file ilum-.
Mancia: You can extract and modify the chart’s
valori.yamlin seguito se si desidera modificare i riferimenti del repository di immagini.
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:dockerizzarebitnamilegacy/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/alveare:3.1.3ilum/kyuubi:1.10.0-sparkilum/mageai:0.9.76ilum/mongodb:6.0.5ilum/spark:3.5.8-deltailum/lancia-scintille:scintilla-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. Salva ogni immagine come tarball
È possibile creare uno script per questo processo. Ad esempio, creare un file denominato 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/hive:3.1.3"
"ilum/kyuubi:1.10.0-spark"
"ilum/mageai:0.9.76"
"ilum/mongodb:6.0.5"
"ilum/spark:3.5.8-delta"
"ilum/spark-launcher: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"
)
per immagine in "${IMAGES[@]}"; fare
echo "Pulling $image..."
docker pull "$image"
filename=$(echo "$image" | tr '/:' '__')
echo "Saving $image A ${filename}.tar..."
docker save "$image" -o "${filename}.tar"
fatto
Esegui lo script:
chmod +x pull_and_save.sh
./pull_and_save.sh
Questo produce un insieme di .catrame file contenenti le tue immagini.
2. Trasferire gli artefatti nell'ambiente offline
Utilizzare il metodo preferito (unità USB, file server interno, scp ecc.) per copiare quanto segue dal computer online all'ambiente offline:
- Il pacchetto di carte Helm (ad esempio,
ilum-).tgz - Tutti i tarball di immagini (ad esempio,
apache_superset_dockerize.tar,ilum_hive_3.1.3.tar, ecc.)
3. Import Container Images (Docker & Containerd)
Quando si utilizza un registro locale, è possibile don’t need per caricare manualmente le immagini su ogni nodo. Al contrario, è possibile inserirli nel registro locale e quindi tutti i nodi estrarranno le immagini dal registro in base alle esigenze. Di seguito sono riportate le istruzioni per preparare le immagini prima di inserirle nel registro.
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. Importare i tarball di immagini (su una macchina)
Su una macchina che può accedere al registro locale, importare i tarball:
sudo Ctr -n k8s.io images importazione /path/to/<image_tarball>.catrame
Per esempio:
sudo Ctr -n k8s.io images importazione /opt/offline-images/ilum_hive_3.1.3.tar
3A.2. Contrassegnare l'immagine per il registro locale
Tag the image with your local registry’s endpoint (for example, if your registry is accessible at localhost:5000):
sudo Ctr -n k8s.io images tag ilum/hive:3.1.3 localhost:5000/ilum/hive:3.1.3
3A.3. Inviare l'immagine al registro locale
Spingere l'immagine con tag:
sudo Ctr -n k8s.io images push --plain-http localhost:5000/ilum/hive:3.1.3
(Utilizzare --plain-http se il registro è configurato senza TLS.)
3B.1. Caricare l'archivio immagini (se necessario)
Se si desidera eseguire la verifica localmente prima di eseguire il push (facoltativo), è possibile caricare un'immagine sul computer di amministrazione:
docker load -i /path/to/<image_tarball>.catrame
Per esempio:
docker load -i /opt/offline-images/ilum_hive_3.1.3.tar
3B.2. Contrassegnare l'immagine per il registro locale
docker tag ilum/hive:3.1.3 localhost:5000/ilum/hive:3.1.3
3B.3. Inviare l'immagine al registro locale
docker push localhost:5000/ilum/hive:3.1.3
Nota: Una volta che le immagini sono nel registro locale, ogni nodo del cluster può estrarle automaticamente quando necessario. Non è necessario precaricare le immagini su ogni nodo.
4. Setup Local Image Registry (Preferred)
L'uso di un registro locale è altamente consigliato perché semplifica la gestione delle immagini e si adatta bene a cluster più grandi o dinamici. Sebbene sia possibile eseguire un registro di base utilizzando registro:2, prendere in considerazione alternative solide come Porto, Nexus Repository Manager o Quay. Per esempio Porto offers role‑based access control, vulnerability scanning, image replication, and a user-friendly web UI.
Importante: Assicurarsi che il Registro di sistema scelto sia configurato con un volume persistente collegato (o archiviazione persistente). In questo modo si garantisce che le immagini rimangano disponibili anche se il contenitore del Registro di sistema viene riavviato o aggiornato.
Esempio: configurazione di un registro di base con archiviazione permanente (Docker)
-
Creare una directory per i dati del Registro di sistema:
Create Directorymkdir -p /opt/registry-data -
Eseguire il contenitore del Registro di sistema con un volume:
Start Registrydocker Correre -d \
-p 5000:5000 \
--nome registry \
-v /opt/registry-data:/var/lib/registry \
registro:2
Esempio: utilizzo di Harbor
For a more robust solution, download Harbor’s offline installer from the Pagina delle versioni di GitHub di Harbor e seguire la documentazione fornita. Harbor richiede la configurazione dell'archiviazione persistente (utilizzando i volumi) come parte della sua installazione.
5. Configure Helm for Local Registry
Per garantire che ilum estrae le immagini dal registro locale anziché dai repository pubblici, aggiorna i riferimenti al repository di immagini nel grafico Helm. Ad esempio, se i valori predefiniti hanno:
ilum-core:
immagine: "ilum/core:6.6.1"
Cambialo in:
ilum-core:
immagine: "localhost:5000/ilum/core:6.6.1"
You can either edit the chart’s default valori.yaml o fornire un file di sostituzione. Ad esempio, crea valori-registro-locali.yaml:
ilum-core:
immagine: "localhost:5000/ilum/core:6.6.1"
ilum-ui:
immagine: "localhost:5000/ilum/ui:6.6.1"
# Aggiungere sostituzioni simili per altri componenti (ad esempio, ilum/flusso d'aria, ilum/alveare, ecc.)
Quindi installa (o aggiorna) utilizzando:
helm install ilum /path/to/ilum-<Versione>.tgz --namespace ilum --create-namespace -f valori-registro-locali.yaml
6. Installa ilum utilizzando Helm
Assicurati che il tuo kubeconfig è configurato per il cluster offline, quindi installare il grafico Helm:
helm install ilum /path/to/ilum-<Versione>.tgz --namespace ilum --create-namespace
(Includere il file di sostituzione se ne si utilizza uno.)
7. Verifica e risoluzione dei problemi
7.1. Verificare la distribuzione
-
Controllare lo stato di rilascio di Helm:
Helm Statushelm status ilum --namespace ilum -
Elenco Pod:
Get Podskubectl get pods -n ilum -
Ispeziona i riferimenti dell'immagine del pod:
Per esempio:
Describe Podkubectl describe pod <pod_name> -n ilum | grep Image:Verificare che i percorsi delle immagini facciano riferimento al registro locale (ad esempio,
localhost:5000/ilum/alveare:3.1.3).
7.2. Risoluzione dei problemi
Click to view troubleshooting steps
- Errori di ImagePullBackOff:
Verificare che le immagini siano disponibili nel registro locale e che tutti i nodi possano accedere al registro. - Accesso al registro:
Assicurarsi che nei nodi siano configurate tutte le impostazioni del Registro di sistema non sicure necessarie (se si utilizza HTTP). - Archiviazione persistente:
Confirm that the local registry’s data directory is correctly mounted so that images persist across container restarts.
TLS interception with an internal CA
When an internal Certificate Authority signs outbound traffic, configure ilum-core.security.trustStore in 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_BUNDLEe 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_scannere ducklake extensions pre-populated in DuckDB's local extension cache (~/.duckdb/extensions/), and with the hive_metastore e 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 load o 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.