ShinyProxy — Runtime multi-tenant pour tableaux de bord¶
ShinyProxy fournit un runtime multi-tenant pour les tableaux de bord Streamlit et R Shiny dans AKKO. Il crée un conteneur isolé par utilisateur et par tableau de bord, garantissant que deux utilisateurs ne partagent jamais l'état Python. Il s'intègre avec ADEN pour servir les tableaux de bord auto-générés et s'authentifie via Keycloak OIDC.
Architecture¶
Navigateur
|
+--v-----------+ +-------------------+
| Traefik | | Keycloak (OIDC) |
| (ingress) | +--------+----------+
+--+-----------+ |
| |
+--v-----------+ +-----------v-----------+
| ShinyProxy |<-->| PostgreSQL (sessions)|
| (:8080) | +-----------------------+
+--+-----------+
|
| crée par (utilisateur x tableau de bord)
|
+--v-----------+ +--v-----------+
| Streamlit | | Streamlit |
| Pod (user A)| | Pod (user B)|
+--------------+ +--------------+
- ShinyProxy crée des pods Kubernetes isolés pour chaque session utilisateur
- OIDC via Keycloak — authentification SSO avec contrôle d'accès par groupe
- Store de sessions PostgreSQL — permet la haute disponibilité sur plusieurs réplicas
- Syncer de catalogue d'apps — surveille la base ADEN et recharge le catalogue à chaud
URLs¶
| Mode | URL |
|---|---|
| Kubernetes (k3d) | https://reports.<domaine> |
Configuration (valeurs Helm)¶
akko-shinyproxy:
enabled: true
server:
image:
repository: openanalytics/shinyproxy
tag: "3.4.0"
replicas: 2 # HA via store de sessions PostgreSQL
oidc:
enabled: true
clientId: "akko-shinyproxy"
scopes: "openid profile email groups"
database:
host: "akko-postgresql"
name: "shinyproxy"
kubernetes:
heartbeatTimeoutSeconds: 300 # Supprime les pods inactifs après 5 min
maxInstancesGlobal: 50
maxInstancesPerUser: 5
defaultResources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1
memory: 2Gi
ingress:
host: "reports.akko.local"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
cpu: 1
memory: 2Gi
Healthcheck¶
ShinyProxy expose un endpoint de santé sur le port 8080 :
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
RBAC (qui peut accéder)¶
- Authentification OIDC via Keycloak — tous les utilisateurs doivent se connecter via SSO
- Accès par groupe — le
rolesClaim: groupsmappe les groupes Keycloak vers les rôles ShinyProxy - Contrôle d'accès par application — chaque tableau de bord dans le catalogue peut restreindre l'accès à des groupes spécifiques
- Client Keycloak :
akko-shinyproxyavec scopesopenid profile email groups
Syncer de catalogue d'applications¶
Le sidecar syncer surveille la table ADEN dashboards dans PostgreSQL et met à jour le ConfigMap du catalogue ShinyProxy. Les tableaux de bord générés par ADEN apparaissent automatiquement dans ShinyProxy sans configuration manuelle.
| Paramètre | Défaut | Description |
|---|---|---|
syncer.intervalSeconds |
30 | Intervalle de polling pour les nouveaux tableaux de bord |
syncer.adenDb |
aden |
Base PostgreSQL contenant la table dashboards |
syncer.reportsPvc |
akko-aden-reports |
PVC où ADEN écrit les fichiers de tableaux de bord |
Fonctionnalités principales¶
| Fonctionnalité | Description |
|---|---|
| Isolation multi-tenant | Un pod par utilisateur par tableau de bord — aucun état partagé |
| SSO OIDC | Authentification Keycloak avec accès par groupe |
| Catalogue automatique | Les tableaux de bord ADEN apparaissent automatiquement via le syncer |
| Haute disponibilité | Plusieurs réplicas avec sessions stockées dans PostgreSQL |
| Limites de ressources | Plafonds par utilisateur et globaux sur les pods concurrents |
| Nettoyage des inactifs | Pods supprimés après 5 min d'inactivité |
Ressources requises¶
| Composant | RAM minimum | Recommandé |
|---|---|---|
| Serveur ShinyProxy | 1 Gi | 2 Gi |
| Chaque pod de tableau de bord | 512 Mi | 2 Gi |
Dépannage¶
Le pod de tableau de bord ne se lance pas¶
Symptômes : L'utilisateur clique sur un tableau de bord mais ShinyProxy affiche « Starting... » indéfiniment.
Cause : Ressources cluster insuffisantes, échec de pull d'image, ou l'image du tableau de bord n'est pas dans le registre.
Solution :
# Consulter les logs ShinyProxy pour les erreurs de création
kubectl logs -n akko deploy/akko-akko-shinyproxy --tail=100 | grep -i "spawn\|error\|fail"
# Vérifier si le pod de tableau de bord a été créé
kubectl get pods -n akko | grep sp-
# Vérifier les événements pour les erreurs de pull
kubectl get events -n akko --sort-by='.lastTimestamp' | grep -i "pull\|image"
Boucle de connexion OIDC¶
Symptômes : L'utilisateur est redirigé vers Keycloak en boucle sans être authentifié.
Cause : L'URL de l'émetteur OIDC ou le secret client est mal configuré.
Solution :
# Vérifier la configuration OIDC
kubectl get secret -n akko akko-shinyproxy-oidc -o yaml
# Consulter les logs ShinyProxy pour les erreurs OIDC
kubectl logs -n akko deploy/akko-akko-shinyproxy --tail=50 | grep -i "oidc\|oauth\|token"
# Vérifier que le client Keycloak existe
kubectl exec -n akko deploy/akko-keycloak -- /opt/keycloak/bin/kcadm.sh get clients -r akko --fields clientId | grep shinyproxy
Le syncer ne met pas à jour le catalogue¶
Symptômes : Les nouveaux tableaux de bord ADEN n'apparaissent pas dans ShinyProxy.
Cause : Le pod syncer ne tourne pas, ou il ne peut pas se connecter à PostgreSQL.
Solution :