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.compointant 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 :
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
Configurez AKKO pour l'utiliser :
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 :
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.
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 :
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¶
Étape 2 : Créer Votre Fichier Values de Production¶
Partez des valeurs par défaut de production et personnalisez :
É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¶
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 :
-
Copiez le modèle de realm :
-
Dans
realm-production.json, mettez à jour chaque champ"secret"pour chaque client (jupyterhub,superset,airflow,grafana,trino,oauth2-proxy,openmetadata) pour correspondre aux valeursglobal.auth.*ClientSecretcorrespondantes. -
Mettez à jour toutes les URLs de
akko.localvers 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¶
- Ouvrez le Cockpit à
https://akko.example.com - Connectez-vous à l'admin Keycloak à
https://keycloak.example.comavec les identifiants admin définis dansglobal.auth.keycloakAdminPassword - 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¶
- Allez à
https://keycloak.akko.example.com/admin - Sélectionnez le realm akko
- Naviguez vers Users et cliquez Create new user
- Après la création, allez dans l'onglet Credentials pour définir un mot de passe
- 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 :
- Connectez-vous à JupyterHub avec un utilisateur ayant le rôle
akko-admin - Ouvrez le notebook
akko-banking-demo.ipynbdepuis le répertoirework/ - 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 :
Gestion des Utilisateurs et des Accès¶
Toute la gestion des utilisateurs est centralisée dans Keycloak :
- Créer un utilisateur : Console Admin Keycloak > Users > Create
- Attribuer un rôle : User > Role mapping > Assigner
akko-admin,akko-engineer, etc. - Fédération LDAP : Keycloak > User federation > Add LDAP provider (connecter à Active Directory ou directory service)
- 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_insecuresont 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
ALLcapabilities - [ ] Les Standards de Sécurité des Pods sont appliqués au niveau du namespace :
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.pullSecretsest configuré pour les registres privés
Pour Aller Plus Loin¶
- Guide de Déploiement Kubernetes -- démarrage rapide et guides spécifiques aux plateformes (k3s, OVHcloud, OpenShift)
- Vue d'Ensemble de l'Architecture -- comment les services se connectent
- Administration RBAC -- configuration détaillée des rôles
- Référence de Configuration -- variables d'environnement et réglages
- Guide de Dépannage -- problèmes courants et solutions
- Ajouter un Service -- étendre la plateforme