Architecture¶
AKKO (Analytics Kernel, Keep Ownership) est une pile analytique souveraine qui unifie plus de 33 services dans une pile lakehouse clé en main. Déployez avec Helm sur Kubernetes -- localement via k3d pour le développement, ou sur tout cluster CNCF conforme en production. Chaque composant est open-source, chaque octet de données reste sur votre infrastructure.
Vue d'Ensemble Générale¶
Traefik (TLS + routage)
|
+------------------------+------------------------+
| | | | |
JupyterHub Superset Dashboards Airflow Cockpit
(notebooks) (BI) (supervision) (pipelines) (portail)
| | | |
+-----+------+-----+----+-----------+
| |
Trino (SQL) Spark Connect
fédération (gRPC)
| |
+------+------+
|
Apache Polaris
(catalogue Iceberg)
|
Stockage objet (S3)
|
PostgreSQL
(PostGIS + pgvector)
Flux de données : la couche de stockage objet stocke les données brutes sous forme de fichiers Parquet. Apache Polaris gère les métadonnées des tables Iceberg (schémas, snapshots, partitions). Spark et Trino se connectent tous deux à Polaris via le protocole REST Iceberg pour lire et écrire les tables. JupyterHub et Superset consomment les résultats des requêtes pour l'analyse et la visualisation.
Couches de Services¶
Infrastructure¶
| Service | Image | Rôle |
|---|---|---|
| Traefik | traefik:v3.6.9 |
Reverse proxy, terminaison TLS, route *.akko.local vers les services via Kubernetes Ingress |
| Cockpit | nginx:1.29-alpine |
Portail avec cartes de santé des services, affichage de la latence, schéma d'architecture |
| PostgreSQL/PostGIS | akko-postgres:2026.04 (personnalisé) |
Base de données relationnelle avec extensions PostGIS (géospatial) et pgvector (embeddings) |
| oauth2-proxy | oauth2-proxy:v7.14.3 |
Middleware ForwardAuth pour les services sans support OIDC natif |
| AKKO Docs | nginx:1.29-alpine |
Sert les rapports Quarto publiés à docs.akko.local |
Data Lake¶
| Service | Image | Rôle |
|---|---|---|
| Stockage objet | chrislusf/seaweedfs |
Stockage objet compatible S3 pour les fichiers de données Iceberg |
| minio-init | minio/mc:RELEASE.2025-08-13T08-35-41Z |
Crée le bucket akko-warehouse au premier démarrage |
Catalogue Iceberg¶
| Service | Image | Rôle |
|---|---|---|
| Apache Polaris | apache/polaris:1.3.0-incubating |
Serveur de catalogue REST Iceberg (remplace tabulario/iceberg-rest). Stocke les métadonnées dans PostgreSQL, sert le protocole REST Iceberg sur le port 8181 |
| polaris-init | curlimages/curl:8.11.1 |
Bootstrap idempotent : crée le catalogue, les principaux/rôles RBAC et les namespaces par défaut via l'API de gestion Polaris |
Calcul¶
| Service | Image | Rôle |
|---|---|---|
| Spark Master | akko-spark:2026.04 (personnalisé) |
Gestionnaire de cluster pour les jobs Spark distribués |
| Spark Worker | akko-spark:2026.04 (personnalisé) |
Noeud exécuteur (2 coeurs, 2 Go de RAM) |
| Spark Connect | akko-spark:2026.04 (personnalisé) |
Serveur gRPC (port 15002) pour les sessions Spark distantes depuis les notebooks |
| Trino | trinodb/trino:480 |
Moteur SQL fédéré avec catalogues Iceberg (via Polaris REST) et PostgreSQL, RBAC basé sur fichier |
| DuckDB | (en processus) | Moteur analytique embarqué dans les conteneurs notebook, interopérabilité Arrow zero-copy |
IDE¶
| Service | Image | Rôle |
|---|---|---|
| JupyterHub | akko-jupyterhub (personnalisé) |
Hub multi-utilisateurs qui déploie des conteneurs notebook individuels via KubeSpawner |
| akko-notebook | akko-notebook (personnalisé) |
Conteneur utilisateur avec Python, R (IRkernel + tidyverse), Julia (DataFrames.jl), code-server (VS Code), Quarto, jupyter-ai, dbt-trino, Great Expectations |
Analytique¶
| Service | Image | Rôle |
|---|---|---|
| Apache Superset | apache/superset:4.1.1 |
Plateforme BI avec source de données Trino et tableau de bord bancaire auto-provisionnés |
| Apache Airflow | apache/airflow:3.1.7-python3.12 |
Orchestration de pipelines avec transport console OpenLineage pour le suivi du lignage |
IA¶
| Service | Image | Rôle |
|---|---|---|
| Ollama | ollama/ollama:0.17.4 |
Serveur d'inférence LLM local (CPU/GPU). Livré avec qwen2.5-coder:7b (génération de code), qwen2.5:3b (chat), et nomic-embed-text (embeddings, 768 dim) |
| ollama-init | ollama/ollama:0.17.4 |
Télécharge les modèles d'embedding et de LLM au premier démarrage |
| LiteLLM | ghcr.io/berriai/litellm:main-stable |
Passerelle IA unifiée avec API compatible OpenAI. Route les requêtes vers les modèles Ollama, fournit le suivi d'utilisation et la limitation de débit |
Gouvernance des Données (profil : governance)¶
Ces services nécessitent 16 Go+ de RAM. Activez-les en définissant openmetadata.enabled=true et akko-opensearch.enabled=true dans vos valeurs Helm.
| Service | Image | Rôle |
|---|---|---|
| OpenMetadata Server | openmetadata/server:1.12.1 |
Catalogue de données, découverte, lignage, tests de qualité, glossaire. Authentifié via Keycloak OIDC (côté serveur, client confidentiel) |
| OpenMetadata Ingestion | openmetadata/ingestion:1.12.1 |
Airflow embarqué pour les workflows d'ingestion de métadonnées |
| OpenMetadata Migrate | openmetadata/server:1.12.1 |
Sidecar de migration de base de données (exécuté une fois avant le démarrage du serveur) |
| OpenSearch | opensearchproject/opensearch:2.19.1 |
Backend de recherche pour OpenMetadata (licence Apache 2.0, remplace Elasticsearch) |
Supervision¶
| Service | Image | Rôle |
|---|---|---|
| Prometheus | prom/prometheus:3.6.7 |
Collecte des métriques de tous les services |
| Dashboards | persesdev/perses |
Rendu de panels PromQL, alertes, exploration de logs. Intégration SSO Keycloak |
| Logs | victoriametrics/victoria-logs |
Backend d'agrégation et recherche LogsQL |
| Log shipper | fluent/fluent-bit |
Collecteur de logs des conteneurs, envoie vers la couche logs |
| Alertmanager | prom/alertmanager:v0.31.1 |
Routage des alertes et notifications |
Sécurité¶
| Service | Image | Rôle |
|---|---|---|
| Keycloak | keycloak:26.1 |
Fournisseur d'identité SSO avec le realm akko : 13 clients OAuth2, 5 rôles RBAC (akko-admin, akko-user, akko-engineer, akko-analyst, akko-viewer), utilisateurs de test pré-configurés |
| OPA | openpolicyagent/opa:1.4.2 |
Open Policy Agent pour le contrôle d'accès fin. Fournit la sécurité au niveau des lignes et le masquage de colonnes pour Trino via le plugin OPA |
Topologie Réseau¶
Kubernetes (principal) : Les services s'exécutent en tant que pods dans le namespace akko. Traefik gère le routage d'entrée avec terminaison TLS via cert-manager ou certificats auto-signés. La communication inter-services utilise les noms DNS de services Kubernetes. En k3d, KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true permet l'échange de jetons OIDC entre pods avec des URL internes.
Mapping des Ports¶
| Service | URL Ingress | Port Interne |
|---|---|---|
| Cockpit | https://akko.local |
80 |
| Tableau de bord Traefik | https://traefik.akko.local |
8080 |
| JupyterHub | https://lab.akko.local |
8000 |
| Superset | https://bi.akko.local |
8088 |
| Airflow | https://orchestrator.akko.local |
8082 |
| Dashboards | https://metrics.akko.local |
8080 |
| Keycloak | https://identity.akko.local |
8080 |
| Trino | https://federation.akko.local |
8080 |
| Interface Spark Master | https://compute.akko.local |
8080 |
| Console stockage objet | https://storage.akko.local |
8888 |
| Polaris | https://polaris.akko.local |
8181 |
| Prometheus | https://prometheus.akko.local |
9090 |
| Ollama | https://ollama.akko.local |
11434 |
| LiteLLM | https://llm.akko.local |
4000 |
| AKKO Docs | https://docs.akko.local |
80 |
| OpenMetadata | https://catalog.akko.local |
8585 |
| PostgreSQL | ClusterIP (interne uniquement) | 5432 |
| API S3 stockage objet | ClusterIP (interne uniquement) | 8333 |
| Spark Master | ClusterIP (interne uniquement) | 7077 |
| Spark Connect | ClusterIP (interne uniquement) | 15002 |
Sidecars d'Initialisation¶
AKKO utilise des jobs et sidecars d'initialisation idempotents (hooks Helm en Kubernetes, ou init containers) pour garantir que toutes les ressources nécessaires existent à chaque déploiement, qu'il s'agisse d'une première installation ou d'une mise à jour.
| Sidecar | S'exécute Après | Ce qu'il Fait |
|---|---|---|
| postgres-init | postgres sain |
Exécute ensure.sql : crée les extensions (PostGIS, pgvector), les schémas (rag, geospatial), les tables et les utilisateurs. Sans risque à ré-exécuter (utilise IF NOT EXISTS et ON CONFLICT DO NOTHING) |
| polaris-init | polaris + storage sains |
Crée le catalogue akko-warehouse avec la configuration de stockage S3, met en place le RBAC (rôle principal ALL, rôle catalogue avec CATALOG_MANAGE_CONTENT), crée les namespaces par défaut (banking, raw, staging, analytics). Idempotent via les codes HTTP (201 = créé, 409 = existe déjà) |
| minio-init | minio sain |
Crée le bucket akko-warehouse avec --ignore-existing |
| superset-init | superset sain |
Importe le YAML de la source de données Trino et exécute bootstrap_dashboard.py pour créer 8 datasets, 8 graphiques et 1 tableau de bord |
| ollama-init | ollama sain |
Télécharge les modèles qwen2.5-coder:7b, qwen2.5:3b et nomic-embed-text |
Images Docker Personnalisées¶
| Image | Dockerfile | Contenu |
|---|---|---|
akko-jupyterhub |
docker/jupyterhub/Dockerfile |
JupyterHub avec KubeSpawner, intégration OIDC Keycloak |
akko-notebook |
docker/jupyterhub/Dockerfile.notebook |
Python 3.11, R (IRkernel, tidyverse, sf, RPostgres), Julia 1.11 (DataFrames.jl, CSV.jl), code-server v4.109.5, Quarto, jupyter-ai, dbt-trino, Great Expectations, GeoPandas, Polars, DuckDB, Altair, Folium |
akko-spark:2026.04 |
docker/spark/Dockerfile |
Apache Spark 3.5.1 avec Iceberg 1.5.2, JARs AWS S3, serveur Spark Connect. Les JARs doivent être intégrés dans l'image (non chargés via --jars ou --packages) |
akko-postgres:2026.04 |
docker/postgres/Dockerfile |
PostgreSQL 16 avec extensions PostGIS 3.4 et pgvector |
Modes de Déploiement¶
AKKO se déploie de manière identique selon deux modes :
Helm sur Kubernetes (Principal)¶
Tous les services sont packagés dans un chart Helm umbrella (helm/akko/) avec 25 dépendances de sous-charts. Déployez sur toute distribution Kubernetes conforme CNCF (k3s, k3d, kubeadm, RKE2, OVHcloud, OpenShift). Utilisez k3d pour le développement local.
cd helm/scripts
./k3d-create.sh # Créer un cluster k3d local
./deploy.sh # Déploiement en deux phases : infra d'abord, puis services
Le script deploy.sh utilise une stratégie de déploiement en deux phases : l'étape 1 installe l'infrastructure (PostgreSQL, stockage objet, Keycloak) avec --no-hooks, puis l'étape 2 exécute helm upgrade avec les hooks activés pour lancer les jobs d'initialisation (postgres-init, polaris-init) dans le bon ordre.
Pour tous les détails, consultez le guide Déploiement Kubernetes.
Principes de Conception¶
-
Initialisation idempotente : Les jobs et sidecars d'initialisation s'exécutent à chaque démarrage et garantissent l'existence des ressources sans erreur si celles-ci existent déjà. Aucune étape manuelle n'est jamais requise après
helm install. -
Aucun correctif manuel : Chaque modification de configuration doit survivre à un cycle complet
helm uninstall && helm install. Si un correctif nécessite une commande manuelle, c'est un bug d'architecture. -
Sondes de santé partout : Chaque pod définit des sondes de readiness et liveness. Les hooks Helm et les init containers imposent l'ordre de démarrage correct.
-
Versions figées : Chaque image conteneur utilise des tags de version explicites. Zéro tag
latestdans l'ensemble du chart. -
Réseau natif Kubernetes : Tous les services communiquent via le namespace
akko. Traefik gère le routage d'ingress et la terminaison TLS. La communication interne utilise les noms DNS de services Kubernetes (ex. :akko-postgresql,akko-trino,akko-akko-polaris). -
Secrets Kubernetes : Tous les identifiants sont stockés dans des Secrets Kubernetes (auto-générés par les templates Helm ou pré-créés). Les services référencent les secrets via
valueFrom.secretKeyRefdans les specs des pods. En dev, des mots de passe déterministes sont définis dansvalues-dev.yaml.