Aller au contenu

Guide de Déploiement Entreprise

Ce guide vous accompagne dans le déploiement d'AKKO en environnement de production ou entreprise. Il couvre les prérequis, le durcissement de la sécurité, TLS, DNS et les opérations au quotidien. Chaque commande est copiable-collable et chaque clé values référence le chart Helm réel.


1. Prérequis

Cluster Kubernetes

Exigence Minimum Recommandé
Version Kubernetes 1.28+ 1.30+
Nœuds 3 (plan de contrôle HA) 5+ (nœuds de charge dédiés)
CPU (total) 12 cœurs 24 cœurs
RAM (totale) 32 Go 64 Go
Classe de stockage N'importe quel provisionneur CSI SSD (ex. gp3, csi-cinder-high-speed)
Contrôleur Ingress Traefik (inclus) ou existant Traefik v3 (inclus)
Répartiteur de charge MetalLB ou LB cloud LB cloud natif

AKKO est testé sur : k3s, kubeadm, EKS, GKE, AKS, OVHcloud MKS et OpenShift. Seules les API Kubernetes standard sont utilisées -- aucun CRD spécifique à une distribution.

Outils

Installez ces outils sur votre poste de travail :

# Vérifier les versions
kubectl version --client    # 1.28+
helm version                # 3.12+
docker version              # 24+ (pour construire les images personnalisées)

DNS

Vous avez besoin d'un domaine (ex. akko.example.com) avec soit :

  • Un enregistrement DNS wildcard *.akko.example.com pointant vers l'IP de votre répartiteur de charge, soit
  • Des enregistrements A/CNAME individuels pour chaque service (voir Section 5)

Certificats TLS

Choisissez parmi :

  • cert-manager avec Let's Encrypt (recommandé en production)
  • Certificat wildcard manuel (ex. de votre autorité de certification)
  • Auto-signé (développement uniquement)

2. Planifier Votre Déploiement

Profils de Déploiement

AKKO propose trois profils, contrôlés en activant ou désactivant des sous-charts dans votre values.yaml :

Minimal (~8 Go RAM, ~4 CPU)

Plateforme de données de base. Adapté à l'évaluation et aux petites équipes.

# Désactiver dans values-production.yaml
akko-ollama:
  enabled: false
akko-litellm:
  enabled: false
akko-lldap:
  enabled: false
loki:
  enabled: false
openmetadata:
  enabled: false
akko-opensearch:
  enabled: false

Services inclus : PostgreSQL, object storage, Polaris, Trino, Spark, Airflow, Superset, JupyterHub, Keycloak, OPA, Cockpit, Docs, Prometheus, Dashboards.

Standard (~20 Go RAM, ~12 CPU) -- Par défaut

Plateforme complète avec IA et agrégation de logs. Recommandé pour la plupart des déploiements.

Services supplémentaires : Ollama (LLM local), LiteLLM (passerelle IA), MLflow (suivi d'expériences), logs layer (logs), log shipper, Alertmanager.

Gouvernance (~28 Go RAM, ~16 CPU)

Tout est inclus, y compris le catalogue de données et la couche de gouvernance.

Services supplémentaires : OpenMetadata Server, OpenSearch.

# Activer la gouvernance dans values-production.yaml
openmetadata:
  enabled: true
akko-opensearch:
  enabled: true

La gouvernance est gourmande en ressources

OpenMetadata + OpenSearch nécessitent environ 4 Go de RAM supplémentaires. Dédiez des nœuds spécifiques ou augmentez la capacité du cluster avant d'activer ce profil.

Décisions de Stockage

Chaque service avec état utilise un PersistentVolumeClaim. Planifiez votre stockage :

Service Objectif Taille recommandée Type de stockage
PostgreSQL Base de données relationnelle partagée 50 Gi SSD
object storage Lac de données S3 (tables Iceberg) 100 Gi+ SSD
Prometheus Rétention des métriques (15j par défaut) 50 Gi SSD ou HDD
logs layer Agrégation des logs 50 Gi HDD
Ollama Fichiers de modèles LLM 20 Gi SSD
Dashboards Persistance des tableaux de bord 5 Gi Tout type
OpenSearch Index du catalogue de gouvernance 30 Gi SSD
Alertmanager État des alertes 5 Gi Tout type

Définissez la classe de stockage globalement ou par service :

global:
  storageClass: "gp3-ssd"    # Valeur par défaut pour tout le cluster

# Ou surcharger par service
akko-postgres:
  persistence:
    storageClass: "fast-ssd"
    size: 50Gi

Exigences Réseau

Port Protocole Utilisation
80 TCP HTTP (redirige vers 443)
443 TCP HTTPS (tous les ingress de services)
6443 TCP API Kubernetes (administration cluster uniquement)

Toute la communication inter-services se fait sur le réseau du cluster. Aucun port supplémentaire n'a besoin d'être exposé.


3. Modification des Identifiants par Défaut (CRITIQUE)

Ne déployez jamais avec les mots de passe par défaut

Le values.yaml par défaut laisse tous les mots de passe vides (auto-générés) ou utilise des valeurs de développement. En production, vous devez définir chaque identifiant explicitement dans votre values-production.yaml.

Tous les identifiants sont définis sous global.auth dans votre fichier values. Générez des mots de passe forts avec :

# Générer un mot de passe aléatoire de 32 caractères
openssl rand -base64 32

# Générer une clé Fernet pour Airflow
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

# Générer un secret de cookie base64 pour OAuth2 Proxy
openssl rand -base64 32 | head -c 32 | base64

Référence Complète des Identifiants

Créez votre values-production.yaml avec tous les identifiants :

global:
  auth:
    # --- PostgreSQL ---
    # Mot de passe super-utilisateur (utilisé par les jobs d'initialisation)
    postgresPassword: "<MOT_DE_PASSE_FORT_1>"

    # Mot de passe utilisateur applicatif (utilisé par Trino, Airflow, Superset, etc.)
    postgresAkkoPassword: "<MOT_DE_PASSE_FORT_2>"

    # --- Stockage objet (S3) ---
    storageRootUser: "akko-admin"
    storageRootPassword: "<MOT_DE_PASSE_FORT_3>"

    # --- Keycloak (Fournisseur d'Identité) ---
    keycloakAdminPassword: "<MOT_DE_PASSE_FORT_4>"

    # --- Apache Polaris (Catalogue Iceberg) ---
    polarisRootSecret: "<MOT_DE_PASSE_FORT_5>"

    # --- Dashboards ---
    dashboardsAdminPassword: "<MOT_DE_PASSE_FORT_6>"

    # --- Apache Superset (Visualisation de Données) ---
    supersetAdminUser: "admin"
    supersetAdminPassword: "<MOT_DE_PASSE_FORT_7>"
    supersetSecretKey: "<HEX_ALEATOIRE_32>"

    # --- Apache Airflow (Orchestration de Pipelines) ---
    airflowAdminUser: "admin"
    airflowAdminPassword: "<MOT_DE_PASSE_FORT_8>"
    airflowFernetKey: "<CLE_FERNET>"

    # --- OAuth2 Proxy (ForwardAuth pour les services sans OIDC natif) ---
    oauth2ProxyCookieSecret: "<BASE64_32_OCTETS>"

    # --- Secrets des Clients OIDC Keycloak ---
    # Chaque service s'authentifiant via Keycloak a besoin de son propre secret.
    # Ceux-ci doivent correspondre aux secrets configurés dans le realm Keycloak.
    oauth2ProxyClientSecret: "<HEX_ALEATOIRE_1>"
    grafanaClientSecret: "<HEX_ALEATOIRE_2>"
    supersetClientSecret: "<HEX_ALEATOIRE_3>"
    jupyterhubClientSecret: "<HEX_ALEATOIRE_4>"
    trinoClientSecret: "<HEX_ALEATOIRE_5>"
    airflowClientSecret: "<HEX_ALEATOIRE_6>"
    openmetadataClientSecret: "<HEX_ALEATOIRE_7>"

Clé Maître LiteLLM

La passerelle IA LiteLLM a sa propre clé maître, configurée séparément :

akko-litellm:
  config:
    general_settings:
      master_key: "<CLE_LITELLM_FORTE>"

URL de Base de Données JupyterHub

Le hub JupyterHub se connecte directement à PostgreSQL. Mettez à jour le mot de passe dans la chaîne de connexion :

jupyterhub:
  hub:
    db:
      type: postgres
      url: "postgresql+psycopg2://postgres:<MOT_DE_PASSE_POSTGRES>@akko-postgresql:5432/jupyterhub"

Connexion Métadonnées Airflow

Airflow nécessite également un mot de passe de base de données explicite :

airflow:
  data:
    metadataConnection:
      protocol: postgresql
      host: "akko-postgresql"
      port: 5432
      db: airflow_metadata
      user: postgres
      pass: "<MOT_DE_PASSE_POSTGRES>"

Connexion Base de Données Superset

superset:
  supersetNode:
    connections:
      db_host: "akko-postgresql"
      db_port: "5432"
      db_user: "postgres"
      db_pass: "<MOT_DE_PASSE_POSTGRES>"
      db_name: "superset"

Utilisez les Secrets Kubernetes pour plus de sécurité

Pour une sécurité maximale, utilisez des références existingSecret au lieu de mots de passe en clair dans les values. De nombreux sous-charts supportent ce pattern. Voir la Section 9 pour les détails.


4. Configuration des Certificats TLS

Option A : cert-manager avec Let's Encrypt (Recommandé)

Installez cert-manager s'il n'est pas déjà présent :

helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager --create-namespace \
  --set crds.enabled=true

Créez un ClusterIssuer :

# cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik
kubectl apply -f cluster-issuer.yaml

Configurez AKKO pour l'utiliser :

global:
  tls:
    enabled: true
    issuer: "letsencrypt-prod"
    secretName: akko-tls

Option B : Certificats Manuels (Wildcard ou Par Service)

Si vous disposez d'un certificat wildcard de votre autorité de certification :

# Créer le secret TLS à partir de vos fichiers de certificat
kubectl create secret tls akko-tls \
  --cert=wildcard.crt \
  --key=wildcard.key \
  -n akko

Configurez AKKO pour utiliser le secret existant :

global:
  tls:
    enabled: true
    issuer: ""              # Vide = pas de cert-manager
    secretName: akko-tls    # Doit correspondre au nom du secret ci-dessus

Option C : Auto-signé (Développement Uniquement)

Pour le développement ou les tests internes uniquement :

global:
  tls:
    enabled: true
    selfSigned: true
    issuer: ""
    secretName: akko-tls

Les certificats auto-signés provoquent des avertissements navigateur

Les utilisateurs verront des avertissements de certificat. Certains services (callbacks OIDC JupyterHub, OAuth Superset) peuvent nécessiter des paramètres tls_verify: false, ce qui est non sécurisé en production.

Configuration TLS de Traefik

Traefik est le contrôleur d'ingress inclus. La terminaison TLS se fait au niveau de Traefik, et les services backend communiquent en HTTP au sein du cluster.

traefik:
  enabled: true
  service:
    type: LoadBalancer
    annotations:
      # Annotations spécifiques au cloud (ex. AWS NLB)
      # service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
  ports:
    web:
      exposedPort: 80
    websecure:
      exposedPort: 443

Si vous disposez déjà d'un contrôleur d'ingress (ex. nginx-ingress sur RKE2), désactivez Traefik et définissez la classe d'ingress :

traefik:
  enabled: false

# Définir la classe d'ingress pour tous les services
# (Chaque service utilisera ingress.className)

5. Configuration DNS

Entrées DNS Requises

Chaque service AKKO expose un hostname via ingress sous votre domaine de base. La valeur global.domain détermine le suffixe.

global:
  domain: akko.example.com    # Votre domaine de production

Cela génère les hostnames suivants :

Service Hostname Fonction
Cockpit akko.example.com Portail de la plateforme (page d'accueil)
Documentation docs.akko.example.com Documentation de la plateforme
Keycloak keycloak.akko.example.com Gestion des identités et des accès
Trino trino.akko.example.com Moteur SQL distribué
Spark spark.akko.example.com Interface Spark Master
Console stockage objet minio.akko.example.com Console du stockage objet
API object storage minio-api.akko.example.com Point d'accès API S3
Superset superset.akko.example.com Visualisation de données
JupyterHub jupyter.akko.example.com Environnement de notebooks
Airflow airflow.akko.example.com Orchestration de pipelines
Dashboards grafana.akko.example.com Tableaux de bord de supervision
Polaris polaris.akko.example.com Catalogue REST Iceberg
MLflow mlflow.akko.example.com Suivi d'expériences ML
Ollama ollama.akko.example.com API LLM locale
LiteLLM litellm.akko.example.com Passerelle IA
Prometheus prometheus.akko.example.com Métriques
Alertmanager alertmanager.akko.example.com Routage des alertes
OpenMetadata catalog.akko.example.com Catalogue de données (gouvernance)
directory service lldap.akko.example.com Administration LDAP (optionnel)
Traefik traefik.akko.example.com Tableau de bord Ingress

DNS Wildcard (Recommandé)

L'approche la plus simple est un seul enregistrement wildcard pointant vers votre répartiteur de charge :

*.akko.example.com    A    <IP_REPARTITEUR_DE_CHARGE>
akko.example.com      A    <IP_REPARTITEUR_DE_CHARGE>

DNS Split-Horizon

Pour les environnements où l'accès interne et externe utilisent des IP différentes :

Zone Enregistrement Cible
Externe *.akko.example.com IP du répartiteur de charge public
Interne *.akko.example.com IP du répartiteur de charge interne/privé

Cela garantit que les utilisateurs au bureau sont routés directement vers le réseau interne tandis que les utilisateurs externes passent par le point d'accès public.


6. Installation Étape par Étape

Étape 1 : Cloner le Dépôt

git clone https://github.com/AKKO-p/AKKO.git
cd AKKO

Étape 2 : Créer Votre Fichier Values de Production

Partez des valeurs par défaut de production et personnalisez :

cp helm/akko/values.yaml values-production.yaml

Éditez values-production.yaml avec vos paramètres. Voici un modèle minimal de production :

# =============================================================================
# AKKO — Modèle de Values de Production
# =============================================================================

global:
  domain: akko.example.com
  storageClass: "gp3-ssd"         # Classe de stockage SSD de votre cluster

  tls:
    enabled: true
    issuer: "letsencrypt-prod"    # ClusterIssuer cert-manager
    secretName: akko-tls

  auth:
    postgresPassword: "<A_CHANGER>"
    postgresAkkoPassword: "<A_CHANGER>"
    minioRootUser: "akko-admin"
    minioRootPassword: "<A_CHANGER>"
    keycloakAdminPassword: "<A_CHANGER>"
    polarisRootSecret: "<A_CHANGER>"
    grafanaAdminPassword: "<A_CHANGER>"
    supersetAdminPassword: "<A_CHANGER>"
    supersetSecretKey: "<A_CHANGER>"
    airflowAdminPassword: "<A_CHANGER>"
    airflowFernetKey: "<A_CHANGER>"
    oauth2ProxyCookieSecret: "<A_CHANGER>"
    # Secrets des clients OIDC (générer des valeurs uniques)
    oauth2ProxyClientSecret: "<A_CHANGER>"
    grafanaClientSecret: "<A_CHANGER>"
    supersetClientSecret: "<A_CHANGER>"
    jupyterhubClientSecret: "<A_CHANGER>"
    trinoClientSecret: "<A_CHANGER>"
    airflowClientSecret: "<A_CHANGER>"

  image:
    registry: "registry.example.com/akko/"  # Votre registre privé
    pullPolicy: IfNotPresent
    pullSecrets:
      - name: registry-credentials

# --- Infrastructure ---
traefik:
  enabled: true
  service:
    type: LoadBalancer

akko-postgres:
  persistence:
    size: 50Gi
  resources:
    requests:
      cpu: 500m
      memory: 1Gi
    limits:
      cpu: "2"
      memory: 4Gi

akko-keycloak:
  hostname: "https://keycloak.akko.example.com"
  ingress:
    host: "keycloak.akko.example.com"

# --- Lac de Données ---
minio:
  mode: distributed              # HA : distribué avec 4 répliques
  replicas: 4
  persistence:
    size: 100Gi
  consoleIngress:
    hosts:
      - minio.akko.example.com
  ingress:
    hosts:
      - minio-api.akko.example.com

# --- Calcul ---
trino:
  server:
    workers: 3                   # Production : 3+ workers
    config:
      query:
        maxMemory: "8GB"
        maxMemoryPerNode: "2GB"
  coordinator:
    resources:
      requests:
        cpu: "1"
        memory: 2Gi
      limits:
        cpu: "4"
        memory: 8Gi
  worker:
    resources:
      requests:
        cpu: "1"
        memory: 2Gi
      limits:
        cpu: "4"
        memory: 8Gi

akko-spark:
  worker:
    replicaCount: 3              # Production : 3+ workers
    memory: "4G"
    cores: 4

# --- Orchestration ---
airflow:
  executor: KubernetesExecutor   # Production : KubernetesExecutor
  config:
    core:
      executor: KubernetesExecutor

# --- IA / LLM ---
akko-ollama:
  gpu:
    enabled: true                # Activer si nœuds GPU disponibles
    # nvidia.com/gpu: 1
  models:
    - qwen2.5-coder:7b
    - qwen2.5:3b
    - nomic-embed-text

akko-litellm:
  config:
    general_settings:
      master_key: "<A_CHANGER>"

# --- Supervision ---
monitoring:
  prometheus:
    prometheusSpec:
      retention: 30d
      storageSpec:
        volumeClaimTemplate:
          spec:
            resources:
              requests:
                storage: 50Gi
  grafana:
    persistence:
      enabled: true
      size: 10Gi
  alertmanager:
    enabled: true

loki:
  enabled: true
  loki:
    persistence:
      size: 50Gi

# --- Gouvernance (optionnel) ---
openmetadata:
  enabled: false                 # Mettre à true si nécessaire
akko-opensearch:
  enabled: false

Étape 3 : Construire et Publier les Images Personnalisées

AKKO inclut 5 images Docker personnalisées qui doivent être construites et publiées vers votre registre de conteneurs :

# Définir votre registre et tag
export AKKO_REGISTRY="registry.example.com/akko"
export AKKO_TAG="2026.03"

# Construire les 5 images personnalisées
bash helm/scripts/build-images.sh

Cela construit et publie :

Image Source Fonction
akko-postgres docker/postgres/Dockerfile PostgreSQL avec PostGIS + pgvector
akko-spark docker/spark/Dockerfile Spark avec JARs Iceberg + AWS
akko-notebook docker/jupyterhub/Dockerfile.notebook JupyterLab + R + Julia + Quarto + libs ML
akko-mlflow docker/mlflow/Dockerfile MLflow + psycopg2 + boto3
akko-cockpit branding/cockpit/Dockerfile Portail (nginx + fichiers statiques)

Mettez à jour votre values-production.yaml pour référencer les images dans votre registre :

global:
  image:
    registry: "registry.example.com/akko/"

akko-postgres:
  image:
    repository: registry.example.com/akko/akko-postgres
    tag: "2026.03"

akko-spark:
  image:
    repository: registry.example.com/akko/akko-spark
    tag: "2026.03"

jupyterhub:
  singleuser:
    image:
      name: registry.example.com/akko/akko-notebook
      tag: "2026.03"

akko-mlflow:
  image:
    repository: registry.example.com/akko/akko-mlflow
    tag: "2026.03"

akko-cockpit:
  image:
    repository: registry.example.com/akko/akko-cockpit
    tag: "2026.03"

Si votre registre nécessite une authentification, créez le secret de pull :

kubectl create namespace akko

kubectl create secret docker-registry registry-credentials \
  --docker-server=registry.example.com \
  --docker-username=<NOM_UTILISATEUR> \
  --docker-password=<MOT_DE_PASSE> \
  -n akko

Étape 4 : Mettre à Jour les Dépendances Helm

cd helm/akko
helm dependency update .

Cela télécharge les 22 charts communautaires (Traefik, object storage, Trino, Airflow, Superset, JupyterHub, kube-prometheus-stack, logs layer, OpenMetadata).

Étape 5 : Préparer le Realm Keycloak

AKKO fournit un realm Keycloak pré-configuré contenant les clients OAuth2 pour chaque service. En production, vous devez mettre à jour les secrets des clients pour correspondre à votre values-production.yaml :

  1. Copiez le modèle de realm :

    cp helm/examples/realm-akko-k3d.json realm-production.json
    

  2. Dans realm-production.json, mettez à jour chaque champ "secret" pour chaque client (jupyterhub, superset, airflow, grafana, trino, oauth2-proxy, openmetadata) pour correspondre aux valeurs global.auth.*ClientSecret correspondantes.

  3. Mettez à jour toutes les URLs de akko.local vers votre domaine de production (akko.example.com).

Étape 6 : Installer AKKO

Une seule commande déploie tous les services, jobs d'initialisation et données de base. Les flags --wait et --wait-for-jobs de Helm garantissent que les bases de données sont prêtes avant le démarrage des services dépendants :

helm upgrade --install akko helm/akko/ -n akko --create-namespace \
  --wait --wait-for-jobs --timeout 20m \
  -f values-production.yaml \
  --set-file akko-keycloak.realm.data=realm-production.json

Le fichier realm est requis à chaque mise à jour

Le flag --set-file akko-keycloak.realm.data=... est obligatoire à chaque helm upgrade. L'omettre provoquera la perte de la configuration du realm Keycloak.

Étape 7 : Vérifier le Déploiement

# Vérifier que tous les pods fonctionnent
kubectl get pods -n akko

# Vérifier que les services ont des endpoints
kubectl get svc -n akko

# Vérifier les ressources ingress
kubectl get ingress -n akko

# Vérifier que les PersistentVolumeClaims sont liés
kubectl get pvc -n akko

# Vérifier les pods en échec
kubectl get pods -n akko --field-selector=status.phase!=Running,status.phase!=Succeeded

Tous les pods devraient atteindre le statut Running en 5 à 10 minutes. Le job d'initialisation de téléchargement des modèles Ollama peut prendre plus de temps selon la vitesse du réseau (les modèles font plusieurs Go).

Étape 8 : Première Connexion

  1. Ouvrez le Cockpit à https://akko.example.com
  2. Connectez-vous à l'admin Keycloak à https://keycloak.example.com avec les identifiants admin définis dans global.auth.keycloakAdminPassword
  3. Vérifiez le SSO en cliquant sur n'importe quel lien de service dans le Cockpit -- vous devriez être redirigé vers Keycloak pour l'authentification

7. Post-Installation

Créer des Utilisateurs dans Keycloak

  1. Allez à https://keycloak.akko.example.com/admin
  2. Sélectionnez le realm akko
  3. Naviguez vers Users et cliquez Create new user
  4. Après la création, allez dans l'onglet Credentials pour définir un mot de passe
  5. Allez dans l'onglet Role mapping pour attribuer un rôle de plateforme

Rôles RBAC AKKO

Le realm Keycloak définit 5 rôles de plateforme qui se propagent à tous les services :

Rôle Trino Airflow Superset Dashboards Description
akko-admin Accès complet Admin Admin Admin Administrateur de plateforme
akko-engineer Créer tables, écrire User Engineer Editor Ingénieur données
akko-analyst Lecture seule User Analyst Editor Analyste métier
akko-steward Lecture + masquage PII Viewer Steward Viewer Conformité / gouvernance
akko-viewer Tableaux de bord uniquement Viewer Viewer Viewer Direction / lecture seule

Vérifier le SSO pour Chaque Service

Après avoir créé un utilisateur de test, vérifiez que le SSO fonctionne en vous connectant à chaque service :

https://federation.akko.example.com -- Interface Web Trino
https://orchestrator.akko.example.com -- Serveur API Airflow 3
https://bi.akko.example.com         -- Tableaux de bord Superset
https://lab.akko.example.com        -- Notebooks JupyterHub
https://metrics.akko.example.com    -- Dashboards
https://catalog.akko.example.com    -- OpenMetadata (si activé)

Chaque service devrait rediriger vers Keycloak pour l'authentification puis revenir au service avec le rôle correct.

Importer les Données de Démonstration (Optionnel)

AKKO inclut des notebooks et DAGs de démonstration qui créent des jeux de données exemples :

  1. Connectez-vous à JupyterHub avec un utilisateur ayant le rôle akko-admin
  2. Ouvrez le notebook akko-banking-demo.ipynb depuis le répertoire work/
  3. Exécutez toutes les cellules pour créer le jeu de données bancaire dans le lakehouse Iceberg

Les DAGs Airflow (akko_e2e_pipeline, akko_data_quality_dag, akko_catalog_sync_dag) sont pré-chargés et peuvent être déclenchés depuis l'interface Airflow.

Configurer les Alertes de Supervision

Alertmanager est déployé avec la pile de supervision. Configurez les récepteurs de notifications :

monitoring:
  alertmanager:
    config:
      receivers:
        - name: "team-email"
          email_configs:
            - to: "ops@example.com"
              from: "akko-alerts@example.com"
              smarthost: "smtp.example.com:587"
        - name: "slack"
          slack_configs:
            - api_url: "https://hooks.slack.com/services/..."
              channel: "#akko-alerts"
      route:
        receiver: "team-email"
        routes:
          - match:
              severity: critical
            receiver: "slack"

8. Opérations Jour 2

Mise à Jour d'AKKO

Pour mettre à jour vers une nouvelle version d'AKKO :

# Récupérer le dernier chart
cd AKKO
git pull origin main

# Mettre à jour les dépendances
cd helm/akko
helm dependency update .

# Reconstruire les images personnalisées (si les Dockerfiles ont changé)
export AKKO_REGISTRY="registry.example.com/akko"
export AKKO_TAG="2026.04"    # Nouveau tag de version
bash helm/scripts/build-images.sh

# Appliquer la mise à jour (le fichier realm est obligatoire !)
helm upgrade akko ./helm/akko \
  --namespace akko \
  -f ../../values-production.yaml \
  --set-file akko-keycloak.realm.data=../../realm-production.json \
  --timeout 15m

Mises à jour progressives

Kubernetes effectue des mises à jour progressives (rolling updates) par défaut. Les services avec plusieurs répliques (workers Trino, workers Spark, object storage distribué) seront mis à jour un pod à la fois sans interruption de service.

Sauvegarde et Restauration

PostgreSQL

# Sauvegarder toutes les bases de données
kubectl exec -n akko statefulset/akko-postgresql -- \
  pg_dumpall -U postgres > akko-pg-backup-$(date +%Y%m%d).sql

# Restaurer
cat akko-pg-backup-20260313.sql | \
  kubectl exec -i -n akko statefulset/akko-postgresql -- \
  psql -U postgres

object storage (Lac de Données S3)

# Utiliser n'importe quel CLI S3 (la CLI AWS convient).
aws --endpoint-url https://storage.akko.example.com s3 \
    sync s3://akko-warehouse /backup/akko-warehouse/

Realm Keycloak

# Exporter le realm (inclut les utilisateurs si demandé)
kubectl exec -n akko deploy/akko-akko-keycloak -- \
  /opt/keycloak/bin/kc.sh export --realm akko --dir /tmp/export
kubectl cp akko/$(kubectl get pod -n akko -l app=akko-keycloak -o name | head -1 | cut -d/ -f2):/tmp/export ./keycloak-export/

Mise à l'Échelle des Services

Mettez à l'échelle les services individuels en mettant à jour le nombre de répliques dans votre fichier values :

# Mettre à l'échelle les workers Trino
trino:
  server:
    workers: 5

# Mettre à l'échelle les workers Spark
akko-spark:
  worker:
    replicaCount: 5

# Passer la couche stockage objet en mode distribué
storage:
  mode: distributed
  replicas: 4

Appliquez avec :

helm upgrade akko ./helm/akko -n akko \
  -f ../../values-production.yaml \
  --set-file akko-keycloak.realm.data=../../realm-production.json

Pour une mise à l'échelle à la demande avec des Horizontal Pod Autoscalers (HPA), configurez directement dans Kubernetes :

kubectl autoscale deployment akko-trino-worker -n akko \
  --min=2 --max=10 --cpu-percent=70

Gestion des Utilisateurs et des Accès

Toute la gestion des utilisateurs est centralisée dans Keycloak :

  1. Créer un utilisateur : Console Admin Keycloak > Users > Create
  2. Attribuer un rôle : User > Role mapping > Assigner akko-admin, akko-engineer, etc.
  3. Fédération LDAP : Keycloak > User federation > Add LDAP provider (connecter à Active Directory ou directory service)
  4. Mapping de groupes : Créer des groupes Keycloak, attribuer des rôles aux groupes, puis ajouter les utilisateurs aux groupes pour l'attribution en masse

Supervision et Alertes

Accédez à la pile de supervision :

  • Dashboards : https://metrics.akko.example.com -- tableaux de bord pré-construits pour le cluster, Trino, Spark, Airflow, PostgreSQL, object storage
  • Prometheus : https://prometheus.akko.example.com -- métriques brutes et requêtes PromQL
  • Alertmanager : https://alertmanager.akko.example.com -- routage et silence des alertes

Métriques clés à surveiller :

Métrique Seuil d'alerte Service
Compteur de redémarrages de pods > 3 en 10 min Tous
Pool de connexions PostgreSQL > 80% akko-postgresql
Utilisation disque object storage > 85% akko-minio
Échecs de requêtes Trino > 10% du taux akko-trino
Taux d'échec des DAGs Airflow > 5% akko-airflow
Pression mémoire des nœuds > 90% Cluster

9. Liste de Vérification du Durcissement Sécuritaire

Utilisez cette liste de vérification avant la mise en production :

Identifiants

  • [ ] Tous les mots de passe global.auth.* sont uniques, forts et non par défaut
  • [ ] La clé maître LiteLLM est définie (akko-litellm.config.general_settings.master_key)
  • [ ] Tous les secrets des clients OIDC Keycloak correspondent entre le JSON du realm et les values
  • [ ] Le mot de passe admin Keycloak est fort et stocké de manière sécurisée
  • [ ] Le volume PostgreSQL est propre (pas de mots de passe de développement résiduels)

TLS

  • [ ] TLS est activé (global.tls.enabled: true)
  • [ ] cert-manager est installé avec un ClusterIssuer valide
  • [ ] Tous les hostnames ingress servent des certificats valides
  • [ ] Les services internes n'exposent pas HTTP à l'extérieur
  • [ ] Les paramètres tls_skip_verify_insecure sont supprimés ou mis à false

Réseau

  • [ ] Le LoadBalancer Traefik a des règles de pare-feu appropriées
  • [ ] Seuls les ports 80 et 443 sont exposés à l'extérieur
  • [ ] L'API Kubernetes (6443) n'est pas accessible publiquement
  • [ ] Les politiques réseau restreignent le trafic pod-à-pod (activer avec global.networkPolicies: true)
  • [ ] Les pods single-user JupyterHub ont un contrôle de sortie (egress)

Sécurité des Pods

  • [ ] Les pods s'exécutent en non-root (global.podSecurityContext.runAsNonRoot: true -- par défaut)
  • [ ] Aucun conteneur ne s'exécute avec privileged: true
  • [ ] Tous les conteneurs abandonnent ALL capabilities
  • [ ] Les Standards de Sécurité des Pods sont appliqués au niveau du namespace :
    kubectl label namespace akko \
      pod-security.kubernetes.io/enforce=restricted \
      pod-security.kubernetes.io/warn=restricted
    

Gestion des Secrets

Pour les déploiements entreprise, envisagez une gestion externe des secrets :

# Exemple : External Secrets Operator avec HashiCorp Vault
# Installer l'opérateur, puis créer des ressources ExternalSecret
# qui synchronisent depuis Vault vers les Secrets Kubernetes
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: akko-postgresql
  namespace: akko
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: akko-postgresql
  data:
    - secretKey: postgres-password
      remoteRef:
        key: akko/postgresql
        property: password

Journalisation d'Audit

  • [ ] Les événements d'audit Keycloak sont activés (connexion, échange de jetons, actions admin)
  • [ ] La journalisation d'audit Kubernetes est configurée au niveau du cluster
  • [ ] Les logs de tâches Airflow sont persistés (non éphémères)
  • [ ] Dashboards et Superset tracent les événements de connexion des utilisateurs

Sécurité des Images

  • [ ] Toutes les images utilisent des tags de version épinglés (pas de :latest)
  • [ ] Les images personnalisées sont analysées pour les vulnérabilités avant le déploiement
  • [ ] Le registre privé utilise TLS et l'authentification
  • [ ] global.image.pullSecrets est configuré pour les registres privés

Pour Aller Plus Loin