Ajouter un service¶
L'ajout d'un nouveau service à AKKO implique de modifier plusieurs fichiers afin de garantir que le service est correctement routé, sécurisé, supervisé et visible dans le portail cockpit. Cette page fournit la checklist complète ainsi qu'un exemple concret.
Checklist¶
| Étape | Fichier | Objectif |
|---|---|---|
| 1 | helm/akko/charts/<sub-chart>/ |
Sous-chart Helm (templates, values, helpers) |
| 2 | helm/examples/realm-akko-k3d.json |
Client OAuth2 (si le service nécessite le SSO) |
| 3 | scripts/generate-secrets.sh |
Ajouter les nouveaux secrets à la génération .env |
| 4 | branding/cockpit-react/src/platform/catalog.ts |
Déclarer le service comme capacité dans une couche |
| 5 | branding/cockpit-react/src/features/<x>/ |
Ajouter une page (uniquement si le service est rendu dans le cockpit) |
| 6 | branding/cockpit-react/src/app/App.tsx |
Ajouter la route (uniquement pour une page intégrée) |
| 7 | scripts/start.sh |
Afficher l'URL du service au démarrage |
| 8 | Documentation | Mettre à jour la documentation d'architecture, le README, etc. |
Chaque étape est détaillée ci-dessous, suivie d'un exemple complet et concret.
Étape 1 -- Sous-chart Helm¶
Créez un sous-chart Helm dans helm/akko/charts/<nom-du-service>/ et ajoutez la dépendance dans helm/akko/Chart.yaml. Chaque service AKKO suit un modèle cohérent :
- Tag d'image épinglé (jamais
latest) - Nom de conteneur préfixé par
akko- - IngressRoute Traefik pour le routage HTTPS
- Healthcheck avec sondes de vivacité et de disponibilité
- Limites de ressources appropriées au service
- Contexte de sécurité (
runAsNonRoot,drop: [ALL])
Modèle de labels Traefik¶
Tous les services exposés via Traefik utilisent ces quatre labels :
labels:
traefik.enable: "true"
traefik.http.routers.<name>.rule: "Host(`<subdomain>.{{ .Values.global.domain }}`)"
traefik.http.routers.<name>.entrypoints: "websecure"
traefik.http.routers.<name>.tls: "true"
Si le service écoute sur un port non standard (autre que 80), ajoutez :
Pour protéger le service derrière le SSO Keycloak via oauth2-proxy, ajoutez le middleware :
traefik.http.routers.<name>.middlewares: "oauth2-auth-chain@file"
# Plus le routeur de callback oauth2 :
traefik.http.routers.<name>-oauth2.rule: "Host(`<subdomain>.{{ .Values.global.domain }}`) && PathPrefix(`/oauth2/`)"
traefik.http.routers.<name>-oauth2.entrypoints: "websecure"
traefik.http.routers.<name>-oauth2.tls: "true"
traefik.http.routers.<name>-oauth2.service: "oauth2-proxy"
Modèle de healthcheck¶
livenessProbe:
httpGet:
path: /<health-path>
port: <port>
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /<health-path>
port: <port>
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
Conseils pour les healthchecks
- Utilisez les sondes
httpGetpour les endpoints de santé HTTP. - Utilisez les sondes
execavec la commande native de healthcheck du service lorsqu'elle est disponible (par ex.["traefik", "healthcheck"]ou["mc", "ready", "local"]). - Certaines images minimales (comme celle d'Ollama) ne contiennent ni
curlniwget. Utilisez les sondestcpSocketcomme solution de repli.
Étape 2 -- Client OAuth Keycloak¶
Si le service supporte OpenID Connect, ajoutez un client dans helm/examples/realm-akko-k3d.json
dans le tableau clients. L'identifiant du client doit correspondre au nom du service.
Définissez publicClient: false pour les flux côté serveur (confidentiels).
Étape 3 -- Génération des secrets¶
Si le service a besoin d'identifiants, ajoutez-les dans scripts/generate-secrets.sh
à l'intérieur du heredoc qui écrit .env :
Après modification, supprimez .env et relancez le script pour intégrer les nouvelles variables :
Étape 4 -- Capacité cockpit¶
Le cockpit est une SPA React (branding/cockpit-react/). Déclarez le service
comme capacité dans sa couche, au sein de src/platform/catalog.ts. Chaque
capacité porte les rôles autorisés à la voir et un kind :
kind: 'external': le service a sa propre UI dédiée, ouverte dans un nouvel onglet (la plupart des services : Trino, Superset, JupyterHub, ...)kind: 'integrated': le service est rendu comme page dans le cockpit (une fonctionnalité React), atteinte via une route interneto: '/x/<slug>'
{ id: 'governance', fr: 'Gouvernance', en: 'Governance', icon: 'shield', color: '--cl-gov', caps: [
// outil externe : ouvre sa propre UI dans un nouvel onglet
{ id: 'myservice', tool: 'myservice', fr: 'Mon service', en: 'My service',
dfr: 'Description courte', den: 'Short description',
vendor: 'myservice', icon: 'database', roles: ENG, kind: 'external', home: true },
] },
Le champ roles est la porte de visibilité : canSeeCap(cap, role, toolAccess)
dans src/session/SessionProvider lit la même matrice d'accès aux outils que
celle qui pilote la porte OPA (ADR-075) ; une carte n'apparaît donc que pour un
utilisateur ayant droit à l'outil. Aucun proxy de santé à configurer : la santé
par tuile vient du backend du cockpit.
Étape 5 -- Page (services intégrés uniquement)¶
Sautez cette étape pour un service external. Si le service est rendu dans
le cockpit, ajoutez une fonctionnalité sous src/features/<x>/ :
src/features/myservice/
├── MyServicePage.tsx # le composant de page
└── i18n.ts # dictionnaire FR/EN (jamais de chaîne codée en dur dans le JSX)
La page lit ses chaînes depuis le dictionnaire i18n.ts via useLang() / un
helper t(), à l'image des fonctionnalités existantes (RAG, NORA, ...).
Étape 6 -- Route (services intégrés uniquement)¶
Enregistrez la route de la page dans src/app/App.tsx, avant le catch-all
x/:slug :
Le cockpit utilise un HashRouter (ADR-074) : aucune règle de réécriture nginx n'est nécessaire pour servir l'îlot statique.
Étape 7 -- URL de démarrage¶
Ajoutez l'URL du service dans la bannière de démarrage dans scripts/start.sh :
Étape 8 -- Documentation¶
Mettez à jour la documentation d'architecture et tout guide pertinent pour refléter le nouveau service.
Exemple complet : ajout de « DataHub »¶
Voici un exemple complet et concret d'ajout d'un service hypothétique DataHub (catalogue de métadonnées) à AKKO.
1. Sous-chart Helm¶
Créez helm/akko/charts/akko-datahub/ avec la structure standard de sous-chart :
helm/akko/charts/akko-datahub/
├── Chart.yaml
├── values.yaml
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── _helpers.tpl
Ajoutez la dépendance dans helm/akko/Chart.yaml :
Exemple de values.yaml :
enabled: true
image:
repository: acryldata/datahub-gms
tag: "v0.13.0"
pullPolicy: IfNotPresent
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 1Gi
cpu: 500m
2. helm/examples/realm-akko-k3d.json¶
Ajoutez un client confidentiel dans le tableau clients :
{
"clientId": "datahub",
"enabled": true,
"publicClient": false,
"secret": "${KC_CLIENT_SECRET_DATAHUB}",
"redirectUris": ["https://datahub.akko.local/*"],
"webOrigins": ["https://datahub.akko.local"],
"protocol": "openid-connect",
"standardFlowEnabled": true,
"directAccessGrantsEnabled": false
}
3. scripts/generate-secrets.sh¶
Ajoutez dans le heredoc :
4. branding/cockpit-react/src/platform/catalog.ts¶
DataHub est un catalogue de métadonnées avec sa propre UI : c'est donc une
capacité external dans la couche Gouvernance :
{ id: 'datahub', tool: 'datahub', fr: 'Catalogue de métadonnées',
en: 'Metadata catalog', dfr: 'Découverte & lignage',
den: 'Discovery & lineage', vendor: 'datahub', icon: 'database',
roles: ENG, kind: 'external', home: true },
5 & 6. Page et route (inutiles ici)¶
DataHub s'ouvre dans son propre onglet (kind: 'external') : ni page React ni
route App.tsx ne sont nécessaires. Ces deux étapes ne concernent qu'un service
integrated rendu dans le cockpit.
7. scripts/start.sh¶
Vérification¶
Après avoir complété toutes les étapes :
# Regénérer les secrets
rm .env && ./scripts/generate-secrets.sh
# Déployer avec Helm
helm upgrade akko helm/akko/ -n akko -f helm/examples/values-dev.yaml \
--set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json
# Vérifier que DataHub est en bonne santé
kubectl get pods -n akko | grep datahub
kubectl logs -f deploy/akko-datahub -n akko
# Ouvrir le cockpit et confirmer que la tuile DataHub apparaît (pour un rôle habilité)
open https://demo.akko.local
# Ouvrir le service directement
open https://datahub.akko.local