Despliega Langfuse en Kubernetes: Observabilidad y trazabilidad para LLMs (¡como un pro!)
Nivel: Intermedio/Avanzado | Utilidad: Observabilidad avanzada en entornos de IA generativa
¿Por qué Langfuse y por qué ahora?
Si trabajas con chatbots, asistentes AI o pipelines de modelos de lenguaje (LLMs) y nunca has trazado una petición “end-to-end”, necesitas descubrir Langfuse. Esta herramienta open source se está convirtiendo en una pieza clave para:
– Auditar y depurar prompts, respuestas y tiempos en proyectos LLM.
– Visualizar flujos de conversación, detectar “hallucinations” y analizar costs.
– Colaborar con equipos en la mejora continua de sistemas AI.
Además, Kubernetes se consolida como la mejor plataforma para desplegar este tipo de herramientas modernas, según las tendencias de 2025 en integración de AI y observabilidad cloud-native[1][2][3].
Arquitectura resumida
Vamos a desplegar los servicios principales de Langfuse:
– langfuse-app: Interfaz web y API
– PostgreSQL: Base de datos
– langfuse-worker (opcional): Procesamiento asíncrono
Cada uno en su propio Deployment y con servicios gestionados por Kubernetes.
Despliegue paso a paso y ficheros YAML
1. Espacio de nombres
apiVersion: v1
kind: Namespace
metadata:
name: langfuse
2. Secretos y ConfigMaps (con variables de ejemplo, personalízalos)
apiVersion: v1
kind: Secret
metadata:
name: langfuse-secrets
namespace: langfuse
type: Opaque
data:
POSTGRES_PASSWORD: cG9zdGdyZXNfcGFzcw== # postgres_pass (base64)
LANGFUSE_SECRET: bGFuZ2Z1c2Vfc2VjcmV0 # langfuse_secret (base64)
---
apiVersion: v1
kind: ConfigMap
metadata:
name: langfuse-config
namespace: langfuse
data:
LANGFUSE_PUBLIC_URL: "https://langfuse.midominio.com"
LANGFUSE_DB_HOST: "langfuse-postgres"
LANGFUSE_DB_PORT: "5432"
LANGFUSE_DB_USER: "postgres"
LANGFUSE_DB_NAME: "langfuse"
3. PostgreSQL (persistente, básico para pruebas)
apiVersion: apps/v1
kind: Deployment
metadata:
name: langfuse-postgres
namespace: langfuse
spec:
replicas: 1
selector:
matchLabels:
app: langfuse-postgres
template:
metadata:
labels:
app: langfuse-postgres
spec:
containers:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: langfuse-secrets
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_NAME
ports:
- containerPort: 5432
volumeMounts:
- name: pgdata
mountPath: /var/lib/postgresql/data
volumes:
- name: pgdata
emptyDir: {} # Sustituye por PVC en producción
---
apiVersion: v1
kind: Service
metadata:
name: langfuse-postgres
namespace: langfuse
spec:
ports:
- port: 5432
selector:
app: langfuse-postgres
4. Langfuse App
apiVersion: apps/v1
kind: Deployment
metadata:
name: langfuse-app
namespace: langfuse
spec:
replicas: 1
selector:
matchLabels:
app: langfuse-app
template:
metadata:
labels:
app: langfuse-app
spec:
containers:
- name: langfuse
image: ghcr.io/langfuse/langfuse:latest
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_HOST
- name: DATABASE_PORT
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_PORT
- name: DATABASE_USER
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_USER
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: langfuse-secrets
key: POSTGRES_PASSWORD
- name: DATABASE_NAME
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_NAME
- name: NEXTAUTH_SECRET
valueFrom:
secretKeyRef:
name: langfuse-secrets
key: LANGFUSE_SECRET
- name: NEXTAUTH_URL
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_PUBLIC_URL
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: langfuse-app
namespace: langfuse
spec:
type: ClusterIP
ports:
- port: 3000
targetPort: 3000
selector:
app: langfuse-app
5. (Opcional) Langfuse Worker
apiVersion: apps/v1
kind: Deployment
metadata:
name: langfuse-worker
namespace: langfuse
spec:
replicas: 1
selector:
matchLabels:
app: langfuse-worker
template:
metadata:
labels:
app: langfuse-worker
spec:
containers:
- name: worker
image: ghcr.io/langfuse/langfuse-worker:latest
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_HOST
- name: DATABASE_PORT
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_PORT
- name: DATABASE_USER
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_USER
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: langfuse-secrets
key: POSTGRES_PASSWORD
- name: DATABASE_NAME
valueFrom:
configMapKeyRef:
name: langfuse-config
key: LANGFUSE_DB_NAME
6. Exposición externa (Ingress básico)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: langfuse-ingress
namespace: langfuse
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: langfuse.midominio.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: langfuse-app
port:
number: 3000
No olvides configurar correctamente DNS y TLS según tu entorno para acceso seguro.
¿Y luego qué? Ejemplo de integración
Desde tu pipeline AI o backend (Python, Node, etc.) puedes conectar con la API de Langfuse mediante su SDK (ver docu oficial). Así podrás registrar cada llamada a tu LLM, analizar respuestas y ¡ver todo en tiempo real!
Consejos extra y troubleshooting
-
Migraciones: Ejecuta la migración de base de datos manualmente tras el primer despliegue. Puedes hacerlo creando un pod temporal usando la imagen de langfuse y ejecutando el comando de
prisma migrate deploy
. -
Persistencia: Sustituye
emptyDir: {}
por un PersistentVolumeClaim real en producción. -
Pruebas iniciales: Accede a
https://langfuse.midominio.com
y registra tu primer usuario. -
Problemas comunes: Si la app da error 500, revisa logs de
langfuse-app
y que la base de datos esté accesible.