
Eco²
Backend · Cloud infrastructure
Veiledning i kildesortering ut fra ett bilde og en samtale.
En alt-i-ett-AI-assistent som forstår hvordan kildesortering fungerer i Korea.
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
Hvordan de 24 nodene faktisk henger sammen, én flyt om gangen.
Selvdriftet Kubernetes bygget med kubeadm. Kartet plasserer de 24 fysiske nodene og arbeidslastene på dem innenfor README-ens fem lag og tegner de faktiske forbindelsene mellom dem. Når en flyt velges, fremheves bare den stien, med nummererte steg.
Den identifiserer avfall ut fra et bilde og forklarer hvordan det skal kastes, og i samtalen kaller den verktøy for steder, vær, gjenvinningspriser og nettsøk og genererer bilder. I dette teamprosjektet begynte jeg med grunnlaget for klynge og utrulling og utvidet ansvaret mitt til domenebackend, asynkron behandling, samtaleagenten og verifisering.
Fra utviklingen til konkurransen til styrking av backend og drift
Tjenesten er avsluttet; en innspilt demo og den tekniske rapporten viser den i bruk.
Scan-forespørsel → levering i sanntid
En forespørsel om bildeanalyse blir arbeid i kø, og framdriftshendelsene kommer tilbake til samme nettleser.
NettleserDNS-oppslag: DNS-oppslagRoute 53
Bare navnet slås opp i Route 53-poster. Forespørsler går ikke gjennom DNS.
Nettleserdataflyt: HTTPS 443AWS ALB
TLS avsluttes ved ALB-en.
AWS ALBdataflyt: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayOverleveres til Istio ingress Envoy via NodePort på EC2-instansmålet.
Istio ingress Envoy
k8s-ingress-gatewaydataflyt: VirtualServiceScan APIk8s-api-scanRutes til Scan API, som setter arbeidet i kø og straks returnerer en job_id; polling etter resultatet besvares med 202 til jobben er ferdig.
Scan API
k8s-api-scandataflyt: Celery-oppgaveRabbitMQk8s-rabbitmqScan-oppgaven legges på RabbitMQ.
RabbitMQ
k8s-rabbitmqdataflyt: consumescan-workerk8s-worker-ai · k8s-worker-ai-2scan-worker (Celery · gevent) i AI-poolen tar den og kjører Vision → Rule → Answer → Reward. De fire stadiene er kjedede Celery-tasks, ikke noder.
AI-pool
k8s-worker-ai · k8s-worker-ai-2dataflyt: HTTPSLLM APIScan- og chat-workerne kaller API-ene til OpenAI og Google.
scan-worker
k8s-worker-ai · k8s-worker-ai-2dataflyt: XADD scan:eventsStreamsk8s-redis-streamsFramdriftshendelser skrives til én av fire Streams-shards.
Streams
k8s-redis-streamsdataflyt: XREADGROUPEvent Routerk8s-event-routerEvent Router leser dem som consumer group og sender XACK etter behandlingen; pending og reclaim holder leveringen at-least-once.
Event Router
k8s-event-routerdataflyt: SETEX stateState KVk8s-redis-streamsDen skriver den siste tilstanden og en markering mot dobbeltbehandling til State KV på samme Redis-node.
Event Router
k8s-event-routerdataflyt: PUBLISHPub/Subk8s-redis-pubsubLeveres i sanntid på jobbens kanal i shard Pub/Sub.
Pub/Sub
k8s-redis-pubsubdataflyt: SUBSCRIBESSE Gatewayk8s-sse-gatewaySSE Gateway abonnerer gjennom én delt listener per prosess og fordeler til hver tilkoblede nettleser.
SSE Gateway
k8s-sse-gatewaydataflyt: SSE-strømNettleserEn tilkobling åpnet over samme ALB- og ingress-sti. Leveringen er at-least-once; duplikater håndteres idempotent.
State KV
k8s-redis-streamsdataflyt: Gjenoppretting ved ny tilkoblingSSE Gatewayk8s-sse-gatewayVed ny tilkobling med Last-Event-ID fyller State KV og de bevarte Streams inn hendelser som ble gått glipp av.
Chat · tokens og lagring
Chat-tokens følger samme hendelsessti som Scan; checkpoints og meldinger lagres av to ulike arbeidslaster.
Nettleserdataflyt: HTTPS 443AWS ALB
TLS avsluttes ved ALB-en.
AWS ALBdataflyt: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayOverleveres til Istio ingress Envoy via NodePort på EC2-instansmålet.
Istio ingress Envoy
k8s-ingress-gatewaydataflyt: VirtualServiceChat APIk8s-api-chatRutes til Chat API.
Chat API
k8s-api-chatdataflyt: Taskiq-oppgaveRabbitMQk8s-rabbitmqChat-oppgaven legges på RabbitMQ.
RabbitMQ
k8s-rabbitmqdataflyt: consumechat-workerk8s-worker-ai · k8s-worker-ai-2chat-worker (Taskiq · asyncio) klassifiserer hensikten med LangGraph, kjører deretter vision ved behov, de valgte verktøyene, aggregatoren og et sammendrag ved behov, og svarer. Hver forespørsel kjører bare grenene den trenger.
AI-pool
k8s-worker-ai · k8s-worker-ai-2dataflyt: HTTPSLLM APIScan- og chat-workerne kaller API-ene til OpenAI og Google.
chat-worker
k8s-worker-ai · k8s-worker-ai-2dataflyt: XADD chat:eventsStreamsk8s-redis-streamsTokens og stage-hendelser skrives til fire Streams-shards; derfra er leveringsstien den samme som for Scan.
Streams
k8s-redis-streamsdataflyt: XREADGROUPEvent Routerk8s-event-routerEvent Router leser dem som consumer group og sender XACK etter behandlingen; pending og reclaim holder leveringen at-least-once.
Event Router
k8s-event-routerdataflyt: PUBLISHPub/Subk8s-redis-pubsubLeveres i sanntid på jobbens kanal i shard Pub/Sub.
Pub/Sub
k8s-redis-pubsubdataflyt: SUBSCRIBESSE Gatewayk8s-sse-gatewaySSE Gateway abonnerer gjennom én delt listener per prosess og fordeler til hver tilkoblede nettleser.
SSE Gateway
k8s-sse-gatewaydataflyt: SSE-strømNettleserEn tilkobling åpnet over samme ALB- og ingress-sti. Leveringen er at-least-once; duplikater håndteres idempotent.
chat-worker
k8s-worker-ai · k8s-worker-ai-2dataflyt: checkpointCachek8s-redis-cacheLangGraph-checkpointet ligger i Redis Cache.
Cache
k8s-redis-cachedataflyt: les checkpointcheckpoint-syncerk8s-worker-ai · k8s-worker-ai-2checkpoint-syncer leser checkpointet fra Redis.
checkpoint-syncer
k8s-worker-ai · k8s-worker-ai-2dataflyt: synkroniser til PostgreSQLPostgreSQLk8s-postgresqlAsyncPostgresSaver lagrer det asynkront i PostgreSQL.
Streams
k8s-redis-streamsdataflyt: chat-persistence grouppersistence consumerk8s-api-chatpersistence consumer på Chat-noden leser done-hendelser som consumer group.
persistence consumer
k8s-api-chatdataflyt: lagre meldingerPostgreSQLk8s-postgresqlChatmeldinger lagres i PostgreSQL. Dette er en annen arbeidslast enn checkpoint-syncer.
Inngang · autentisering
Den synkrone veien fra klyngens inngang til et domene-API. Bare policybeskyttede stier sjekker autentisering først; pod-trafikk mellom noder går over Calico VXLAN.
NettleserDNS-oppslag: DNS-oppslagRoute 53
Bare navnet slås opp i Route 53-poster. Forespørsler går ikke gjennom DNS.
Nettleserdataflyt: HTTPS 443AWS ALB
TLS avsluttes ved ALB-en.
AWS ALBdataflyt: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayOverleveres til Istio ingress Envoy via NodePort på EC2-instansmålet.
Istio ingress Envoy
k8s-ingress-gatewaydataflyt: ext-authz · gRPC 50051ext-authzk8s-api-authBare stier under en CUSTOM-policy spør først Go ext-authz (tidsavbrudd 2 s, failOpen false). Stier som login, health og docs er unntatt.
ext-authz
k8s-api-authdataflyt: blacklist-oppslagblacklistk8s-redis-authTokenet kontrolleres mot Redis-blacklisten.
Istio ingress Envoy
k8s-ingress-gatewaydataflyt: VirtualServiceChat APIk8s-api-chatRutes til Chat API.
Chat API
k8s-api-chatdataflyt: gRPCimages APIk8s-api-imageDet synkrone kallet chat → images som README nevner.
auth API
k8s-api-authdataflyt: gRPCusers APIk8s-api-usersDet synkrone kallet auth → users som README nevner.
Storage-pool · asynkrone skrivinger
Blacklisten for autentisering og eierskap til figurer lagres av workers i storage-poolen, som henter arbeidet sitt fra RabbitMQ.
blacklist
k8s-redis-authdataflyt: outbox:blacklistauth-relayk8s-worker-storage · k8s-worker-storage-2auth-relay (auth-Bus i README) leser Redis-outboxen.
auth-relay
k8s-worker-storage · k8s-worker-storage-2dataflyt: blacklist.eventsRabbitMQk8s-rabbitmqDen publiserer på nytt til RabbitMQ, med nye forsøk og en DLQ.
RabbitMQ
k8s-rabbitmqdataflyt: blacklist.eventsauth-workerk8s-worker-storage · k8s-worker-storage-2auth-worker mottar blacklist-hendelsene.
auth-worker
k8s-worker-storage · k8s-worker-storage-2dataflyt: lagre blacklistblacklistk8s-redis-authDe lagres i Redis-blacklisten.
RabbitMQ
k8s-rabbitmqdataflyt: Celery batchusers-workerk8s-worker-storage · k8s-worker-storage-2users-worker mottar arbeid om eierskap til figurer i batcher.
users-worker
k8s-worker-storage · k8s-worker-storage-2dataflyt: UPSERTPostgreSQLk8s-postgresqlDet skrives til PostgreSQL.
Konfigurere · skalere · observere
Platform Layer er ikke et steg forespørsler går gjennom; det ruller ut, konfigurerer, skalerer og observerer de andre lagene. Nodene er EC2-instanser laget med Terraform, med kubeadm og Calico installert av Ansible; CI validerer bare Terraform og kjører aldri apply automatisk.
GitHub Actions · Docker Hubkonfigurasjon · skalering: image · manifest-revisjonArgo CD image updater
k8s-masterArgo CD bringer klyngens konfigurasjon i samsvar via App-of-Apps og Sync Waves. Bare image updaterens plassering på control plane ble bekreftet.
ALB Controller · ExternalDNS
k8s-masterkonfigurasjon · skalering: Ingress → ALB · DNS-posterAWS-administrertALB Controller og ExternalDNS konfigurerer ressurser på AWS-siden. Dette er ikke en sti forespørsler tar.
Istiod
k8s-masterkonfigurasjon · skalering: xDS-konfigurasjonIstio ingress Envoyk8s-ingress-gatewayIstiod sender Gateway-, VirtualService- og EnvoyFilter-konfigurasjonen via xDS til ingress Envoy og til Envoy-sidecaren for hvert API.
KEDA
k8s-monitoringkonfigurasjon · skalering: antall podsAI-poolk8s-worker-ai · k8s-worker-ai-2KEDA justerer antallet worker-pods. Antallet noder endres ikke.
KEDA
k8s-monitoringkonfigurasjon · skalering: antall podsstorage-poolk8s-worker-storage · k8s-worker-storage-2Worker-pods i storage-poolen skaleres på samme måte.
Fluent Bitobserverbarhet: loggerElasticsearch
k8s-loggingFluent Bit er et DaemonSet på alle noder og sender logger til Elasticsearch.
AI-pool
k8s-worker-ai · k8s-worker-ai-2observerbarhet: sporing av LLM-kjøringerLangSmithTraces av LLM-kall sendes til LangSmith, en ekstern SaaS.
Alle forbindelser med samme tykkelse. Velg en flyt for å fremheve bare dens vei, med nummererte steg.
- Heltrukket · retningen forespørsler, arbeid, hendelser og skrivinger flyter i
- Prikket · DNS-oppslag; forespørsler går ikke gjennom det
- Stiplet · konfigurasjon eller skalering; ikke en datavei
- Lang strek-prikk · logger og sporing av kjøringer
- Kraftig svart linje · den valgte flyten; tallene angir rekkefølgen
- Boks · en fysisk node, vertsnavn i overskriften
- Indre chip · en arbeidslast som kjører på noden
- Stiplet ramme · en planleggingspool med to noder
- Stiplet boks · utenfor klyngen, telles ikke som node
- Oransje kontur · der en modell tar beslutninger
- Control plane1 node
- Domain API8 noder
- AI-pool2 noder
- storage-pool2 noder
- Data5 noder
- Platform6 noder
README-ens fem lag (båndene) og de fysiske gruppene (fargen i hver nodes overskrift) grupperer de samme 24 nodene ulikt. State KV deler Streams-noden og telles ikke separat; Route 53, ALB-en og tjenester utenfor klyngen er ikke noder. En pool er et planleggingsområde, ikke en påstand om at hver pod kjører på begge nodene.
24noder
24 = 1 control plane + 8 API + 4 worker + 5 data + 6 platform
1Control plane
role: control-planekube-apiserver · scheduler · controller-manager · etcd samt plattformens controllere.
- k8s-master
8Domain API
domain: <tjeneste>Én node per domene. Interne kall bruker 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
To planleggingspooler med to noder hver. KEDA endrer antallet pods; antallet noder forblir det samme.
storage-pool
domain: worker-storage- k8s-worker-storage
- k8s-worker-storage-2
AI-pool
domain: worker-ai- k8s-worker-ai
- k8s-worker-ai-2
5Data
Redis er fordelt på fire noder etter formål. PostgreSQL-lagringen er EBS CSI · gp3.
- k8s-postgresql
- k8s-redis-auth
- k8s-redis-streams
- k8s-redis-cache
- k8s-redis-pubsub
6Platform
Meldinger, observerbarhet, ingress og levering i sanntid har hver sin node.
- k8s-rabbitmq
- k8s-monitoring
- k8s-logging
- k8s-ingress-gateway
- k8s-sse-gateway
- k8s-event-router
- Alle noder
- Fluent Bit · DaemonSet
- Calico
Konfigurerte modeller · per leverandør
Tjenesten er lagt ned, så dette er modellene som er konfigurert i repositoryet, ikke valg som finnes i dag. Hver rolle står for seg; dette er ikke en liste over verifiserte kjøringer.
OpenAI
Standardleverandør for Chat
Chat
openai/gpt-5.2standard
Standardmodellen er gpt-5.2; en modell som oppgis i forespørselen, brukes i stedet.
Scan
gpt-5.2standardgpt-5.2-progpt-5.1gpt-5gpt-5-progpt-5-mini
Modeller utenfor tilordningen med 13 modeller avvises.
Bildetilordning
gpt-image-1.5
Atskilt fra gpt-5.2, som er orkestreringsmodellen for Responses. Bildegenerering er slått av som standard.
Evaluering
gpt-4o-ministandard
LLM-graderen for evaluering av samtaler, atskilt fra Chat-modellen.
Google
Når Chat velger Google
Chat
google/gemini-3-pro-previewgoogle/gemini-3-flash-preview
Når Google er valgt, er gemini-3-flash-preview standard.
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
Bildetilordning
gemini-3-pro-image-preview
Kildebackend main d8840c7Offentlig commit 29. september 2026 · kontrollert 8. oktober 2026