Dépannage¶
Un guide complet problème-solution pour les problèmes courants d'AKKO, organisé par composant. Chaque entrée décrit le symptôme, la cause racine et la correction.
Traefik¶
Traefik plante ou ne démarre pas avec Docker Engine v29+¶
Symptôme : Le conteneur Traefik s'arrête immédiatement ou entre dans une boucle de redémarrage après la mise à jour de Docker Desktop.
Cause : Traefik v3.2 et v3.3 présentent un problème de compatibilité avec Docker Engine v29+.
Correction : Utilisez Traefik v3.4 ou ultérieur. AKKO épingle Traefik à v3.6.9 dans
le chart Helm.
PostgreSQL¶
Le mot de passe dans .env a changé mais la connexion échoue toujours¶
Symptôme : Après avoir regénéré .env, les services ne peuvent plus se connecter à PostgreSQL
avec le nouveau mot de passe. Erreur : password authentication failed for user "akko".
Cause : PostgreSQL stocke les mots de passe des utilisateurs dans son volume de données.
Les scripts d'initialisation dans postgres/init/ ne s'exécutent qu'une seule fois (au premier
démarrage lorsque le volume est vide). Modifier .env ne met pas à jour le mot de passe
dans la base de données.
Correction : Mettez à jour manuellement le mot de passe dans la base en cours d'exécution :
kubectl exec -n akko deploy/akko-postgresql -- psql -U postgres -c \
"ALTER USER akko WITH PASSWORD 'paste-new-password';"
Répétez pour chaque utilisateur concerné (postgres, akko, keycloak_user).
Warning
Cela s'applique à tous les utilisateurs PostgreSQL. Les scripts d'initialisation
dans postgres/init/ (montés dans docker-entrypoint-initdb.d) ne s'exécutent que
lorsque le volume de données est vide. Le sidecar postgres-init gère la création
idempotente des schémas et extensions, mais les changements de mot de passe nécessitent
toujours un ALTER USER.
Les scripts d'initialisation ne se sont pas exécutés¶
Symptôme : Les bases de données, extensions ou schémas attendus sont manquants.
Cause : Les scripts d'initialisation Docker PostgreSQL (docker-entrypoint-initdb.d/)
ne s'exécutent qu'au premier démarrage avec un volume de données vide.
Correction : Pour tout ce qui doit persister entre les redémarrages et reconstructions,
AKKO utilise le sidecar postgres-init avec ensure.sql. Si vous devez relancer les scripts
d'initialisation depuis zéro :
kubectl delete pvc -n akko -l app.kubernetes.io/name=akko-postgres
helm upgrade akko helm/akko/ -n akko
Danger
Cela détruit toutes les données de la base. Exportez tout ce dont vous avez besoin au préalable.
Apache Polaris (Catalogue Iceberg)¶
Les identifiants de démarrage ne sont pas appliqués¶
Symptôme : POLARIS_BOOTSTRAP_CREDENTIALS (défini dans les values Helm ou un Secret Kubernetes) est ignoré.
Cause : Polaris ne lit les identifiants de démarrage qu'au premier lancement (base de données vide).
Correction : Si vous devez réinitialiser les identifiants Polaris, supprimez les données Polaris de PostgreSQL et redémarrez :
kubectl delete deploy -n akko -l app.kubernetes.io/name=akko-polaris
kubectl exec -n akko statefulset/akko-postgresql -- psql -U postgres -d akko -c "DROP SCHEMA IF EXISTS polaris CASCADE;"
helm upgrade akko helm/akko/ -n akko
Le catalogue disparaît après la recréation de la base¶
Symptôme : polaris-init indique « catalog already exists » mais Trino/Spark ne
trouvent aucune table. L'API de gestion renvoie une liste de catalogues vide.
Cause : Après une réinitialisation du volume PostgreSQL, polaris-init peut conserver
un état obsolète. Les métadonnées du catalogue ont disparu mais le script d'initialisation
pense qu'il est toujours présent.
Correction : Recréez toujours les catalogues à l'aide du job d'initialisation :
# Le job polaris-init s'exécute automatiquement lors d'un helm upgrade :
helm upgrade akko helm/akko/ -n akko
Ne jamais créer de catalogues Polaris manuellement
Le script polaris-init contient le format storageConfigInfo correct
(avec stsUnavailable, endpoint, pathStyleAccess comme champs de premier niveau)
et la configuration RBAC complète (rôle de principal, rôle de catalogue, autorisations).
Les commandes curl manuelles se trompent fréquemment dans le format -- Polaris
ignore silencieusement la notation pointée (s3.endpoint) et les objets imbriqués
({"s3": {...}}).
Trino reçoit « invalid_scope » de Polaris¶
Symptôme : Le connecteur Iceberg de Trino échoue avec invalid_scope lors de
l'authentification auprès de Polaris.
Cause : Le scope OAuth2 par défaut de Trino est rejeté par Polaris.
Correction : Définissez le scope explicite dans trino/catalog/iceberg.properties :
DROP TABLE interdit¶
Symptôme : DROP TABLE échoue avec DROP_TABLE_WITH_PURGE refusé.
Cause : Le RBAC de Polaris n'accorde pas les privilèges de purge par défaut.
Correction : Utilisez CALL iceberg.system.unregister_table('schema', 'table') au lieu
de DROP TABLE.
Keycloak (SSO)¶
Boucle de connexion Safari avec certificats auto-signés¶
Symptôme : La connexion redirige en boucle infinie dans Safari. Les autres navigateurs fonctionnent normalement.
Cause : Safari est strict concernant les certificats TLS auto-signés et bloque les cookies cross-origin pour les certificats non approuvés.
Correction : Approuvez le certificat AKKO dans le Trousseau macOS :
- Ouvrez Trousseaux d'accès (Keychain Access)
- Glissez
traefik/certs/akko.crtdans le trousseau Système - Double-cliquez dessus, développez Confiance, définissez sur Toujours faire confiance
- Redémarrez Safari complètement
Erreur emailVerified à la connexion JupyterHub¶
Symptôme : oauth2-proxy rejette la connexion de l'utilisateur avec une erreur de vérification.
Cause : Les utilisateurs Keycloak doivent avoir emailVerified: true pour passer la
validation d'oauth2-proxy.
Correction : Dans la console d'administration Keycloak, modifiez l'utilisateur et activez Email verified. Tous les utilisateurs de test (alice, bob, carol, dave) doivent avoir ce drapeau activé.
KC_HOSTNAME_URL silencieusement ignoré¶
Symptôme : Erreurs de discordance d'émetteur Keycloak. La validation des jetons échoue.
Cause : KC_HOSTNAME_URL est une clé de configuration v1, silencieusement ignorée dans
Keycloak 26.x.
Correction : Utilisez KC_HOSTNAME (pas KC_HOSTNAME_URL). Définissez
KC_HOSTNAME_BACKCHANNEL_DYNAMIC: false pour un émetteur cohérent.
Trino¶
Accès refusé pour l'utilisateur¶
Symptôme : Les requêtes Trino échouent avec Access Denied.
Cause : L'utilisateur n'appartient pas au groupe RBAC approprié.
Correction : Vérifiez trino/etc/group.txt et assurez-vous que l'utilisateur est listé
dans le groupe approprié. AKKO utilise cinq rôles : akko-admin, akko-engineer, akko-analyst,
akko-user, akko-viewer. Voir le guide RBAC pour plus de détails.
Échec d'authentification pour le connecteur PostgreSQL¶
Symptôme : Trino ne peut pas interroger le catalogue PostgreSQL. Erreur :
password authentication failed for user "akko".
Cause : Le mot de passe de l'utilisateur akko dans PostgreSQL ne correspond pas à celui
de la configuration Trino (provenant des values Helm ou des Secrets Kubernetes). Cela se produit
lorsque les secrets ont été regénérés mais que le volume PostgreSQL conserve l'ancien mot de passe.
Correction : Consultez la correction de la persistance des mots de passe PostgreSQL ci-dessus.
Spark¶
JARs introuvables à l'exécution (ClassNotFoundException)¶
Symptôme : Les jobs Spark échouent avec ClassNotFoundException pour les classes
Iceberg ou AWS.
Cause : L'utilisation des options --jars ou --packages pour charger des JARs ne
fonctionne pas de manière fiable avec Spark Connect en raison de l'isolation du ClassLoader.
Correction : Tous les JARs doivent être intégrés dans l'image Docker via le
Dockerfile akko-spark. Après l'ajout de JARs :
# Reconstruisez l'image et poussez-la dans le registre, puis mettez à jour :
bash helm/scripts/build-images.sh
kubectl rollout restart deploy/akko-spark-master deploy/akko-spark-worker deploy/akko-spark-connect -n akko
Erreur SerializedLambda sur .collect()¶
Symptôme : Exception SerializedLambda lors de l'appel à .collect() sur les tables
de métadonnées Iceberg en mode Spark Connect.
Cause : Problème connu de sérialisation de Spark Connect avec les tables de métadonnées Iceberg.
Correction : Utilisez .show() au lieu de .collect() pour les requêtes sur les tables de
métadonnées. Pour un accès programmatique, utilisez .toPandas() qui contourne le chemin de
sérialisation.
Superset¶
Erreur EXPRESSION_NOT_AGGREGATE sur les graphiques¶
Symptôme : Un graphique Superset échoue avec EXPRESSION_NOT_AGGREGATE lors de
l'utilisation d'un dataset virtuel.
Cause : Les métriques Superset sur les datasets virtuels doivent utiliser des fonctions
d'agrégation. Une référence de colonne simple comme amount n'est pas valide en tant que
métrique.
Correction : Définissez les métriques avec des fonctions d'agrégation : SUM(amount),
COUNT(*), AVG(score), etc.
L'association graphique-tableau de bord ne fonctionne pas via l'API REST¶
Symptôme : Les graphiques créés via l'API REST de Superset n'apparaissent pas sur le tableau de bord.
Cause : L'endpoint REST POST pour les tableaux de bord ne crée pas la relation
many-to-many avec les slices (graphiques).
Correction : Utilisez l'approche ORM dans le script de bootstrap :
dash.slices = [slice1, slice2, ...] avec un commit de session de base de données.
JupyterHub / Notebooks¶
Les extensions code-server ne se chargent pas¶
Symptôme : Les extensions VS Code sont manquantes dans les sessions code-server.
Cause : Les extensions installées au niveau utilisateur sont perdues entre les redémarrages de conteneur.
Correction : Les extensions doivent être installées au niveau système dans le Dockerfile :
Un hook before-notebook.d crée un lien symbolique du répertoire d'extensions vers chaque
session utilisateur.
CHOWN_HOME échoue avec les volumes en lecture seule¶
Symptôme : Le conteneur notebook ne démarre pas. Erreur : chown: read-only file system.
Cause : CHOWN_HOME_OPTS=-R tente de faire un chown sur tous les volumes montés,
y compris les montages en lecture seule comme notebooks/.
Correction : Définissez CHOWN_HOME=no dans la configuration du spawner et utilisez un
hook before-notebook.d personnalisé qui exécute chown 2>/dev/null || true (ignore les
erreurs sur les montages en lecture seule).
Ollama (IA locale)¶
Mémoire insuffisante avec les grands modèles¶
Symptôme : Le conteneur Ollama plante ou redémarre lors du chargement d'un grand modèle LLM.
Cause : Les grands modèles (7B+ paramètres) nécessitent plus de RAM que ce que Docker Desktop alloue généralement. AKKO est livré avec qwen2.5-coder:7b (4,7 Go), qwen2.5:3b et nomic-embed-text.
Correction : Utilisez un modèle plus léger comme qwen2.5:3b pour le chat, ou augmentez l'allocation mémoire de Docker Desktop à 16 Go ou plus. Le modèle qwen2.5-coder:7b nécessite au moins 10 Go de RAM disponible.
Le healthcheck échoue (pas de curl dans l'image)¶
Symptôme : Le healthcheck d'Ollama renvoie un état non sain alors que le service fonctionne.
Cause : L'image Ollama ne contient ni curl ni wget.
Correction : Utilisez une vérification TCP dans le healthcheck :
Note
Utilisez CMD (pas CMD-SHELL) car le /bin/sh de l'image Ollama ne supporte
pas /dev/tcp.
OpenMetadata (Profil Gouvernance)¶
Mémoire insuffisante / boucle de redémarrage¶
Symptôme : Le serveur OpenMetadata ou OpenSearch plantent de manière répétée.
Cause : Mémoire Docker Desktop insuffisante. OpenMetadata + OpenSearch nécessitent environ 2,5 Go combinés.
Correction : Allouez au moins 16 Go à Docker Desktop. Ne démarrez ces services qu'avec le profil gouvernance :
OpenSearch plante avec un heap de 768 Mo¶
Symptôme : OpenSearch entre dans une boucle de redémarrage avec des erreurs OOM.
Cause : OpenSearch nécessite environ 1 Go pour la mémoire heap + native. Une limite de 768 Mo est insuffisante.
Correction : Assurez-vous qu'OpenSearch est configuré avec au moins -Xms512m -Xmx512m
et une limite mémoire de conteneur supérieure à 1 Go.
Erreurs de sérialisation API sur les requêtes PUT¶
Symptôme : L'API REST d'OpenMetadata renvoie des erreurs 400/500 sur les requêtes PUT pour les entités.
Cause : Les endpoints PUT attendent des chaînes FQN (Fully Qualified Name) pour les champs
comme service, testSuite et domain -- et non des objets {id, type}.
Correction : Utilisez toujours des valeurs FQN sous forme de chaînes dans les payloads PUT.
Pour les data products, les assets doivent être ajoutés via un appel PATCH séparé après la
création.
Le conteneur de migration échoue¶
Symptôme : Le sidecar de migration OpenMetadata s'arrête avec une erreur.
Cause : Commande de point d'entrée incorrecte.
Correction : La commande de migration doit être :
Et non ./openmetadata.sh qui est le point d'entrée du serveur.
Communication inter-services¶
Les services ne peuvent pas communiquer entre eux via les URL externes¶
Symptôme : Un pod tente d'accéder à identity.akko.local et obtient
connection refused ou une erreur de résolution DNS.
Cause : Les noms de domaine externes (par ex. *.akko.local) peuvent ne pas se résoudre
à l'intérieur du cluster, ou peuvent résoudre vers l'IP de l'ingress qui ne peut pas router
vers les pods.
Fix : Utilisez toujours les noms DNS de services Kubernetes pour la communication inter-services :
| Au lieu de | Utilisez |
|---|---|
identity.akko.local |
akko-akko-keycloak:8080 |
minio.akko.local |
akko-minio:9000 |
federation.akko.local |
akko-trino:8080 |
En k3d, KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true permet l'échange de jetons OIDC pod-à-pod
via les URL internes.
DNS et domaine *.akko.local¶
Le domaine par défaut d'AKKO est akko.local, configurable via global.domain dans les
values Helm. Tous les services sont exposés via l'ingress Traefik sous
<service>.akko.local (par ex. identity.akko.local, bi.akko.local).
Résolution DNS locale¶
Pour accéder aux services depuis votre machine de développement, ajoutez les entrées dans
/etc/hosts ou utilisez un résolveur DNS local (comme dnsmasq) :
# /etc/hosts (exemple pour k3d)
127.0.0.1 cockpit.akko.local identity.akko.local bi.akko.local federation.akko.local minio.akko.local jupyterhub.akko.local orchestrator.akko.local grafana.akko.local experiments.akko.local
Domaine personnalisé
Pour utiliser un autre domaine (par ex. akko.example.com), modifiez global.domain
dans vos values Helm. Tous les ingress et les URL OAuth seront mis à jour automatiquement.
Communication interne au cluster¶
Les pods ne doivent jamais utiliser les URL *.akko.local pour communiquer entre eux.
À l'intérieur du cluster Kubernetes, les services se joignent via le DNS interne :
akko-akko-keycloak:8080(pasidentity.akko.local)akko-minio:9000(pasminio.akko.local)akko-trino:8080(pasfederation.akko.local)
Cela évite les problèmes de hairpin routing et garantit que la communication fonctionne indépendamment de la configuration DNS de l'hôte.
Volume published-reports¶
Le rendu Quarto échoue avec une erreur de permission¶
Symptôme : Le rendu d'un rapport Quarto depuis JupyterHub échoue car le répertoire de sortie n'est pas accessible en écriture.
Cause : Le volume published-reports est créé en tant que root. L'utilisateur
notebook (uid 1000) ne peut pas y écrire.
Correction : Assurez-vous que le volume est accessible en écriture pour tous :
Ceci est géré automatiquement par le point d'entrée du service AKKO Docs, mais peut nécessiter d'être réappliqué si le volume est recréé.