Observability
Portée : namespaced · Kind : Observability (nom court obs, pluriel observabilities) · Groupe : core.navique.com/v1alpha1
Observabilité LLM — traces, évaluations, gestion des prompts. Observability est la charge de travail d'observabilité générique : spec.type sélectionne l'implémentation du backend. Aujourd'hui, seul langfuse est implémenté (Langfuse v3 via le langfuse-operator) ; les autres types sont préparés (scaffold) pour l'avenir.
Spec
| Champ | Type | Description |
|---|---|---|
type | enum (requis) | Implémentation du backend. Seul langfuse est implémenté aujourd'hui |
secretsRef | LocalRef (optionnel) | SecretsManagement du même namespace à attendre. Omettez-le pour utiliser de simples Secrets Kubernetes que vous gérez vous-même — voir secretsRef |
mesh | object | Intègre le namespace au ServiceMesh du cluster (auto / enabled / disabled) |
image | object | Remplacement de l'image pour le backend sélectionné |
ingress | object | Hôte + TLS (TLS ⇒ garantit la présence de cert-manager) |
sso | object | Connexion OIDC/SSO (voir SSO) |
langfuse | object | Configuration spécifique à Langfuse — présente lorsque type: langfuse (voir le bloc langfuse) |
Ces champs de premier niveau sont communs à tous les types de backend. La configuration spécifique au backend réside sous un bloc nommé d'après le type (spec.langfuse pour le backend Langfuse).
type
type | Statut | Émet |
|---|---|---|
langfuse | Implémenté | Un LangfuseInstance (langfuse.palena.ai/v1alpha1) via le langfuse-operator |
Les autres types de backend sont réservés et pas encore implémentés ; en définir un produit une condition de statut « not yet implemented » explicite.
Le bloc langfuse
Lorsque type: langfuse, spec.langfuse contient le câblage de Langfuse v3. Langfuse v3 nécessite Postgres, ClickHouse, Redis et un stockage d'objets (blob) ; chaque datastore peut référencer une ressource datastore ou pointer vers un hôte externe.
| Champ | Type | Description |
|---|---|---|
postgres | DatastoreRef (requis) | Référence un PostgresCluster ou externe |
clickhouse | DatastoreRef (requis) | Référence un ClickHouseCluster ou externe |
redis | DatastoreRef (requis) | Référence un RedisInstance ou externe |
blob | object (requis) | Stockage d'objets (requis par Langfuse v3) : S3 / Azure / GCS |
auth | object | nextAuthUrl ; secret/salt générés automatiquement par l'opérateur |
bootstrap | object | Amorçage headless d'une org / projet / clé API + utilisateur admin (voir Bootstrap) |
licenseSecretRef | SecretKeyRef | Licence Langfuse Enterprise — accès par personne (voir Donner accès aux personnes) |
defaultAccess | object | Accès automatique pour toute personne qui se connecte (voir Donner accès aux personnes) |
DatastoreRef
| Champ | Description |
|---|---|
mode | ref (une ressource datastore) ou external |
ref | La ressource datastore à utiliser (mode ref) |
databaseName | Base de données dans le datastore partagé. Postgres : requis pour un PostgresCluster géré/adopté. ClickHouse : facultatif (par défaut default) ; doit figurer dans spec.databases du ClickHouseCluster (une Stack s'en charge) — Langfuse l'attend. Lettres, chiffres et _ uniquement |
connectionSecretRef | Secret de connexion (mode external) |
blob (union discriminée)
provider sélectionne le backend ; fournissez le bloc correspondant. Les identifiants sont lus depuis un Secret dans le namespace sous des clés canoniques ; l'omission du secret d'identifiants sélectionne les identifiants cloud ambiants (IRSA / Workload Identity).
| Fournisseur | Bloc | Clés d'identifiants |
|---|---|---|
s3 (par défaut) | s3 (bucket, region, endpoint, forcePathStyle) | access-key-id, secret-access-key |
azure | azure (storageAccountName, containerName, endpoint) | account-key |
gcs | gcs (bucket, projectId) | credentials (JSON du SA) |
Ce qu'il émet
Pour type: langfuse, le contrôleur résout les datastores, garantit la présence de cert-manager si TLS/ingress est activé, garantit la présence du langfuse-operator, et émet un LangfuseInstance (langfuse.palena.ai/v1alpha1) référençant les datastores et secrets résolus. La provenance managed/adopt/external réside dans les ressources datastore référencées — Observability se contente de pointer vers elles.
Datastores gérés par l'opérateur par défaut
Pour ClickHouse et Redis, le langfuse-operator peut les gérer en interne. Sauf si vous référencez un datastore external, le contrôleur utilise par défaut un ClickHouse/Redis géré par l'opérateur — vous n'avez donc pas strictement besoin d'un ClickHouseCluster / RedisInstance dédié. Postgres est généralement partagé avec le Gateway.
Exemple
apiVersion: core.navique.com/v1alpha1
kind: Observability
metadata:
name: observability
namespace: forge-langfuse
spec:
type: langfuse
secretsRef: { name: langfuse-secrets }
ingress: { enabled: true, host: langfuse.forge.example.com, tls: true }
langfuse:
postgres: { mode: ref, ref: { name: forge-pg, namespace: forge-data }, databaseName: langfuse }
clickhouse: { mode: ref, ref: { name: forge-ch, namespace: forge-data } }
redis: { mode: ref, ref: { name: forge-redis, namespace: forge-data } }
blob:
provider: azure
azure:
storageAccountName: forgelangfuse
containerName: langfuse-eventsSSO / OIDC login
spec.sso active l'authentification unique. Pour le backend Langfuse, il utilise le fournisseur OIDC personnalisé générique de Langfuse v3 : l'opérateur définit le bloc natif spec.auth.oidc de la LangfuseInstance, que le langfuse-operator traduit en configuration AUTH_CUSTOM_* de Langfuse. Les identifiants du client OAuth proviennent d'un Secret du même namespace (via SecretsManagement).
| Champ | Description |
|---|---|
issuerURL | URL de base de l'émetteur OIDC / de découverte |
clientSecretRef.name | Secret contenant le client OAuth (les clés par défaut sont client-id / client-secret) |
scopes | Scopes demandés (par défaut openid, email, profile) |
providerName | Libellé du bouton de connexion (AUTH_CUSTOM_NAME) |
Les champs provider, tenantID et les endpoints explicites du type SSO partagé sont réservés au Gateway et ignorés ici.
L'IdP doit autoriser le callback OIDC personnalisé <publicURL>/api/auth/callback/custom ; activez donc spec.ingress (ou définissez langfuse.auth.nextAuthUrl) sur une URL publique.
spec:
type: langfuse
sso:
issuerURL: https://idp.example.com
providerName: "Acme SSO"
clientSecretRef: { name: langfuse-oidc }TIP
Les fournisseurs OIDC statiques font partie de la build open-source auto-hébergée de Langfuse. Seuls la configuration SSO dans l'interface, l'application du SSO par organisation, et le RBAC/SCIM sont des fonctionnalités Langfuse Enterprise.
Bootstrap
spec.langfuse.bootstrap amorce en mode headless une organisation, un projet, une clé API initiale et un utilisateur admin dans un Langfuse community neuf, via l'environnement LANGFUSE_INIT_*. Cela permet à la plateforme de démarrer entièrement câblée sans que personne n'ait à se connecter d'abord à l'interface Langfuse — par exemple pour qu'un Gateway puisse exporter des traces vers une clé de projet connue sur un Langfuse community qui ne pourrait sinon pas générer de clés de projet.
| Champ | Description |
|---|---|
organization | Nom de l'organisation initiale |
project | Nom du projet initial |
apiKeySecretRef | Secret à renseigner avec la clé publique/secrète du projet amorcé |
admin | Utilisateur admin (email + mot de passe depuis un Secret) amorcé au premier démarrage |
Les identifiants amorcés sont écrits dans des Secrets possédés afin que les consommateurs (export de traces du Gateway, console de management) puissent les lire sans étapes dans l'interface.
Donner accès aux personnes
Il y a deux façons d'accéder à Langfuse, et elles n'exigent pas la même chose :
- Une par une — une
Identitydetype: observability(avecobservabilityRefet unrole:viewer,member,adminouowner) rend la personne membre de l'organisation de ce Langfuse : l'organisation du bootstrap lorsquebootstrapest actif, qui contient projets et traces. La gestion des membres de Langfuse est une fonction Enterprise : il faut donclicenseSecretRef(la clé de licence Langfuse Enterprise). Sans elle, une telle Identity indique que la licence manque. - Toute personne qui se connecte —
defaultAccessajoute automatiquement chaque nouvel utilisateur Langfuse (par exemple à sa première connexion d'entreprise) à l'organisation et au projet du bootstrap. Aucune licence n'est nécessaire. Sans licence, c'estorgRolequi compte sur tous les projets : les rôles au niveau projet (projectRole) sont aussi une fonction Enterprise.
status.peopleAccess indique si l'accès individuel est Available, ou pourquoi non (NeedsLicense, NeedsNewerLangfuseOperator), et status.signInAccessRole le rôle réellement accordé par l'accès automatique. La console de gestion lit les deux pour proposer la bonne option.
| Champ | Description |
|---|---|
licenseSecretRef | Secret contenant la licence Langfuse Enterprise (clé license par défaut) |
defaultAccess.orgRole | OWNER / ADMIN / MEMBER / VIEWER (par défaut) / NONE |
defaultAccess.projectRole | OWNER / ADMIN / MEMBER / VIEWER (par défaut) — Enterprise uniquement |
defaultAccess nécessite bootstrap (refusé à l'admission sinon).
Secrets
nextauth-secret et salt sont générés automatiquement et soumis à rotation par le langfuse-operator dans un Secret <instance>-generated-secrets — vous ne sourcez pas ces valeurs depuis Key Vault sauf si vous souhaitez les remplacer. Les identifiants des datastores proviennent des Secrets matérialisés des ressources datastore référencées (plus Key Vault pour les datastores externes). Consultez Gestion des secrets.
Status
Disponibilité par datastore, disponibilité de l'instance, et l'hôte ingress, plus les champs standard conditions et observedGeneration. Un type non implémenté fait remonter une condition « not yet implemented » explicite.