
Eco²
Backend · Cloud infrastructure
Hinweise zur Mülltrennung aus einem Foto und einem Gespräch.
Ein All-in-one-KI-Assistent, der versteht, wie Mülltrennung in Korea funktioniert.
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
Wie die 24 Knoten tatsächlich verbunden sind, ein Ablauf nach dem anderen.
Selbst verwaltetes Kubernetes, aufgebaut mit kubeadm. Die Karte setzt die 24 physischen Knoten und die Workloads darauf in die fünf Schichten des README und verbindet sie mit ihren tatsächlichen Verbindungen. Wird ein Ablauf gewählt, ist nur dieser Pfad hervorgehoben, mit nummerierten Schritten.
Er erkennt Abfall auf einem Foto und erklärt, wie er zu entsorgen ist, und im Gespräch ruft er Tools für Orte, Wetter, Recyclingpreise und Websuche auf und erzeugt Bilder. In diesem Teamprojekt begann ich mit der Cluster- und Deployment-Basis und weitete meinen Bereich auf das Domain-Backend, die asynchrone Verarbeitung, den Konversationsagenten und die Verifikation aus.
Von der Entwicklung für den Wettbewerb bis zur Härtung von Backend und Betrieb
Der Dienst hat seinen Betrieb beendet; eine aufgezeichnete Demo und der technische Bericht zeigen ihn in Aktion.
Scan-Anfrage → Live-Zustellung
Eine Fotoanalyse-Anfrage wird zu eingereihter Arbeit, und ihre Fortschrittsereignisse kommen zum selben Browser zurück.
BrowserDNS-Abfrage: DNS-AbfrageRoute 53
Nur der Name wird aus den Route-53-Einträgen aufgelöst. Anfragen laufen nicht durch DNS.
BrowserDatenfluss: HTTPS 443AWS ALB
TLS endet am ALB.
AWS ALBDatenfluss: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayÜber den NodePort des EC2-Instanzziels an den Istio-Ingress-Envoy übergeben.
Istio ingress Envoy
k8s-ingress-gatewayDatenfluss: VirtualServiceScan APIk8s-api-scanAn die Scan-API geroutet, die die Arbeit einreiht und sofort eine job_id zurückgibt; eine Ergebnisabfrage antwortet mit 202, bis der Job fertig ist.
Scan API
k8s-api-scanDatenfluss: Celery-TaskRabbitMQk8s-rabbitmqDer Scan-Task kommt in RabbitMQ.
RabbitMQ
k8s-rabbitmqDatenfluss: consumescan-workerk8s-worker-ai · k8s-worker-ai-2scan-worker (Celery · gevent) im AI-Pool übernimmt ihn und führt Vision → Rule → Answer → Reward aus. Die vier Stufen sind verkettete Celery-Tasks, keine Knoten.
AI-Pool
k8s-worker-ai · k8s-worker-ai-2Datenfluss: HTTPSLLM APIDie Scan- und Chat-Worker rufen die APIs von OpenAI und Google auf.
scan-worker
k8s-worker-ai · k8s-worker-ai-2Datenfluss: XADD scan:eventsStreamsk8s-redis-streamsFortschrittsereignisse werden in einen von vier Streams-Shards geschrieben.
Streams
k8s-redis-streamsDatenfluss: XREADGROUPEvent Routerk8s-event-routerDer Event Router liest sie als Consumer Group und bestätigt sie nach der Verarbeitung per XACK; pending und reclaim halten die Zustellung at-least-once.
Event Router
k8s-event-routerDatenfluss: SETEX stateState KVk8s-redis-streamsEr schreibt den neuesten Zustand und eine Markierung gegen doppelte Verarbeitung in State KV auf demselben Redis-Knoten.
Event Router
k8s-event-routerDatenfluss: PUBLISHPub/Subk8s-redis-pubsubIn Echtzeit auf dem Kanal des Jobs im Shard-Pub/Sub zugestellt.
Pub/Sub
k8s-redis-pubsubDatenfluss: SUBSCRIBESSE Gatewayk8s-sse-gatewayDas SSE Gateway abonniert über einen gemeinsamen Listener pro Prozess und verteilt an jeden verbundenen Browser.
SSE Gateway
k8s-sse-gatewayDatenfluss: SSE-StreamBrowserEine Verbindung, die über denselben ALB- und Ingress-Pfad geöffnet wird. Die Zustellung ist at-least-once; Duplikate werden idempotent behandelt.
State KV
k8s-redis-streamsDatenfluss: Wiederherstellung bei WiederverbindungSSE Gatewayk8s-sse-gatewayBei einer Wiederverbindung mit Last-Event-ID füllen State KV und die aufbewahrten Streams verpasste Ereignisse auf.
Chat · Tokens und Speicherung
Chat-Tokens nehmen denselben Ereignispfad wie Scan; Checkpoints und Nachrichten werden von zwei verschiedenen Workloads gespeichert.
BrowserDatenfluss: HTTPS 443AWS ALB
TLS endet am ALB.
AWS ALBDatenfluss: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayÜber den NodePort des EC2-Instanzziels an den Istio-Ingress-Envoy übergeben.
Istio ingress Envoy
k8s-ingress-gatewayDatenfluss: VirtualServiceChat APIk8s-api-chatAn die Chat-API geroutet.
Chat API
k8s-api-chatDatenfluss: Taskiq-TaskRabbitMQk8s-rabbitmqDer Chat-Task kommt in RabbitMQ.
RabbitMQ
k8s-rabbitmqDatenfluss: consumechat-workerk8s-worker-ai · k8s-worker-ai-2chat-worker (Taskiq · asyncio) klassifiziert die Absicht mit LangGraph, führt dann bei Bedarf vision, die gewählten Tools, aggregator und bei Bedarf eine Zusammenfassung aus und antwortet. Jede Anfrage führt nur die Zweige aus, die sie braucht.
AI-Pool
k8s-worker-ai · k8s-worker-ai-2Datenfluss: HTTPSLLM APIDie Scan- und Chat-Worker rufen die APIs von OpenAI und Google auf.
chat-worker
k8s-worker-ai · k8s-worker-ai-2Datenfluss: XADD chat:eventsStreamsk8s-redis-streamsTokens und Stufenereignisse werden in vier Streams-Shards geschrieben; ab dort ist der Zustellpfad derselbe wie bei Scan.
Streams
k8s-redis-streamsDatenfluss: XREADGROUPEvent Routerk8s-event-routerDer Event Router liest sie als Consumer Group und bestätigt sie nach der Verarbeitung per XACK; pending und reclaim halten die Zustellung at-least-once.
Event Router
k8s-event-routerDatenfluss: PUBLISHPub/Subk8s-redis-pubsubIn Echtzeit auf dem Kanal des Jobs im Shard-Pub/Sub zugestellt.
Pub/Sub
k8s-redis-pubsubDatenfluss: SUBSCRIBESSE Gatewayk8s-sse-gatewayDas SSE Gateway abonniert über einen gemeinsamen Listener pro Prozess und verteilt an jeden verbundenen Browser.
SSE Gateway
k8s-sse-gatewayDatenfluss: SSE-StreamBrowserEine Verbindung, die über denselben ALB- und Ingress-Pfad geöffnet wird. Die Zustellung ist at-least-once; Duplikate werden idempotent behandelt.
chat-worker
k8s-worker-ai · k8s-worker-ai-2Datenfluss: checkpointCachek8s-redis-cacheDer LangGraph-Checkpoint liegt in Redis Cache.
Cache
k8s-redis-cacheDatenfluss: Checkpoint lesencheckpoint-syncerk8s-worker-ai · k8s-worker-ai-2checkpoint-syncer liest den Checkpoint aus Redis.
checkpoint-syncer
k8s-worker-ai · k8s-worker-ai-2Datenfluss: mit PostgreSQL synchronisierenPostgreSQLk8s-postgresqlAsyncPostgresSaver speichert ihn asynchron in PostgreSQL.
Streams
k8s-redis-streamsDatenfluss: chat-persistence grouppersistence consumerk8s-api-chatDer Persistence-Consumer auf dem Chat-Knoten liest done-Ereignisse als Consumer Group.
persistence consumer
k8s-api-chatDatenfluss: Nachrichten speichernPostgreSQLk8s-postgresqlChat-Nachrichten werden in PostgreSQL gespeichert. Das ist ein anderer Workload als checkpoint-syncer.
Eingang · Auth
Der synchrone Pfad vom Eingang des Clusters bis zu einer Domain-API. Nur Policy-geschützte Pfade durchlaufen zuerst die Auth-Prüfung; Pod-Verkehr zwischen Knoten läuft über Calico VXLAN.
BrowserDNS-Abfrage: DNS-AbfrageRoute 53
Nur der Name wird aus den Route-53-Einträgen aufgelöst. Anfragen laufen nicht durch DNS.
BrowserDatenfluss: HTTPS 443AWS ALB
TLS endet am ALB.
AWS ALBDatenfluss: HTTP · NodePortIstio ingress Envoy
k8s-ingress-gatewayÜber den NodePort des EC2-Instanzziels an den Istio-Ingress-Envoy übergeben.
Istio ingress Envoy
k8s-ingress-gatewayDatenfluss: ext-authz · gRPC 50051ext-authzk8s-api-authNur Pfade unter einer CUSTOM-Policy fragen zuerst den Go-ext-authz (Timeout 2 s, failOpen false). Pfade wie Login, Health und Docs sind ausgenommen.
ext-authz
k8s-api-authDatenfluss: Blacklist-Abfrageblacklistk8s-redis-authDas Token wird gegen die Redis-Blacklist geprüft.
Istio ingress Envoy
k8s-ingress-gatewayDatenfluss: VirtualServiceChat APIk8s-api-chatAn die Chat-API geroutet.
Chat API
k8s-api-chatDatenfluss: gRPCimages APIk8s-api-imageDer synchrone Aufruf chat → images, der im README genannt ist.
auth API
k8s-api-authDatenfluss: gRPCusers APIk8s-api-usersDer synchrone Aufruf auth → users, der im README genannt ist.
Storage-Pool · asynchrones Speichern
Die Auth-Blacklist und der Charakterbesitz werden von Workern im Storage-Pool gespeichert, die ihre Arbeit aus RabbitMQ beziehen.
blacklist
k8s-redis-authDatenfluss: outbox:blacklistauth-relayk8s-worker-storage · k8s-worker-storage-2auth-relay (der auth-Bus des README) liest die Redis-Outbox.
auth-relay
k8s-worker-storage · k8s-worker-storage-2Datenfluss: blacklist.eventsRabbitMQk8s-rabbitmqEr veröffentlicht erneut in RabbitMQ, mit Wiederholungen und einer DLQ.
RabbitMQ
k8s-rabbitmqDatenfluss: blacklist.eventsauth-workerk8s-worker-storage · k8s-worker-storage-2auth-worker empfängt die Blacklist-Ereignisse.
auth-worker
k8s-worker-storage · k8s-worker-storage-2Datenfluss: Blacklist speichernblacklistk8s-redis-authSie werden in der Redis-Blacklist gespeichert.
RabbitMQ
k8s-rabbitmqDatenfluss: Celery batchusers-workerk8s-worker-storage · k8s-worker-storage-2users-worker empfängt Arbeit zum Charakterbesitz in Batches.
users-worker
k8s-worker-storage · k8s-worker-storage-2Datenfluss: UPSERTPostgreSQLk8s-postgresqlSie wird auf PostgreSQL angewandt.
Konfigurieren · Skalieren · Beobachten
Der Platform Layer ist kein Schritt, den Anfragen durchlaufen; er deployt, konfiguriert, skaliert und beobachtet die anderen Schichten. Die Knoten sind mit Terraform erstellte EC2-Instanzen, auf denen Ansible kubeadm und Calico installiert hat; CI validiert Terraform nur und wendet es nie automatisch an.
GitHub Actions · Docker HubKonfigurieren · Skalieren: Image · Manifest-RevisionArgo CD image updater
k8s-masterArgo CD gleicht die Cluster-Konfiguration über App-of-Apps und Sync Waves an. Bestätigt wurde nur die Control-Plane-Platzierung des Image Updaters.
ALB Controller · ExternalDNS
k8s-masterKonfigurieren · Skalieren: Ingress → ALB · DNS-EinträgeVon AWS verwaltetALB Controller und ExternalDNS konfigurieren Ressourcen auf AWS-Seite. Das ist kein Pfad, den Anfragen nehmen.
Istiod
k8s-masterKonfigurieren · Skalieren: xDS-KonfigurationIstio ingress Envoyk8s-ingress-gatewayIstiod verteilt die Konfiguration von Gateway, VirtualService und EnvoyFilter per xDS an den Ingress-Envoy und an den Envoy-Sidecar jeder API.
KEDA
k8s-monitoringKonfigurieren · Skalieren: Pod-AnzahlAI-Poolk8s-worker-ai · k8s-worker-ai-2KEDA passt die Anzahl der Worker-Pods an. Die Knotenzahl ändert sich nicht.
KEDA
k8s-monitoringKonfigurieren · Skalieren: Pod-AnzahlStorage-Poolk8s-worker-storage · k8s-worker-storage-2Worker-Pods im Storage-Pool werden auf dieselbe Weise skaliert.
Fluent BitBeobachtung: LogsElasticsearch
k8s-loggingFluent Bit ist ein DaemonSet auf jedem Knoten und sendet Logs an Elasticsearch.
AI-Pool
k8s-worker-ai · k8s-worker-ai-2Beobachtung: LLM-Lauf-TracingLangSmithLLM-Aufruf-Traces gehen an LangSmith, ein externes SaaS.
Alle Verbindungen in gleicher Stärke. Wird ein Ablauf gewählt, ist nur sein Pfad hervorgehoben, mit nummerierten Schritten.
- Durchgezogen · Richtung, in der Anfragen, Arbeit, Ereignisse und Schreibvorgänge fließen
- Gepunktet · DNS-Abfrage; Anfragen laufen nicht hindurch
- Gestrichelt · Konfigurieren oder Skalieren; kein Datenpfad
- Lang strichpunktiert · Logs und Ausführungs-Tracing
- Dicke schwarze Linie · der gewählte Ablauf; Nummern geben die Reihenfolge an
- Kasten · ein physischer Knoten, Hostname in der Kopfzeile
- Innerer Chip · ein Workload auf diesem Knoten
- Gestrichelter Rahmen · ein Scheduling-Pool aus zwei Knoten
- Gestrichelter Kasten · außerhalb des Clusters, nicht als Knoten gezählt
- Orange Umrandung · wo ein Modell entscheidet
- Control plane1 Knoten
- Domain API8 Knoten
- AI-Pool2 Knoten
- Storage-Pool2 Knoten
- Data5 Knoten
- Platform6 Knoten
Die fünf Schichten des README (die Bänder) und die physischen Gruppen (der Farbton der Kopfzeile jedes Knotens) gruppieren dieselben 24 Knoten unterschiedlich. State KV teilt sich den Streams-Knoten und wird nicht separat gezählt; Route 53, der ALB und Dienste außerhalb des Clusters sind keine Knoten. Ein Pool ist ein Scheduling-Bereich, keine Behauptung, dass jeder Pod auf beiden Knoten läuft.
24Knoten
24 = 1 control plane + 8 API + 4 worker + 5 data + 6 platform
1Control plane
role: control-planekube-apiserver · scheduler · controller-manager · etcd sowie die Plattform-Controller.
- k8s-master
8Domain API
domain: <Dienst>Ein Knoten pro Domain. Interne Aufrufe nutzen 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
Zwei Scheduling-Pools mit je zwei Knoten. KEDA ändert die Pod-Anzahl; die Knotenzahl bleibt gleich.
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 ist nach Zweck auf vier Knoten aufgeteilt. Der Speicher für PostgreSQL ist EBS CSI · gp3.
- k8s-postgresql
- k8s-redis-auth
- k8s-redis-streams
- k8s-redis-cache
- k8s-redis-pubsub
6Platform
Messaging, Beobachtung, Ingress und Echtzeit-Zustellung haben jeweils einen eigenen Knoten.
- k8s-rabbitmq
- k8s-monitoring
- k8s-logging
- k8s-ingress-gateway
- k8s-sse-gateway
- k8s-event-router
- Jeder Knoten
- Fluent Bit · DaemonSet
- Calico
Konfigurierte Modelle · nach Anbieter
Der Dienst wurde eingestellt, daher sind dies die im Repository konfigurierten Modelle, keine heute verfügbare Auswahl. Jede Rolle ist separat aufgeführt; es ist keine Liste verifizierter Läufe.
OpenAI
Standardanbieter für Chat
Chat
openai/gpt-5.2Standard
Das Standardmodell ist gpt-5.2; ein in der Anfrage genanntes Modell wird stattdessen verwendet.
Scan
gpt-5.2Standardgpt-5.2-progpt-5.1gpt-5gpt-5-progpt-5-mini
Modelle außerhalb der Zuordnung von 13 Modellen werden abgelehnt.
Bildzuordnung
gpt-image-1.5
Getrennt von gpt-5.2, dem Orchestrierungsmodell für Responses. Bildgenerierung ist standardmäßig aus.
Bewertung
gpt-4o-miniStandard
Der LLM-Grader für die Gesprächsbewertung, getrennt vom Chat-Modell.
Google
Wenn Chat Google wählt
Chat
google/gemini-3-pro-previewgoogle/gemini-3-flash-preview
Ist Google gewählt, ist gemini-3-flash-preview der 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
Bildzuordnung
gemini-3-pro-image-preview
Quellebackend main d8840c7Öffentlicher Commit September 29, 2026 · geprüft October 8, 2026