
Eco²
Backend · Cloud infrastructure
Orientação de reciclagem a partir de uma foto e de uma conversa.
Um assistente de IA tudo-em-um que entende como funciona a reciclagem na Coreia.
Eco² vocabulary
- edge
- auth offload
- domain api
- task queue
- scan pipeline
- chat agent
- event bus
- cluster
- gitops
- autoscaling
- observability
- load test
- evaluation
Edge: ROUTE 53 · ALB · HTTPS 443 · internet-facing · external-dns · istio-ingressgateway · NodePort · eco2-gateway · VirtualService · x-canary · AuthorizationPolicy · ENVOY SIDECAR · kiali-serverAuth Offload: AuthorizationPolicy · action: CUSTOM · notPaths · envoyExtAuthzGrpc · failOpen: false · CheckRequest · x-user-id · BlacklistCache · BootstrapFromRedis · outbox:blacklist · blacklist.events · UsersServiceDomain API: VirtualService · x-user-id · /api/v1/scan · X-Idempotency-Key · job_id · stream_url · 202 ACCEPTED · Retry-After · ScanTask · UsersService · ImageService · ENVOY SIDECARTask Queue: outbox:blacklist · blacklist.events · RabbitmqCluster · scan.direct · reward.events · dlx · x-dead-letter-exchange · chat.process · AioPikaBroker · task_acks_late · apply_async · gevent · scan.vision · scan.rule · scan.answer · scan.reward · CELERY CHAIN · QueueLength · inspect ping · QUEUE SATURATIONScan Pipeline: ScanTask · scan.direct · reward.events · apply_async · gevent · scan.vision · scan.rule · scan.answer · scan.reward · CELERY CHAIN · RewardStep · item_class_list.yaml · situation_tags.yaml · LITE RAG · JsonRegulationRetriever · PipelineStage · waste_rag · XADD · domain: worker-ai · pipeline_duration · vision_stage_durationChat Agent: ImageService · chat.process · AioPikaBroker · create_chat_graph · route_by_intent · MULTI-INTENT FANOUT · waste_rag · recyclable_price · collection_point · image_generation · aggregator · thread_id · SyncableRedisSaver · AsyncPostgresSaver · LANGSMITH_TRACING · regenerateEvent Bus: job_id · stream_url · PipelineStage · XADD · scan:events:{shard} · XREADGROUP · XACK · XAUTOCLAIM · PendingReclaimer · STATE KV · scan:state:{job_id} · sse:events:{shard} · SSEBroadcastManager · Last-Event-ID · scan_sse_connections_active · ServiceMonitor · traceparentCluster: NodePort · kubeadm init · kubeadm join · vxlanMode · BGPConfiguration · module "vpc" · worker_ai · nodeSelector · domain: worker-ai · NoSchedule · 24-NODE CLUSTERGitOps: external-dns · x-canary · dev-root · ApplicationSet · sync-wave · selfHeal · ignoreDifferences · argocd-image-updater · update-strategy: digest · write-back-method · targetRevision · ci-services.ymlAutoscaling: ignoreDifferences · ScaledObject · QueueLength · cooldownPeriod · pollingInterval · fallback · maxReplicaCount · stabilizationWindowSeconds · HorizontalPodAutoscaler · scan_sse_connections_active · prometheus-adapterObservability: 24-NODE CLUSTER · prometheus-adapter · FLUENT BIT · Elasticsearch · Kibana · kube-prometheus-stack · AlertmanagerConfig · ServiceMonitor · JAEGER · OPENTELEMETRY · traceparent · kiali-server · LANGSMITH_TRACINGLoad Test: k6 · ramping-vus · thresholds · pipeline_duration · vision_stage_duration · poll_timeout · inspect ping · WORKER RESTART · POLLING TIMEOUT · QUEUE SATURATIONEvaluation: EvalConfig · eval_mode · eval_sample_rate · eval_cost_budget_daily_usd · EvalResult · EvalGrade · code_grader · llm_grader · CUSUM · regenerate · OpenAIBARSEvaluator
Como os 24 nós se conectam de fato, um fluxo de cada vez.
Kubernetes autogerenciado, construído com kubeadm. O mapa coloca os 24 nós físicos e seus workloads dentro das cinco camadas do README e os liga por suas conexões reais. Ao escolher um fluxo, só esse caminho é destacado, com etapas numeradas.
Ele identifica o resíduo a partir de uma foto e explica como descartá-lo, e na conversa chama ferramentas de locais, clima, preços de recicláveis e busca na web, e gera imagens. Neste projeto em equipe, comecei pelo cluster e pela base de implantação e ampliei meu escopo para o backend de domínio, o processamento assíncrono, o agente conversacional e a verificação.
Do desenvolvimento para a competição ao reforço do backend e da operação
O serviço encerrou sua operação; uma demo gravada e o relatório técnico o mostram em funcionamento.
Requisição do Scan → entrega ao vivo
Uma requisição de análise de foto vira trabalho na fila, e seus eventos de progresso voltam ao mesmo navegador.
Navegadorconsulta DNS: Consulta DNSRoute 53
Só o nome é resolvido a partir dos registros do Route 53. As requisições não passam pelo DNS.
Navegadorfluxo de dados: HTTPS 443AWS ALB
O TLS termina no ALB.
AWS ALBfluxo de dados: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayEntregue ao Envoy de ingress do Istio pelo NodePort do destino de instância EC2.
Istio ingress Envoy
k8s-ingress-gatewayfluxo de dados: VirtualServiceScan APIk8s-api-scanRoteado para a API do Scan, que enfileira o trabalho e devolve um job_id na hora; a consulta do resultado responde 202 até o job terminar.
Scan API
k8s-api-scanfluxo de dados: Tarefa CeleryRabbitMQk8s-rabbitmqA tarefa do Scan vai para o RabbitMQ.
RabbitMQ
k8s-rabbitmqfluxo de dados: consumescan-workerk8s-worker-ai · k8s-worker-ai-2O scan-worker (Celery · gevent), no pool de IA, a recebe e executa Vision → Rule → Answer → Reward. As quatro etapas são tarefas do Celery encadeadas, não nós.
Pool de IA
k8s-worker-ai · k8s-worker-ai-2fluxo de dados: HTTPSLLM APIOs workers de scan e chat chamam as APIs da OpenAI e do Google.
scan-worker
k8s-worker-ai · k8s-worker-ai-2fluxo de dados: XADD scan:eventsStreamsk8s-redis-streamsOs eventos de progresso são gravados em um dos quatro shards do Streams.
Streams
k8s-redis-streamsfluxo de dados: XREADGROUPEvent Routerk8s-event-routerO Event Router os lê como consumer group e faz XACK após processá-los; pending e reclaim mantêm a entrega at-least-once.
Event Router
k8s-event-routerfluxo de dados: SETEX stateState KVk8s-redis-streamsGrava o estado mais recente e um marcador de processamento duplicado no State KV, no mesmo nó Redis.
Event Router
k8s-event-routerfluxo de dados: PUBLISHPub/Subk8s-redis-pubsubEntregue em tempo real no canal do job, no Pub/Sub de shard.
Pub/Sub
k8s-redis-pubsubfluxo de dados: SUBSCRIBESSE Gatewayk8s-sse-gatewayO SSE Gateway assina por meio de um único listener compartilhado por processo e distribui para cada navegador conectado.
SSE Gateway
k8s-sse-gatewayfluxo de dados: Stream SSENavegadorUma conexão aberta pelo mesmo caminho de ALB e ingress. A entrega é at-least-once; duplicatas são tratadas de forma idempotente.
State KV
k8s-redis-streamsfluxo de dados: Recuperação na reconexãoSSE Gatewayk8s-sse-gatewayNa reconexão com Last-Event-ID, o State KV e os Streams retidos preenchem os eventos perdidos.
Chat · tokens e armazenamento
Os tokens do Chat seguem o mesmo caminho de eventos do Scan; checkpoints e mensagens são armazenados por dois workloads diferentes.
Navegadorfluxo de dados: HTTPS 443AWS ALB
O TLS termina no ALB.
AWS ALBfluxo de dados: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayEntregue ao Envoy de ingress do Istio pelo NodePort do destino de instância EC2.
Istio ingress Envoy
k8s-ingress-gatewayfluxo de dados: VirtualServiceChat APIk8s-api-chatRoteado para a API do Chat.
Chat API
k8s-api-chatfluxo de dados: Tarefa TaskiqRabbitMQk8s-rabbitmqA tarefa do Chat vai para o RabbitMQ.
RabbitMQ
k8s-rabbitmqfluxo de dados: consumechat-workerk8s-worker-ai · k8s-worker-ai-2O chat-worker (Taskiq · asyncio) classifica a intenção com LangGraph, depois executa a visão se necessário, as ferramentas selecionadas, o agregador e um resumo se necessário, e responde. Cada requisição executa só os ramos de que precisa.
Pool de IA
k8s-worker-ai · k8s-worker-ai-2fluxo de dados: HTTPSLLM APIOs workers de scan e chat chamam as APIs da OpenAI e do Google.
chat-worker
k8s-worker-ai · k8s-worker-ai-2fluxo de dados: XADD chat:eventsStreamsk8s-redis-streamsTokens e eventos de etapa são gravados em quatro shards do Streams; dali em diante, o caminho de entrega é o mesmo do Scan.
Streams
k8s-redis-streamsfluxo de dados: XREADGROUPEvent Routerk8s-event-routerO Event Router os lê como consumer group e faz XACK após processá-los; pending e reclaim mantêm a entrega at-least-once.
Event Router
k8s-event-routerfluxo de dados: PUBLISHPub/Subk8s-redis-pubsubEntregue em tempo real no canal do job, no Pub/Sub de shard.
Pub/Sub
k8s-redis-pubsubfluxo de dados: SUBSCRIBESSE Gatewayk8s-sse-gatewayO SSE Gateway assina por meio de um único listener compartilhado por processo e distribui para cada navegador conectado.
SSE Gateway
k8s-sse-gatewayfluxo de dados: Stream SSENavegadorUma conexão aberta pelo mesmo caminho de ALB e ingress. A entrega é at-least-once; duplicatas são tratadas de forma idempotente.
chat-worker
k8s-worker-ai · k8s-worker-ai-2fluxo de dados: checkpointCachek8s-redis-cacheO checkpoint do LangGraph fica no Redis Cache.
Cache
k8s-redis-cachefluxo de dados: ler o checkpointcheckpoint-syncerk8s-worker-ai · k8s-worker-ai-2O checkpoint-syncer lê o checkpoint do Redis.
checkpoint-syncer
k8s-worker-ai · k8s-worker-ai-2fluxo de dados: sincronizar com o PostgreSQLPostgreSQLk8s-postgresqlO AsyncPostgresSaver o armazena no PostgreSQL de forma assíncrona.
Streams
k8s-redis-streamsfluxo de dados: chat-persistence grouppersistence consumerk8s-api-chatO persistence consumer do nó do Chat lê os eventos done como consumer group.
persistence consumer
k8s-api-chatfluxo de dados: salvar mensagensPostgreSQLk8s-postgresqlAs mensagens do Chat são salvas no PostgreSQL. É um workload diferente do checkpoint-syncer.
Entrada · autenticação
O caminho síncrono da entrada do cluster até uma API de domínio. Só os caminhos protegidos por política verificam a autenticação primeiro; o tráfego de pods entre nós passa pelo Calico VXLAN.
Navegadorconsulta DNS: Consulta DNSRoute 53
Só o nome é resolvido a partir dos registros do Route 53. As requisições não passam pelo DNS.
Navegadorfluxo de dados: HTTPS 443AWS ALB
O TLS termina no ALB.
AWS ALBfluxo de dados: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayEntregue ao Envoy de ingress do Istio pelo NodePort do destino de instância EC2.
Istio ingress Envoy
k8s-ingress-gatewayfluxo de dados: ext-authz · gRPC 50051ext-authzk8s-api-authSó os caminhos sob uma política CUSTOM consultam primeiro o ext-authz em Go (timeout de 2 s, failOpen false). Caminhos como login, health e docs ficam de fora.
ext-authz
k8s-api-authfluxo de dados: consulta à blacklistblacklistk8s-redis-authO token é verificado na blacklist do Redis.
Istio ingress Envoy
k8s-ingress-gatewayfluxo de dados: VirtualServiceChat APIk8s-api-chatRoteado para a API do Chat.
Chat API
k8s-api-chatfluxo de dados: gRPCimages APIk8s-api-imageA chamada síncrona chat → images citada no README.
auth API
k8s-api-authfluxo de dados: gRPCusers APIk8s-api-usersA chamada síncrona auth → users citada no README.
Pool de armazenamento · gravações assíncronas
A blacklist de autenticação e a posse dos personagens são armazenadas pelos workers do pool de armazenamento, que recebem o trabalho do RabbitMQ.
blacklist
k8s-redis-authfluxo de dados: outbox:blacklistauth-relayk8s-worker-storage · k8s-worker-storage-2O auth-relay (o auth-Bus do README) lê o outbox do Redis.
auth-relay
k8s-worker-storage · k8s-worker-storage-2fluxo de dados: blacklist.eventsRabbitMQk8s-rabbitmqEle republica no RabbitMQ, com novas tentativas e uma DLQ.
RabbitMQ
k8s-rabbitmqfluxo de dados: blacklist.eventsauth-workerk8s-worker-storage · k8s-worker-storage-2O auth-worker recebe os eventos da blacklist.
auth-worker
k8s-worker-storage · k8s-worker-storage-2fluxo de dados: armazenar a blacklistblacklistk8s-redis-authEles são armazenados na blacklist do Redis.
RabbitMQ
k8s-rabbitmqfluxo de dados: Celery batchusers-workerk8s-worker-storage · k8s-worker-storage-2O users-worker recebe em lotes o trabalho de posse de personagens.
users-worker
k8s-worker-storage · k8s-worker-storage-2fluxo de dados: UPSERTPostgreSQLk8s-postgresqlÉ aplicado ao PostgreSQL.
Configurar · escalar · observar
A Platform Layer não é uma etapa pela qual as requisições passam; ela implanta, configura, escala e observa as outras camadas. Os nós são instâncias EC2 criadas com Terraform, com kubeadm e Calico instalados pelo Ansible; a CI só valida o Terraform e nunca o aplica automaticamente.
GitHub Actions · Docker Hubconfiguração · escala: imagem · revisão de manifestArgo CD image updater
k8s-masterO Argo CD alinha a configuração do cluster por App-of-Apps e Sync Waves. Só a alocação do image updater no control plane foi confirmada.
ALB Controller · ExternalDNS
k8s-masterconfiguração · escala: Ingress → ALB · registros DNSGerenciado pela AWSO ALB Controller e o ExternalDNS configuram os recursos do lado da AWS. Não é um caminho pelo qual as requisições passam.
Istiod
k8s-masterconfiguração · escala: Configuração xDSIstio ingress Envoyk8s-ingress-gatewayO Istiod envia via xDS a configuração de Gateway, VirtualService e EnvoyFilter ao Envoy de ingress e ao sidecar Envoy de cada API.
KEDA
k8s-monitoringconfiguração · escala: número de podsPool de IAk8s-worker-ai · k8s-worker-ai-2O KEDA ajusta o número de pods dos workers. O número de nós não muda.
KEDA
k8s-monitoringconfiguração · escala: número de podspool de armazenamentok8s-worker-storage · k8s-worker-storage-2Os pods dos workers do pool de armazenamento são escalados da mesma forma.
Fluent Bitobservabilidade: logsElasticsearch
k8s-loggingO Fluent Bit é um DaemonSet em todos os nós e envia os logs ao Elasticsearch.
Pool de IA
k8s-worker-ai · k8s-worker-ai-2observabilidade: rastreamento de execuções de LLMLangSmithOs traces das chamadas de LLM vão para o LangSmith, um SaaS externo.
Todas as conexões com a mesma espessura. Escolha um fluxo para destacar só o caminho dele, com etapas numeradas.
- Contínua · direção em que fluem requisições, trabalho, eventos e gravações
- Pontilhada · consulta DNS; as requisições não passam por ela
- Tracejada · configuração ou escala; não é um caminho de dados
- Traço e ponto longos · logs e rastreamento de execuções
- Linha preta grossa · o fluxo selecionado; os números dão a ordem
- Caixa · um nó físico, com o nome do host no cabeçalho
- Chip interno · uma carga de trabalho rodando nesse nó
- Moldura tracejada · um pool de agendamento de dois nós
- Caixa tracejada · fora do cluster, não contada como nó
- Contorno laranja · onde um modelo decide
- Control plane1 nó
- Domain API8 nós
- Pool de IA2 nós
- pool de armazenamento2 nós
- Data5 nós
- Platform6 nós
As cinco camadas do README (as faixas) e os grupos físicos (o tom do cabeçalho de cada nó) agrupam de forma diferente os mesmos 24 nós. O State KV compartilha o nó do Streams e não é contado à parte; Route 53, o ALB e os serviços fora do cluster não são nós. Um pool é um intervalo de scheduling, não a afirmação de que todo pod roda nos dois nós.
24nós
24 = 1 control plane + 8 API + 4 worker + 5 data + 6 platform
1Control plane
role: control-planekube-apiserver · scheduler · controller-manager · etcd, além dos controladores da plataforma.
- k8s-master
8Domain API
domain: <serviço>Um nó por domínio. As chamadas internas usam gRPC.
- k8s-api-auth
- k8s-api-users
- k8s-api-scan
- k8s-api-character
- k8s-api-location
- k8s-api-image
- k8s-api-chat
- k8s-api-info
4Execution worker
Dois pools de scheduling de dois nós cada. O KEDA muda o número de pods; o número de nós continua o mesmo.
pool de armazenamento
domain: worker-storage- k8s-worker-storage
- k8s-worker-storage-2
Pool de IA
domain: worker-ai- k8s-worker-ai
- k8s-worker-ai-2
5Data
O Redis é dividido em quatro nós por finalidade. O armazenamento do PostgreSQL é EBS CSI · gp3.
- k8s-postgresql
- k8s-redis-auth
- k8s-redis-streams
- k8s-redis-cache
- k8s-redis-pubsub
6Platform
Mensageria, observabilidade, ingress e entrega em tempo real têm cada um seu próprio nó.
- k8s-rabbitmq
- k8s-monitoring
- k8s-logging
- k8s-ingress-gateway
- k8s-sse-gateway
- k8s-event-router
- Todos os nós
- Fluent Bit · DaemonSet
- Calico
Modelos configurados · por provedor
O serviço foi encerrado, então estes são os modelos configurados no repositório, não opções disponíveis hoje. Cada papel aparece separado; não é uma lista de execuções verificadas.
OpenAI
Provedor padrão do Chat
Chat
openai/gpt-5.2padrão
O modelo padrão é gpt-5.2; um modelo indicado na requisição é usado no lugar.
Scan
gpt-5.2padrãogpt-5.2-progpt-5.1gpt-5gpt-5-progpt-5-mini
Modelos fora do mapeamento de 13 modelos são rejeitados.
Mapeamento de imagens
gpt-image-1.5
Separado do gpt-5.2, o modelo de orquestração do Responses. A geração de imagens fica desligada por padrão.
Avaliação
gpt-4o-minipadrão
O corretor LLM da avaliação de conversas, separado do modelo do Chat.
Google
Quando o Chat escolhe o Google
Chat
google/gemini-3-pro-previewgoogle/gemini-3-flash-preview
Com o Google selecionado, gemini-3-flash-preview é o padrão.
Scan
gemini-3-pro-previewgemini-3-flash-previewgemini-2.5-progemini-2.5-flashgemini-2.5-flash-litegemini-2.0-flashgemini-2.0-flash-lite
Mapeamento de imagens
gemini-3-pro-image-preview
Fontebackend main d8840c7Commit público de September 29, 2026 · verificado em October 8, 2026