Despliega Langfuse en Kubernetes: Observabilidad y trazabilidad para LLMs (¡como un pro!)

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.
Avatar

Por Mid