Vai al contenuto principale

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 Setup
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-.tgz.

Mancia: You can extract and modify the chart’s valori.yaml in 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.1
  • apache/airflow:3.0.2
  • apache/nifi:2.5.0
  • apache/superset:dockerizzare
  • 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/alveare: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/lancia-scintille:scintilla-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

1.3. Salva ogni immagine come tarball

È possibile creare uno script per questo processo. Ad esempio, creare un file denominato pull_and_save.sh:

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:

Execute 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.

3A.1. Importare i tarball di immagini (su una macchina)

Su una macchina che può accedere al registro locale, importare i tarball:

Import Image
sudo Ctr -n k8s.io images importazione /path/to/<image_tarball>.catrame

Per esempio:

Import Hive Image
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):

Tag Image
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:

Push Image
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.)


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)

  1. Creare una directory per i dati del Registro di sistema:

    Create Directory
    mkdir -p /opt/registry-data
  2. Eseguire il contenitore del Registro di sistema con un volume:

    Start Registry
    docker 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
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
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 Status
    helm status ilum --namespace ilum
  • Elenco Pod:

    Get Pods
    kubectl get pods -n ilum
  • Ispeziona i riferimenti dell'immagine del pod:

    Per esempio:

    Describe Pod
    kubectl 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.