2026-05-07 13:09:13 -03:00
2026-05-07 13:02:13 -03:00
2026-05-07 13:02:13 -03:00
2026-05-07 13:09:13 -03:00
2026-05-07 13:09:13 -03:00
2026-05-07 13:09:13 -03:00

🚀 Tutorial Completo — Deploy do Langfuse no Oracle Kubernetes Engine (OKE)

📌 Introdução

Este tutorial apresenta um processo completo para implantação do Langfuse no Oracle Cloud Infrastructure (OCI), utilizando:

  • Oracle Kubernetes Engine (OKE)
  • OCI Container Registry (OCIR)
  • OCI Vault
  • OCI Object Storage
  • PostgreSQL
  • Redis
  • ClickHouse

Além do deployment em si, este tutorial cobre:

  • arquitetura do Langfuse
  • conceitos fundamentais
  • purpose de cada componente
  • gerenciamento de imagens Docker
  • secrets centralizados no OCI Vault
  • preparação de ambiente
  • deployment automatizado via Kubernetes YAML

🧠 O que é o Langfuse

Langfuse é uma plataforma de observabilidade para aplicações de IA generativa.

Ele permite:

  • rastrear chamadas de LLM
  • armazenar traces
  • monitorar prompts
  • analisar custos
  • acompanhar latência
  • versionar prompts
  • inspecionar tool calls
  • avaliar qualidade de respostas

🏗️ Arquitetura Geral

Componentes:

  • PostgreSQL
  • Redis
  • ClickHouse
  • Langfuse API
  • Langfuse Worker
  • OCI Vault
  • OCI Object Storage
  • OCIR
  • OKE

🔐 OCI Vault

Os scripts create_secrets.sh e update_secret.sh criam e atualizam secrets no OCI Vault.

Antes de iniciar esta etapa, crie um VAULT e UMA ENCRYPTION KEY. Busque pelos OCID destes 2 componentes para setar dentro de seu script create_secrets.sh e update_secret.sh

A ENCRYPTION_KEY precisa possuir:

  • 64 caracteres
  • hexadecimal
  • 256 bits

Exemplo:

ENCRYPTION_KEY=$(openssl rand -hex 32)

📦 OCI Registry (OCIR)

O script mirror_images.sh copia imagens públicas para o registry privado OCI.

Exemplo:

docker pull langfuse/langfuse:3.1.0

docker tag langfuse/langfuse:3.1.0 iad.ocir.io/namespace/langfuse:3.1.0

docker push iad.ocir.io/namespace/langfuse:3.1.0

O mesmo ocorre para:

  • langfuse-worker
  • redis
  • postgres
  • clickhouse

☸️ Kubernetes Deployment

O arquivo final.yaml contém:

  • StorageClass
  • PVCs
  • Deployments
  • StatefulSets
  • Services
  • HPA

PostgreSQL

Responsável por:

  • usuários
  • traces
  • prompts
  • configurações

Readiness probe:

pg_isready -U langfuse

Redis

Responsável por:

  • filas
  • cache
  • jobs

ClickHouse

Responsável por:

  • analytics
  • métricas
  • observabilidade

Langfuse API

Responsável por:

  • UI
  • API
  • autenticação

Langfuse Worker

Responsável por:

  • filas
  • processamento assíncrono
  • exports

initContainers

Utilizados para aguardar:

  • PostgreSQL
  • Redis
  • ClickHouse

antes da inicialização dos pods.

Exemplo:

until nc -z langfuse-db 5432

🌐 OCI Load Balancer

Service utilizado:

kind: Service
type: LoadBalancer

Healthcheck:

oci.oraclecloud.com/healthcheck-path: "/api/public/health"

☁️ OCI Object Storage

Utilizado para:

  • eventos
  • batches
  • exports

Auth utilizada:

LANGFUSE_OCI_AUTH_TYPE=instance_principal

⚙️ Principais Variáveis

Variável Função
DATABASE_URL PostgreSQL
REDIS_AUTH Redis
CLICKHOUSE_PASSWORD ClickHouse
NEXTAUTH_SECRET Auth
ENCRYPTION_KEY Criptografia
SALT Salt
NEXTAUTH_URL URL pública

📦 Fluxo Completo — Imagens, OCI Vault e Deployment Final

🎯 Objetivo

Antes do deployment do Langfuse no Oracle Kubernetes Engine (OKE), existem algumas etapas preparatórias fundamentais.

Essas etapas possuem dois objetivos principais:

  1. Centralizar imagens Docker em um registry privado OCI (OCIR)
  2. Centralizar secrets no OCI Vault para que o deployment Kubernetes possa consumir valores seguros dinamicamente

O fluxo completo funciona assim:

Docker Hub
    ↓
Mirror para OCI Registry (OCIR)
    ↓
Criação de Secrets no OCI Vault
    ↓
Captura dos OCIDs dos Secrets
    ↓
Leitura dinâmica via OCI CLI
    ↓
envsubst
    ↓
Geração do final.yaml
    ↓
kubectl apply

Nota: Antes de iniciar o processo de deployment, certifque-se de que exista um dynamic group e as policies estejam de acordo na OCI.

Dynamic Group oke-langfuse: ALL {instance.compartment.id = 'ocid1.compartment.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}

  • Todos os recursos deste compartment estarão habilitados para as policies abaixo

Algumas policies importantes:

  • Allow dynamic-group oke-langfuse to manage objects in compartment kubernetes
  • Allow dynamic-group oke-langfuse to read buckets in compartment kubernetes
  • Allow dynamic-group oke-langfuse to manage volume-family in compartment kubernetes

🟢 Etapa 1 — Publicar Imagens no OCI Registry (OCIR)

📌 Objetivo

O Kubernetes do OKE precisa baixar imagens Docker.

Embora seja possível utilizar imagens públicas diretamente do Docker Hub, em ambientes corporativos normalmente utilizamos um registry privado OCI por motivos de:

  • segurança
  • governança
  • performance
  • disponibilidade
  • controle de versões
  • evitar rate limit do Docker Hub

📦 Imagens utilizadas

O deployment utiliza:

Imagem Função
langfuse/langfuse API/UI
langfuse/langfuse-worker Worker
postgres Banco
redis Cache
clickhouse/clickhouse-server Analytics

🔄 Processo de Mirror

O script:

mirror_images.sh

executa:

  1. Pull da imagem pública
  2. Tag para o OCIR
  3. Push para o registry OCI

Exemplo

Pull

docker pull langfuse/langfuse:3.1.0

Tag

docker tag langfuse/langfuse:3.1.0 iad.ocir.io/namespace/langfuse:3.1.0

Push

docker push iad.ocir.io/namespace/langfuse:3.1.0

📌 Resultado Final

Após isso, o Kubernetes utilizará:

iad.ocir.io/SEU_NAMESPACE/langfuse:3.1.0

em vez da imagem pública.


🔐 Etapa 2 — Criar Secrets no OCI Vault

📌 Objetivo

O deployment possui:

  • senhas
  • tokens
  • chaves de criptografia

Esses valores NÃO devem ficar hardcoded no YAML.

Por isso usamos:

  • OCI Vault
  • OCI KMS

🧠 Secrets utilizados

Secret Finalidade
DB_PASSWORD PostgreSQL
REDIS_AUTH Redis
CLICKHOUSE_PASSWORD ClickHouse
NEXTAUTH_SECRET Auth Langfuse
ENCRYPTION_KEY Criptografia interna
SALT Salt interno

🔧 Script utilizado

Arquivo:

create_secrets.sh

📌 Como funciona

O script:

  1. Gera senhas
  2. Gera ENCRYPTION_KEY
  3. Codifica em Base64
  4. Cria os secrets no OCI Vault

🔐 ENCRYPTION_KEY

A variável:

ENCRYPTION_KEY=$(openssl rand -hex 32)

gera:

  • 32 bytes
  • 64 chars hex
  • 256 bits

Formato obrigatório do Langfuse.


📤 Resultado do Script

Ao final, o OCI Vault retorna:

export OCI_SECRET_DB=ocid1.vaultsecret...

Esses valores são os:

  • OCIDs dos secrets

🧠 O que é o OCID do Secret?

Cada secret criado no OCI Vault recebe um identificador único:

ocid1.vaultsecret.oc1....

Esse OCID é utilizado depois para:

  • localizar
  • ler
  • atualizar

o conteúdo do secret.


🔥 Etapa 3 — Capturar os OCIDs

📌 Objetivo

Os scripts seguintes precisam saber:

  • qual secret acessar
  • onde buscar a senha

Por isso os OCIDs precisam ser armazenados.


📌 Exemplo

export OCI_SECRET_DB="ocid1.vaultsecret.oc1..."

📌 Utilização

Esses OCIDs serão utilizados no:

set_var.sh

⚙️ Etapa 4 — Carregar Secrets Dinamicamente

📌 Objetivo

Antes de gerar o YAML final:

  • precisamos buscar os valores reais no OCI Vault

🔧 Função utilizada

get_secret() {

  oci secrets secret-bundle get \
    --secret-id "$secret_ocid" \
    --query 'data."secret-bundle-content".content' \
    --raw-output | base64 --decode
}

📌 O que ocorre aqui

O script:

  1. Chama OCI CLI
  2. Busca o secret
  3. Recebe Base64
  4. Decodifica
  5. Exporta para variável de ambiente

📌 Exemplo

export DB_PASSWORD=$(get_secret "$OCI_SECRET_DB")

📌 Resultado

Agora temos:

export DB_PASSWORD="senha_real"

em memória no shell.


🧩 Etapa 5 — Construção do final.yaml

📌 Objetivo

O arquivo:

langfuse_dest.yaml

possui placeholders:

${DB_PASSWORD}

⚙️ Variáveis de Ambiente — Langfuse no OKE

📌 Introdução

O deployment do Langfuse depende de diversas variáveis de ambiente responsáveis por configurar:

  • banco de dados
  • cache
  • analytics
  • autenticação
  • object storage
  • OCI
  • imagens
  • Kubernetes
  • URLs
  • segurança

Essas variáveis são carregadas principalmente pelo:

set_var.sh

e posteriormente injetadas no:

final.yaml

através do:

envsubst

🧩 Variáveis de Configuração OCI


OCI_PROFILE

export OCI_PROFILE=DEFAULT

Objetivo

Define qual profile do OCI CLI será utilizado.

Origem

Arquivo:

~/.oci/config

Exemplo

[DEFAULT]
user=...
fingerprint=...
tenancy=...
region=...

OCI_REGION

export OCI_REGION=us-ashburn-1

Objetivo

Define a região OCI utilizada por:

  • Vault
  • Object Storage
  • Registry
  • APIs OCI

Exemplos

Região Valor
Ashburn us-ashburn-1
São Paulo sa-saopaulo-1

OCI_NAMESPACE

export OCI_NAMESPACE="idavixsf5sbx"

Objetivo

Namespace do OCI Object Storage e OCIR.

Utilizado em:

  • Registry
  • Bucket endpoints

📦 Variáveis do OCI Registry (OCIR)


REGION

export REGION="iad"

Objetivo

Região curta utilizada pelo OCIR.

Exemplos

Região OCI Short Name
us-ashburn-1 iad
sa-saopaulo-1 gru

TENANCY_NAMESPACE

export TENANCY_NAMESPACE=${OCI_NAMESPACE}

Objetivo

Namespace do tenancy no OCIR.


REGISTRY

export REGISTRY="${REGION}.ocir.io/${TENANCY_NAMESPACE}"

Resultado

iad.ocir.io/idavixsf5sbx

Objetivo

Registry privado OCI utilizado pelo Kubernetes.


🧠 Variáveis do Deployment


APP_NAME

export APP_NAME="langfuse"

Objetivo

Prefixo dos recursos Kubernetes.

Exemplos

Gera:

  • langfuse-db
  • langfuse-redis
  • langfuse-clickhouse

K8S_NAMESPACE

export K8S_NAMESPACE="langfuse"

Objetivo

Namespace Kubernetes onde os recursos serão criados.


IMAGE_REPOSITORY

export IMAGE_REPOSITORY="${REGISTRY}"

Objetivo

Define o registry utilizado pelas imagens.

Resultado

iad.ocir.io/idavixsf5sbx

IMAGE_TAG

export IMAGE_TAG="3.1.0"

Objetivo

Tag da imagem principal Langfuse.


CLICKHOUSE_TAG

export CLICKHOUSE_TAG="23.8"

Objetivo

Versão do ClickHouse.


REDIS_TAG

export REDIS_TAG="7.2"

Objetivo

Versão Redis.


POSTGRES_TAG

export POSTGRES_TAG="15"

Objetivo

Versão PostgreSQL.


🌐 Variáveis de URL


NEXTAUTH_URL

export NEXTAUTH_URL="https://langfuse.seudominio.com"

Objetivo

URL pública utilizada pelo frontend do Langfuse.

Impacto

Utilizada para:

  • login
  • redirects
  • cookies
  • OAuth

🔐 Variáveis de Secrets OCI Vault


OCI_SECRET_DB

export OCI_SECRET_DB="ocid1.vaultsecret..."

Objetivo

OCID do secret contendo a senha PostgreSQL.


OCI_SECRET_REDIS

export OCI_SECRET_REDIS="ocid1.vaultsecret..."

Objetivo

OCID do secret Redis.


OCI_SECRET_CLICKHOUSE

export OCI_SECRET_CLICKHOUSE="ocid1.vaultsecret..."

Objetivo

OCID da senha ClickHouse.


OCI_SECRET_NEXTAUTH

export OCI_SECRET_NEXTAUTH="ocid1.vaultsecret..."

Objetivo

Secret de autenticação do Langfuse.


OCI_SECRET_ENCRYPTION

export OCI_SECRET_ENCRYPTION="ocid1.vaultsecret..."

Objetivo

Secret utilizado para criptografia interna.


OCI_SECRET_SALT

export OCI_SECRET_SALT="ocid1.vaultsecret..."

Objetivo

Salt interno do Langfuse.


🔥 Variáveis Carregadas Dinamicamente

Estas variáveis são carregadas via:

get_secret()

DB_PASSWORD

export DB_PASSWORD=$(get_secret "$OCI_SECRET_DB")

Objetivo

Senha PostgreSQL.


DATABASE_URL

export DATABASE_URL="postgresql://langfuse:${DB_PASSWORD}@${APP_NAME}-db:5432/langfuse"

Objetivo

Connection string PostgreSQL.

Estrutura

postgresql://USUARIO:SENHA@HOST:PORTA/BANCO

REDIS_AUTH

export REDIS_AUTH=$(get_secret "$OCI_SECRET_REDIS")

Objetivo

Senha Redis.


CLICKHOUSE_PASSWORD

export CLICKHOUSE_PASSWORD=$(get_secret "$OCI_SECRET_CLICKHOUSE")

Objetivo

Senha ClickHouse.


NEXTAUTH_SECRET

export NEXTAUTH_SECRET=$(get_secret "$OCI_SECRET_NEXTAUTH")

Objetivo

Secret JWT/Auth do Langfuse.


ENCRYPTION_KEY

export ENCRYPTION_KEY=$(get_secret "$OCI_SECRET_ENCRYPTION")

Objetivo

Criptografia interna.

Requisitos

  • 64 chars
  • hexadecimal
  • 256 bits

Validação

openssl rand -hex 32

SALT

export SALT=$(get_secret "$OCI_SECRET_SALT")

Objetivo

Salt interno utilizado pelo Langfuse.


Redis


REDIS_HOST

export REDIS_HOST="${APP_NAME}-redis"

Objetivo

Hostname Redis interno Kubernetes.


REDIS_PORT

export REDIS_PORT="6379"

Objetivo

Porta Redis.


📊 ClickHouse


CLICKHOUSE_URL

export CLICKHOUSE_URL="http://${APP_NAME}-clickhouse:8123"

Objetivo

Endpoint HTTP ClickHouse.


CLICKHOUSE_USER

export CLICKHOUSE_USER="default"

Objetivo

Usuário ClickHouse.


CLICKHOUSE_MIGRATION_URL

export CLICKHOUSE_MIGRATION_URL="clickhouse://${APP_NAME}-clickhouse:9000"

Objetivo

Endpoint nativo ClickHouse utilizado pelas migrations.


CLICKHOUSE_CLUSTER_ENABLED

export CLICKHOUSE_CLUSTER_ENABLED="false"

Objetivo

Define se ClickHouse opera em cluster distribuído.


☁️ OCI Object Storage


LANGFUSE_S3_EVENT_UPLOAD_BUCKET

export LANGFUSE_S3_EVENT_UPLOAD_BUCKET="langfuse-events"

Objetivo

Bucket de eventos.


LANGFUSE_S3_EVENT_UPLOAD_REGION

export LANGFUSE_S3_EVENT_UPLOAD_REGION="${OCI_REGION}"

Objetivo

Região do bucket.


LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT

export LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT="https://${OCI_NAMESPACE}.compat.objectstorage.${OCI_REGION}.oraclecloud.com"

Objetivo

Endpoint S3-compatible OCI.


LANGFUSE_USE_OCI_NATIVE_OBJECT_STORAGE

export LANGFUSE_USE_OCI_NATIVE_OBJECT_STORAGE="true"

Objetivo

Ativa integração OCI nativa.


LANGFUSE_OCI_AUTH_TYPE

export LANGFUSE_OCI_AUTH_TYPE="instance_principal"

Objetivo

Utiliza Instance Principal em vez de Access Key.

Benefício

Não precisamos:

  • access key
  • secret key

📌 Resumo Geral

Principais categorias

Categoria Variáveis
OCI OCI_REGION, OCI_PROFILE
Registry REGISTRY, IMAGE_REPOSITORY
Kubernetes APP_NAME, K8S_NAMESPACE
PostgreSQL DATABASE_URL
Redis REDIS_AUTH
ClickHouse CLICKHOUSE_URL
Security NEXTAUTH_SECRET, ENCRYPTION_KEY
OCI Vault OCI_SECRET_*
Object Storage LANGFUSE_S3_*

🚀 Fluxo Completo

OCI Vault
   ↓
get_secret()
   ↓
export VARIAVEIS
   ↓
envsubst
   ↓
final.yaml
   ↓
kubectl apply

Resultado Final

Ao final:

  • todas variáveis ficam centralizadas
  • secrets permanecem seguros
  • deployment torna-se parametrizável
  • ambiente fica reproduzível
  • stack torna-se adequada para CI/CD e produção

🔧 Substituição dinâmica

O script utiliza:

envsubst < langfuse_dest.yaml > final.yaml

📌 O que acontece

O Linux substitui:

${DB_PASSWORD}

por:

langfuse123

📌 Resultado

É gerado:

final.yaml

com:

  • todas variáveis preenchidas
  • senhas reais
  • URLs reais
  • tags reais
  • namespace real

☸️ Etapa 6 — Deployment Kubernetes

📌 Objetivo

Aplicar:

  • Deployments
  • Services
  • StatefulSets
  • PVCs
  • HPAs

no OKE.

Nota: É importante frisar que em regime produtivo, as etapas de gerar imagens, setar variaveis e executar a atualização no YAML de deployment final não são etapas necessárias. Pressupõe-se que as variáveis e as imagens já estejam preparadas para a execução de uma esteira produtiva. Estas etapas anteriores apenas servem para este tutorial como ilustração de como os recursos de OCI se comportam.


🔧 Comando

kubectl apply -f final.yaml

Nota: O arquivo de deployment final.yaml publica a solução em um endpoint com DNS: https://langfuse.seu. Lembre-se de alterar


📌 Resultado

O Kubernetes:

  • cria pods
  • cria services
  • cria volumes
  • cria load balancer
  • sobe Langfuse

🔒 Benefícios dessa Arquitetura

Segurança

Nenhuma senha:

  • hardcoded
  • commitada
  • salva no YAML final do template

Governança

Secrets centralizados no OCI Vault.


Escalabilidade

O mesmo template pode ser usado para:

  • DEV
  • QA
  • PROD

mudando apenas:

  • variáveis
  • secrets
  • tags

Reutilização

O deployment torna-se:

  • parametrizável
  • automatizável
  • CI/CD friendly

🚀 Fluxo Final Consolidado

1. mirror_images.sh
   ↓
2. create_secrets.sh
   ↓
3. capturar OCIDs
   ↓
4. set_var.sh
   ↓
5. envsubst
   ↓
6. final.yaml
   ↓
7. kubectl apply

Testando a Solução

Abra o browser para validar a UI do Langfuse. O Load-Balancer foi criado para uma subnet privada, nada impede de se criar em uma subnet pública. Para poder acessar talvez seja necessário executar o ssh em túnel como o exemplo:

ssh -i /mnt/d/Dropbox/ORACLE/sshkeybundle/Privatekey.pem opc@129.158.211.144 -L 8087:10.0.20.44:80

E depois acessar via browser com:

http://localhost:8087

img.png

img_1.png

img_2.png


Resultado Final

Ao final:

  • imagens privadas OCI
  • secrets centralizados
  • deployment automatizado
  • stack observável
  • Langfuse operacional no OKE
  • arquitetura segura e escalável
Description
No description provided
Readme 479 KiB
Languages
Shell 100%