
Eco²
Backend · Cloud infrastructure
Vejledning i affaldssortering ud fra ét foto og en samtale.
En samlet AI-assistent, der forstår, hvordan affaldssortering 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 noder faktisk forbindes, ét flow ad gangen.
Selvadministreret Kubernetes bygget med kubeadm. Kortet placerer de 24 fysiske noder og deres workloads inden for README's fem lag og tegner de faktiske forbindelser mellem dem. Når et flow vælges, fremhæves kun den sti, med nummererede trin.
Den identificerer affald ud fra et foto og forklarer, hvordan det skal bortskaffes, og i samtalen kalder den værktøjer til steder, vejr, genbrugspriser og websøgning og genererer billeder. I dette teamprojekt begyndte jeg med fundamentet for klynge og udrulning og udvidede mit ansvar til domænebackend, asynkron behandling, samtaleagenten og verifikation.
Fra udviklingen til konkurrencen til styrkelse af backend og drift
Tjenesten er afsluttet; en optaget demo og den tekniske rapport viser den i funktion.
Scan-forespørgsel → levering i realtid
En forespørgsel om fotoanalyse bliver til arbejde i kø, og dens fremdriftshændelser kommer tilbage til samme browser.
BrowserDNS-opslag: DNS-opslagRoute 53
Kun navnet slås op i Route 53-poster. Forespørgsler passerer ikke gennem DNS.
Browserdataflow: HTTPS 443AWS ALB
TLS afsluttes ved ALB'en.
AWS ALBdataflow: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayOverdrages til Istio ingress Envoy via EC2-instansmålets NodePort.
Istio ingress Envoy
k8s-ingress-gatewaydataflow: VirtualServiceScan APIk8s-api-scanRoutes til Scan API'et, der sætter arbejdet i kø og straks returnerer et job_id; polling efter resultatet besvares med 202, indtil jobbet er færdigt.
Scan API
k8s-api-scandataflow: Celery-opgaveRabbitMQk8s-rabbitmqScan-opgaven lægges på RabbitMQ.
RabbitMQ
k8s-rabbitmqdataflow: consumescan-workerk8s-worker-ai · k8s-worker-ai-2scan-worker (Celery · gevent) i AI-puljen tager den og kører Vision → Rule → Answer → Reward. De fire stadier er kædede Celery-tasks, ikke noder.
AI-pulje
k8s-worker-ai · k8s-worker-ai-2dataflow: HTTPSLLM APIScan- og chat-workerne kalder OpenAI- og Google-API'erne.
scan-worker
k8s-worker-ai · k8s-worker-ai-2dataflow: XADD scan:eventsStreamsk8s-redis-streamsFremdriftshændelser skrives til én af fire Streams-shards.
Streams
k8s-redis-streamsdataflow: XREADGROUPEvent Routerk8s-event-routerEvent Router læser dem som consumer group og sender XACK efter behandlingen; pending og reclaim holder leveringen at-least-once.
Event Router
k8s-event-routerdataflow: SETEX stateState KVk8s-redis-streamsDen skriver den seneste tilstand og en markering mod dobbeltbehandling til State KV på samme Redis-node.
Event Router
k8s-event-routerdataflow: PUBLISHPub/Subk8s-redis-pubsubLeveres i realtid på jobbets kanal i shard Pub/Sub.
Pub/Sub
k8s-redis-pubsubdataflow: SUBSCRIBESSE Gatewayk8s-sse-gatewaySSE Gateway abonnerer gennem én delt listener pr. proces og fordeler til hver tilsluttet browser.
SSE Gateway
k8s-sse-gatewaydataflow: SSE-streamBrowserEn forbindelse åbnet over samme ALB- og ingress-sti. Leveringen er at-least-once; dubletter håndteres idempotent.
State KV
k8s-redis-streamsdataflow: Gendannelse ved genforbindelseSSE Gatewayk8s-sse-gatewayVed genforbindelse med Last-Event-ID udfylder State KV og de bevarede Streams de manglende hændelser.
Chat · tokens og lagring
Chat-tokens følger samme hændelsessti som Scan; checkpoints og beskeder gemmes af to forskellige workloads.
Browserdataflow: HTTPS 443AWS ALB
TLS afsluttes ved ALB'en.
AWS ALBdataflow: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayOverdrages til Istio ingress Envoy via EC2-instansmålets NodePort.
Istio ingress Envoy
k8s-ingress-gatewaydataflow: VirtualServiceChat APIk8s-api-chatRoutes til Chat API'et.
Chat API
k8s-api-chatdataflow: Taskiq-opgaveRabbitMQk8s-rabbitmqChat-opgaven lægges på RabbitMQ.
RabbitMQ
k8s-rabbitmqdataflow: consumechat-workerk8s-worker-ai · k8s-worker-ai-2chat-worker (Taskiq · asyncio) klassificerer hensigten med LangGraph, kører derefter vision om nødvendigt, de valgte værktøjer, aggregatoren og et resumé om nødvendigt og svarer. Hver forespørgsel kører kun de grene, den har brug for.
AI-pulje
k8s-worker-ai · k8s-worker-ai-2dataflow: HTTPSLLM APIScan- og chat-workerne kalder OpenAI- og Google-API'erne.
chat-worker
k8s-worker-ai · k8s-worker-ai-2dataflow: XADD chat:eventsStreamsk8s-redis-streamsTokens og stage-hændelser skrives til fire Streams-shards; derfra er leveringsstien den samme som for Scan.
Streams
k8s-redis-streamsdataflow: XREADGROUPEvent Routerk8s-event-routerEvent Router læser dem som consumer group og sender XACK efter behandlingen; pending og reclaim holder leveringen at-least-once.
Event Router
k8s-event-routerdataflow: PUBLISHPub/Subk8s-redis-pubsubLeveres i realtid på jobbets kanal i shard Pub/Sub.
Pub/Sub
k8s-redis-pubsubdataflow: SUBSCRIBESSE Gatewayk8s-sse-gatewaySSE Gateway abonnerer gennem én delt listener pr. proces og fordeler til hver tilsluttet browser.
SSE Gateway
k8s-sse-gatewaydataflow: SSE-streamBrowserEn forbindelse åbnet over samme ALB- og ingress-sti. Leveringen er at-least-once; dubletter håndteres idempotent.
chat-worker
k8s-worker-ai · k8s-worker-ai-2dataflow: checkpointCachek8s-redis-cacheLangGraph-checkpointet ligger i Redis Cache.
Cache
k8s-redis-cachedataflow: læs checkpointcheckpoint-syncerk8s-worker-ai · k8s-worker-ai-2checkpoint-syncer læser checkpointet fra Redis.
checkpoint-syncer
k8s-worker-ai · k8s-worker-ai-2dataflow: synkronisér til PostgreSQLPostgreSQLk8s-postgresqlAsyncPostgresSaver gemmer det asynkront i PostgreSQL.
Streams
k8s-redis-streamsdataflow: chat-persistence grouppersistence consumerk8s-api-chatpersistence consumer på Chat-noden læser done-hændelser som consumer group.
persistence consumer
k8s-api-chatdataflow: gem beskederPostgreSQLk8s-postgresqlChatbeskeder gemmes i PostgreSQL. Det er en anden workload end checkpoint-syncer.
Indgang · autentificering
Den synkrone vej fra klyngens indgang til et domæne-API. Kun policybeskyttede stier kontrollerer autentificering først; pod-trafik mellem noder kører på Calico VXLAN.
BrowserDNS-opslag: DNS-opslagRoute 53
Kun navnet slås op i Route 53-poster. Forespørgsler passerer ikke gennem DNS.
Browserdataflow: HTTPS 443AWS ALB
TLS afsluttes ved ALB'en.
AWS ALBdataflow: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayOverdrages til Istio ingress Envoy via EC2-instansmålets NodePort.
Istio ingress Envoy
k8s-ingress-gatewaydataflow: ext-authz · gRPC 50051ext-authzk8s-api-authKun stier under en CUSTOM-policy spørger først Go ext-authz (timeout 2 s, failOpen false). Stier som login, health og docs er undtaget.
ext-authz
k8s-api-authdataflow: blacklist-opslagblacklistk8s-redis-authTokenet kontrolleres mod Redis-blacklisten.
Istio ingress Envoy
k8s-ingress-gatewaydataflow: VirtualServiceChat APIk8s-api-chatRoutes til Chat API'et.
Chat API
k8s-api-chatdataflow: gRPCimages APIk8s-api-imageDet synkrone kald chat → images, som README nævner.
auth API
k8s-api-authdataflow: gRPCusers APIk8s-api-usersDet synkrone kald auth → users, som README nævner.
Storage-pulje · asynkrone skrivninger
Blacklisten for autentificering og ejerskab af figurer gemmes af workers i storage-puljen, som henter deres arbejde fra RabbitMQ.
blacklist
k8s-redis-authdataflow: outbox:blacklistauth-relayk8s-worker-storage · k8s-worker-storage-2auth-relay (README's auth-Bus) læser Redis-outboxen.
auth-relay
k8s-worker-storage · k8s-worker-storage-2dataflow: blacklist.eventsRabbitMQk8s-rabbitmqDen genpublicerer til RabbitMQ med nye forsøg og en DLQ.
RabbitMQ
k8s-rabbitmqdataflow: blacklist.eventsauth-workerk8s-worker-storage · k8s-worker-storage-2auth-worker modtager blacklist-hændelserne.
auth-worker
k8s-worker-storage · k8s-worker-storage-2dataflow: gem blacklistblacklistk8s-redis-authDe gemmes i Redis-blacklisten.
RabbitMQ
k8s-rabbitmqdataflow: Celery batchusers-workerk8s-worker-storage · k8s-worker-storage-2users-worker modtager arbejde om ejerskab af figurer i batches.
users-worker
k8s-worker-storage · k8s-worker-storage-2dataflow: UPSERTPostgreSQLk8s-postgresqlDet skrives til PostgreSQL.
Konfigurere · skalere · observere
Platform Layer er ikke et trin, forespørgsler passerer; det udruller, konfigurerer, skalerer og observerer de andre lag. Noderne er EC2-instanser oprettet med Terraform, med kubeadm og Calico installeret af Ansible; CI validerer kun Terraform og kører aldrig apply automatisk.
GitHub Actions · Docker Hubkonfiguration · skalering: image · manifest-revisionArgo CD image updater
k8s-masterArgo CD bringer klyngens konfiguration i overensstemmelse via App-of-Apps og Sync Waves. Kun image updaterens placering på control plane blev bekræftet.
ALB Controller · ExternalDNS
k8s-masterkonfiguration · skalering: Ingress → ALB · DNS-posterAWS-administreretALB Controller og ExternalDNS konfigurerer ressourcer på AWS-siden. Det er ikke en sti, forespørgsler tager.
Istiod
k8s-masterkonfiguration · skalering: xDS-konfigurationIstio ingress Envoyk8s-ingress-gatewayIstiod sender Gateway-, VirtualService- og EnvoyFilter-konfigurationen via xDS til ingress Envoy og til hvert API's Envoy-sidecar.
KEDA
k8s-monitoringkonfiguration · skalering: antal podsAI-puljek8s-worker-ai · k8s-worker-ai-2KEDA justerer antallet af worker-pods. Antallet af noder ændres ikke.
KEDA
k8s-monitoringkonfiguration · skalering: antal podsstorage-puljek8s-worker-storage · k8s-worker-storage-2Worker-pods i storage-puljen skaleres på samme måde.
Fluent Bitobserverbarhed: logsElasticsearch
k8s-loggingFluent Bit er et DaemonSet på alle noder og sender logs til Elasticsearch.
AI-pulje
k8s-worker-ai · k8s-worker-ai-2observerbarhed: sporing af LLM-kørslerLangSmithTraces af LLM-kald sendes til LangSmith, en ekstern SaaS.
Alle forbindelser med samme tykkelse. Vælg et flow for kun at fremhæve dets vej med nummererede trin.
- Fuldt optrukket · den retning, som forespørgsler, arbejde, hændelser og skrivninger flyder i
- Prikket · DNS-opslag; forespørgsler passerer ikke igennem det
- Stiplet · konfiguration eller skalering; ikke en datavej
- Lang streg-prik · logs og sporing af kørsler
- Kraftig sort linje · det valgte flow; tal angiver rækkefølgen
- Boks · en fysisk node, værtsnavn i overskriften
- Indre chip · en workload, der kører på noden
- Stiplet ramme · en planlægningspulje med to noder
- Stiplet boks · uden for klyngen, tælles ikke som node
- Orange kontur · hvor en model træffer beslutninger
- Control plane1 node
- Domain API8 noder
- AI-pulje2 noder
- storage-pulje2 noder
- Data5 noder
- Platform6 noder
README's fem lag (båndene) og de fysiske grupper (farven i hver nodes overskrift) grupperer de samme 24 noder forskelligt. State KV deler Streams-noden og tælles ikke separat; Route 53, ALB'en og tjenester uden for klyngen er ikke noder. En pulje er et planlægningsområde, ikke en påstand om, at hver pod kører på begge noder.
24noder
24 = 1 control plane + 8 API + 4 worker + 5 data + 6 platform
1Control plane
role: control-planekube-apiserver · scheduler · controller-manager · etcd samt platformens controllere.
- k8s-master
8Domain API
domain: <tjeneste>Én node pr. domæne. Interne kald bruger 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 planlægningspuljer med to noder hver. KEDA ændrer antallet af pods; antallet af noder forbliver det samme.
storage-pulje
domain: worker-storage- k8s-worker-storage
- k8s-worker-storage-2
AI-pulje
domain: worker-ai- k8s-worker-ai
- k8s-worker-ai-2
5Data
Redis er fordelt på fire noder efter formål. PostgreSQL-lageret er EBS CSI · gp3.
- k8s-postgresql
- k8s-redis-auth
- k8s-redis-streams
- k8s-redis-cache
- k8s-redis-pubsub
6Platform
Beskeder, observerbarhed, ingress og levering i realtid har hver deres node.
- k8s-rabbitmq
- k8s-monitoring
- k8s-logging
- k8s-ingress-gateway
- k8s-sse-gateway
- k8s-event-router
- Alle noder
- Fluent Bit · DaemonSet
- Calico
Konfigurerede modeller · efter udbyder
Tjenesten er lukket, så det er de modeller, der er konfigureret i repositoryet, ikke valg, der findes i dag. Hver rolle står for sig; det er ikke en liste over verificerede kørsler.
OpenAI
Standardudbyder for Chat
Chat
openai/gpt-5.2standard
Standardmodellen er gpt-5.2; en model angivet i forespørgslen bruges i stedet.
Scan
gpt-5.2standardgpt-5.2-progpt-5.1gpt-5gpt-5-progpt-5-mini
Modeller uden for mappingen med 13 modeller afvises.
Billedmapping
gpt-image-1.5
Adskilt fra gpt-5.2, som er orkestreringsmodellen for Responses. Billedgenerering er som standard slået fra.
Evaluering
gpt-4o-ministandard
LLM-graderen til evaluering af samtaler, adskilt fra Chat-modellen.
Google
Når Chat vælger 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
Billedmapping
gemini-3-pro-image-preview
Kildebackend main d8840c7Offentlig commit 29. september 2026 · kontrolleret 8. oktober 2026