{ "version": "1.1", "id": "lab-topology", "title": "실험대의 구성", "question": "이 실험들은 어떤 기계 위에서 돌았는가", "type": "architecture", "direction": "TB", "audience": [ "같은 실험을 재현하려는 백엔드 엔지니어" ], "summary": "베어메탈 한 대 위의 VM 두 대에 k3s 를 올리고, 호스트 nginx 가 TLS 를 끝낸 뒤 traefik 으로 넘긴다.", "alt": "test-server 호스트의 nginx 가 kc-lab-1 의 traefik 으로 프록시하고, 그 아래 두 VM 에 Keycloak 과 데이터 저장소가 나뉘어 있는 구성.", "long_description": "베어메탈 test-server 위에 VM 두 대를 올렸다. kc-lab-1 이 k3s server 이자 컨트롤 플레인이고 keycloak-1 이 여기 있다. kc-lab-2 는 agent 이며 keycloak-0 과 PostgreSQL, Redis 가 함께 있다. 저장소가 한 노드에 몰려 있어 그 노드를 잃으면 DB 도 같이 잃는다. 호스트 nginx 가 Let's Encrypt 인증서로 TLS 를 끝내고 traefik 으로 넘기며, 인증서 하나에 auth·app1·app2 세 이름이 SAN 으로 들어 있다.", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", "anchor": { "kind": "heading", "value": "실험대", "line": 85 } }, "composition": { "profile": "query-fanout", "diagram_only": true, "reference_ids": [ "metrics-query-fanout" ], "rationale": "호스트 nginx 에서 들어온 요청이 traefik 을 거쳐 두 Keycloak 노드로 갈라지는 것이 이 절의 지배적 구조다. 하나의 진입점에서 여러 백엔드로 퍼지는 모양이므로 query-fanout 을 골랐다." }, "groups": [], "nodes": [ { "id": "nginx", "label": "호스트 nginx", "kind": "gateway", "role": "source", "emphasis": "primary", "description": "Let's Encrypt 인증서로 TLS 를 끝내고 traefik 으로 넘긴다.", "details": [ "SAN: auth · app1 · app2" ], "evidence": [ { "start_line": 88, "end_line": 92 } ], "assumption": false }, { "id": "traefik", "label": "traefik (kc-lab-1)", "kind": "gateway", "role": "control", "emphasis": "normal", "description": "k3s 의 인그레스. 호스트 이름으로 서비스를 고른다.", "details": [ "k3s server 노드" ], "evidence": [ { "start_line": 85, "end_line": 87 } ], "assumption": false }, { "id": "keycloak-1", "label": "keycloak-1", "kind": "service", "role": "shard", "emphasis": "primary", "description": "컨트롤 플레인 노드에 있다.", "details": [ "kc-lab-1" ], "evidence": [ { "start_line": 85, "end_line": 86 } ], "assumption": false }, { "id": "keycloak-0", "label": "keycloak-0", "kind": "service", "role": "shard", "emphasis": "primary", "description": "저장소와 같은 노드에 있다.", "details": [ "kc-lab-2" ], "evidence": [ { "start_line": 86, "end_line": 87 } ], "assumption": false }, { "id": "stores", "label": "PostgreSQL · Redis", "kind": "datastore", "role": "store", "emphasis": "warning", "description": "둘 다 kc-lab-2 에 있다. 이 노드를 잃으면 저장소도 같이 잃는다.", "details": [ "kc-lab-2" ], "evidence": [ { "start_line": 86, "end_line": 87 } ], "assumption": false } ], "edges": [ { "id": "tls", "from": "nginx", "to": "traefik", "label": "TLS 종단", "kind": "request", "evidence": [ { "start_line": 88, "end_line": 92 } ], "assumption": false }, { "id": "to-k1", "from": "traefik", "to": "keycloak-1", "label": "라우팅", "kind": "request", "evidence": [ { "start_line": 85, "end_line": 87 } ], "assumption": false }, { "id": "to-k0", "from": "traefik", "to": "keycloak-0", "label": "라우팅", "kind": "request", "evidence": [ { "start_line": 85, "end_line": 87 } ], "assumption": false }, { "id": "k0-store", "from": "keycloak-0", "to": "stores", "label": "같은 노드", "kind": "read", "evidence": [ { "start_line": 86, "end_line": 87 } ], "assumption": false } ], "legend": [], "metadata": { "rationale": "저장소가 kc-lab-2 한 곳에 몰린 것을 그림에서 읽히게 배치했다. A-4 의 두 결과가 이 배치에서 갈린다." } }