
Eco²
Backend · Cloud infrastructure
Advies over afvalscheiding uit één foto en een gesprek.
Een alles-in-één AI-assistent die begrijpt hoe afvalscheiding in Korea werkt.
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
Hoe de 24 nodes werkelijk verbonden zijn, stroom voor stroom.
Zelfbeheerde Kubernetes, opgezet met kubeadm. De kaart plaatst de 24 fysieke nodes en de workloads erop binnen de vijf lagen van de README en verbindt ze met hun werkelijke verbindingen. Kies een stroom en alleen dat pad wordt gemarkeerd, met genummerde stappen.
Hij herkent afval op een foto en legt uit hoe het moet worden weggegooid, en in een gesprek roept hij tools aan voor locaties, weer, recyclingprijzen en zoeken op het web, en genereert hij afbeeldingen. In dit teamproject begon ik bij de cluster- en uitrolbasis en breidde ik mijn reikwijdte uit naar de domeinbackend, asynchrone verwerking, de conversationele agent en verificatie.
Van de ontwikkeling voor de wedstrijd tot het verstevigen van backend en beheer
De dienst is niet meer in bedrijf; een opgenomen demo en het technische rapport tonen hem in werking.
Scan-verzoek → live levering
Een verzoek om fotoanalyse wordt werk in de queue, en de voortgangsevents ervan komen terug bij dezelfde browser.
BrowserDNS-lookup: DNS-lookupRoute 53
Alleen de naam wordt opgezocht in de Route 53-records. Verzoeken gaan niet door DNS.
Browserdatastroom: HTTPS 443AWS ALB
TLS eindigt op de ALB.
AWS ALBdatastroom: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayVia de NodePort van het EC2-instancetarget doorgegeven aan de Istio-ingress-Envoy.
Istio ingress Envoy
k8s-ingress-gatewaydatastroom: VirtualServiceScan APIk8s-api-scanGerouteerd naar de Scan-API, die het werk in de queue zet en meteen een job_id teruggeeft; een opvraging van het resultaat antwoordt 202 tot de job klaar is.
Scan API
k8s-api-scandatastroom: Celery-taakRabbitMQk8s-rabbitmqDe Scan-taak gaat RabbitMQ in.
RabbitMQ
k8s-rabbitmqdatastroom: consumescan-workerk8s-worker-ai · k8s-worker-ai-2scan-worker (Celery · gevent) in de AI-pool neemt hem aan en voert Vision → Rule → Answer → Reward uit. De vier fasen zijn aaneengeschakelde Celery-taken, geen nodes.
AI-pool
k8s-worker-ai · k8s-worker-ai-2datastroom: HTTPSLLM APIDe scan- en chatworkers roepen de API’s van OpenAI en Google aan.
scan-worker
k8s-worker-ai · k8s-worker-ai-2datastroom: XADD scan:eventsStreamsk8s-redis-streamsVoortgangsevents worden naar een van vier Streams-shards geschreven.
Streams
k8s-redis-streamsdatastroom: XREADGROUPEvent Routerk8s-event-routerDe Event Router leest ze als consumer group en XACKt na verwerking; pending en reclaim houden de levering at-least-once.
Event Router
k8s-event-routerdatastroom: SETEX stateState KVk8s-redis-streamsHij schrijft de laatste toestand en een markering tegen dubbele verwerking naar State KV op dezelfde Redis-node.
Event Router
k8s-event-routerdatastroom: PUBLISHPub/Subk8s-redis-pubsubIn realtime geleverd op het kanaal van de job in shard-Pub/Sub.
Pub/Sub
k8s-redis-pubsubdatastroom: SUBSCRIBESSE Gatewayk8s-sse-gatewayDe SSE Gateway abonneert via één gedeelde listener per proces en verdeelt naar elke verbonden browser.
SSE Gateway
k8s-sse-gatewaydatastroom: SSE-streamBrowserEen verbinding die over hetzelfde ALB- en ingresspad wordt geopend. Levering is at-least-once; duplicaten worden idempotent afgehandeld.
State KV
k8s-redis-streamsdatastroom: Herstel bij herverbindingSSE Gatewayk8s-sse-gatewayBij herverbinding met Last-Event-ID vullen State KV en de bewaarde Streams gemiste events aan.
Chat · tokens en opslag
Chattokens volgen hetzelfde eventpad als Scan; checkpoints en berichten worden door twee verschillende workloads opgeslagen.
Browserdatastroom: HTTPS 443AWS ALB
TLS eindigt op de ALB.
AWS ALBdatastroom: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayVia de NodePort van het EC2-instancetarget doorgegeven aan de Istio-ingress-Envoy.
Istio ingress Envoy
k8s-ingress-gatewaydatastroom: VirtualServiceChat APIk8s-api-chatGerouteerd naar de Chat-API.
Chat API
k8s-api-chatdatastroom: Taskiq-taakRabbitMQk8s-rabbitmqDe Chat-taak gaat RabbitMQ in.
RabbitMQ
k8s-rabbitmqdatastroom: consumechat-workerk8s-worker-ai · k8s-worker-ai-2chat-worker (Taskiq · asyncio) classificeert de intentie met LangGraph, voert daarna zo nodig vision, de gekozen tools, de aggregator en zo nodig een samenvatting uit, en antwoordt. Elk verzoek voert alleen de takken uit die het nodig heeft.
AI-pool
k8s-worker-ai · k8s-worker-ai-2datastroom: HTTPSLLM APIDe scan- en chatworkers roepen de API’s van OpenAI en Google aan.
chat-worker
k8s-worker-ai · k8s-worker-ai-2datastroom: XADD chat:eventsStreamsk8s-redis-streamsTokens en fase-events worden naar vier Streams-shards geschreven; vanaf daar is het leveringspad hetzelfde als bij Scan.
Streams
k8s-redis-streamsdatastroom: XREADGROUPEvent Routerk8s-event-routerDe Event Router leest ze als consumer group en XACKt na verwerking; pending en reclaim houden de levering at-least-once.
Event Router
k8s-event-routerdatastroom: PUBLISHPub/Subk8s-redis-pubsubIn realtime geleverd op het kanaal van de job in shard-Pub/Sub.
Pub/Sub
k8s-redis-pubsubdatastroom: SUBSCRIBESSE Gatewayk8s-sse-gatewayDe SSE Gateway abonneert via één gedeelde listener per proces en verdeelt naar elke verbonden browser.
SSE Gateway
k8s-sse-gatewaydatastroom: SSE-streamBrowserEen verbinding die over hetzelfde ALB- en ingresspad wordt geopend. Levering is at-least-once; duplicaten worden idempotent afgehandeld.
chat-worker
k8s-worker-ai · k8s-worker-ai-2datastroom: checkpointCachek8s-redis-cacheDe LangGraph-checkpoint staat in Redis Cache.
Cache
k8s-redis-cachedatastroom: checkpoint lezencheckpoint-syncerk8s-worker-ai · k8s-worker-ai-2checkpoint-syncer leest de checkpoint uit Redis.
checkpoint-syncer
k8s-worker-ai · k8s-worker-ai-2datastroom: synchroniseren naar PostgreSQLPostgreSQLk8s-postgresqlAsyncPostgresSaver slaat hem asynchroon op in PostgreSQL.
Streams
k8s-redis-streamsdatastroom: chat-persistence grouppersistence consumerk8s-api-chatDe persistence-consumer op de Chat-node leest done-events als consumer group.
persistence consumer
k8s-api-chatdatastroom: berichten opslaanPostgreSQLk8s-postgresqlChatberichten worden in PostgreSQL opgeslagen. Dit is een andere workload dan checkpoint-syncer.
Ingang · authenticatie
Het synchrone pad van de ingang van het cluster tot een domein-API. Alleen paden onder een policy controleren eerst de authenticatie; Pod-verkeer tussen nodes loopt over Calico VXLAN.
BrowserDNS-lookup: DNS-lookupRoute 53
Alleen de naam wordt opgezocht in de Route 53-records. Verzoeken gaan niet door DNS.
Browserdatastroom: HTTPS 443AWS ALB
TLS eindigt op de ALB.
AWS ALBdatastroom: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayVia de NodePort van het EC2-instancetarget doorgegeven aan de Istio-ingress-Envoy.
Istio ingress Envoy
k8s-ingress-gatewaydatastroom: ext-authz · gRPC 50051ext-authzk8s-api-authAlleen paden onder een CUSTOM-policy vragen eerst de Go-ext-authz (timeout 2 s, failOpen false). Paden zoals login, health en docs zijn uitgezonderd.
ext-authz
k8s-api-authdatastroom: blacklist opzoekenblacklistk8s-redis-authHet token wordt gecontroleerd tegen de Redis-blacklist.
Istio ingress Envoy
k8s-ingress-gatewaydatastroom: VirtualServiceChat APIk8s-api-chatGerouteerd naar de Chat-API.
Chat API
k8s-api-chatdatastroom: gRPCimages APIk8s-api-imageDe synchrone aanroep chat → images die in de README wordt genoemd.
auth API
k8s-api-authdatastroom: gRPCusers APIk8s-api-usersDe synchrone aanroep auth → users die in de README wordt genoemd.
Storagepool · asynchroon opslaan
De authenticatie-blacklist en het personagebezit worden opgeslagen door workers in de storagepool die hun werk uit RabbitMQ halen.
blacklist
k8s-redis-authdatastroom: outbox:blacklistauth-relayk8s-worker-storage · k8s-worker-storage-2auth-relay (de auth-Bus uit de README) leest de Redis-outbox.
auth-relay
k8s-worker-storage · k8s-worker-storage-2datastroom: blacklist.eventsRabbitMQk8s-rabbitmqHij publiceert opnieuw naar RabbitMQ, met retries en een DLQ.
RabbitMQ
k8s-rabbitmqdatastroom: blacklist.eventsauth-workerk8s-worker-storage · k8s-worker-storage-2auth-worker ontvangt de blacklist-events.
auth-worker
k8s-worker-storage · k8s-worker-storage-2datastroom: blacklist opslaanblacklistk8s-redis-authZe worden opgeslagen in de Redis-blacklist.
RabbitMQ
k8s-rabbitmqdatastroom: Celery batchusers-workerk8s-worker-storage · k8s-worker-storage-2users-worker ontvangt werk voor personagebezit in batches.
users-worker
k8s-worker-storage · k8s-worker-storage-2datastroom: UPSERTPostgreSQLk8s-postgresqlHet wordt toegepast op PostgreSQL.
Configureren · schalen · observeren
De Platform Layer is geen stap waar verzoeken doorheen gaan; die rolt uit, configureert, schaalt en observeert de andere lagen. De nodes zijn met Terraform gemaakte EC2-instances, waarop Ansible kubeadm en Calico heeft geïnstalleerd; CI valideert Terraform alleen en past het nooit automatisch toe.
GitHub Actions · Docker Hubconfigureren · schalen: image · manifestrevisieArgo CD image updater
k8s-masterArgo CD brengt de clusterconfiguratie in lijn via App-of-Apps en Sync Waves. Alleen de control-plane-plaatsing van de image updater is bevestigd.
ALB Controller · ExternalDNS
k8s-masterconfigureren · schalen: Ingress → ALB · DNS-recordsBeheerd door AWSDe ALB Controller en ExternalDNS configureren resources aan AWS-zijde. Dit is geen pad dat verzoeken nemen.
Istiod
k8s-masterconfigureren · schalen: xDS-configuratieIstio ingress Envoyk8s-ingress-gatewayIstiod pusht de configuratie van Gateway, VirtualService en EnvoyFilter via xDS naar de ingress-Envoy en naar de Envoy-sidecar van elke API.
KEDA
k8s-monitoringconfigureren · schalen: aantal PodsAI-poolk8s-worker-ai · k8s-worker-ai-2KEDA past het aantal worker-Pods aan. Het aantal nodes verandert niet.
KEDA
k8s-monitoringconfigureren · schalen: aantal Podsstoragepoolk8s-worker-storage · k8s-worker-storage-2Worker-Pods in de storagepool worden op dezelfde manier geschaald.
Fluent Bitobserveerbaarheid: logsElasticsearch
k8s-loggingFluent Bit is een DaemonSet op elke node en stuurt logs naar Elasticsearch.
AI-pool
k8s-worker-ai · k8s-worker-ai-2observeerbaarheid: LLM-run-tracingLangSmithLLM-aanroeptraces gaan naar LangSmith, een externe SaaS.
Alle verbindingen even zwaar. Kies een stroom om alleen het pad daarvan te markeren, met genummerde stappen.
- Doorgetrokken · richting waarin verzoeken, werk, events en schrijfacties stromen
- Gestippeld · DNS-lookup; verzoeken gaan er niet doorheen
- Gestreept · configureren of schalen; geen datapad
- Lange streep-punt · logs en run-tracing
- Dikke zwarte lijn · de gekozen stroom; nummers geven de volgorde
- Vak · een fysieke node, hostnaam in de kop
- Binnenchip · een workload die op die node draait
- Gestreept kader · een schedulingpool van twee nodes
- Gestreept vak · buiten het cluster, niet als node geteld
- Oranje omlijning · waar een model beslist
- Control plane1 node
- Domain API8 nodes
- AI-pool2 nodes
- storagepool2 nodes
- Data5 nodes
- Platform6 nodes
De vijf lagen van de README (de banden) en de fysieke groepen (de tint van de kop van elke node) groeperen dezelfde 24 nodes verschillend. State KV deelt de Streams-node en wordt niet apart geteld; Route 53, de ALB en diensten buiten het cluster zijn geen nodes. Een pool is een schedulingbereik, geen bewering dat elke pod op beide nodes draait.
24nodes
24 = 1 control plane + 8 API + 4 worker + 5 data + 6 platform
1Control plane
role: control-planekube-apiserver · scheduler · controller-manager · etcd, plus de platformcontrollers.
- k8s-master
8Domain API
domain: <dienst>Eén node per domein. Interne aanroepen gebruiken 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
Twee schedulingpools van elk twee nodes. KEDA wijzigt het aantal pods; het aantal nodes blijft gelijk.
storagepool
domain: worker-storage- k8s-worker-storage
- k8s-worker-storage-2
AI-pool
domain: worker-ai- k8s-worker-ai
- k8s-worker-ai-2
5Data
Redis is per doel opgesplitst over vier nodes. De opslag van PostgreSQL is EBS CSI · gp3.
- k8s-postgresql
- k8s-redis-auth
- k8s-redis-streams
- k8s-redis-cache
- k8s-redis-pubsub
6Platform
Messaging, observeerbaarheid, ingress en realtime levering hebben elk een eigen node.
- k8s-rabbitmq
- k8s-monitoring
- k8s-logging
- k8s-ingress-gateway
- k8s-sse-gateway
- k8s-event-router
- Elke node
- Fluent Bit · DaemonSet
- Calico
Geconfigureerde modellen · per provider
De dienst is beëindigd, dus dit zijn de modellen die in de repository zijn geconfigureerd, geen keuzes die vandaag beschikbaar zijn. Elke rol staat apart vermeld; dit is geen lijst van geverifieerde runs.
OpenAI
Standaardprovider voor Chat
Chat
openai/gpt-5.2standaard
Het standaardmodel is gpt-5.2; een model dat in het verzoek wordt genoemd, wordt in plaats daarvan gebruikt.
Scan
gpt-5.2standaardgpt-5.2-progpt-5.1gpt-5gpt-5-progpt-5-mini
Modellen buiten de toewijzing van 13 modellen worden geweigerd.
Beeldtoewijzing
gpt-image-1.5
Los van gpt-5.2, het orchestratiemodel voor Responses. Beeldgeneratie staat standaard uit.
Evaluatie
gpt-4o-ministandaard
De LLM-grader voor gespreksevaluatie, los van het Chat-model.
Google
Als Chat Google kiest
Chat
google/gemini-3-pro-previewgoogle/gemini-3-flash-preview
Met Google geselecteerd is gemini-3-flash-preview de standaard.
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
Beeldtoewijzing
gemini-3-pro-image-preview
Bronbackend main d8840c7Publieke commit September 29, 2026 · gecontroleerd October 8, 2026