Files
document-haness/docs/keycloak-session-store/final/.techviz/b5-b6-storage-and-keys/spec.json
T

187 lines
5.1 KiB
JSON

{
"version": "1.1",
"id": "b5-b6-storage-and-keys",
"title": "볼륨 없는 영속화와 replica별 키 회전",
"question": "설정을 켰다는 사실만으로 영속화와 일관된 키 회전을 기대할 수 있는가",
"type": "architecture",
"direction": "LR",
"audience": [
"저장소와 키 회전을 운영하는 엔지니어"
],
"summary": "Redis AOF 는 볼륨이 없으면 컨테이너와 함께 사라진다. 키 회전 뒤에는 replica별 JWKS cache 상태가 달라 같은 옛 토큰이 401과 200을 번갈아 받았다.",
"alt": "운영 변경에서 Redis AOF는 볼륨 없는 데이터 디렉터리로 이어져 소멸하고, realm 키 회전은 replica별 JWKS cache 차이로 401과 200이 갈리는 두 경로.",
"long_description": "B-5에서는 appendonly yes 설정이 적용돼도 /data가 컨테이너 파일시스템이라 재시작 때 사라졌다. B-6에서는 옛 키를 지운 뒤 같은 토큰을 반복 요청하자 401과 200이 교대로 나왔다. echo replica 둘의 JWKS cache가 독립적이라 한쪽은 새 목록을 받아 옛 키를 잃었고 다른 쪽은 아직 들고 있었기 때문이다.",
"source_context": {
"document": "docs/keycloak-session-store/final/document.md",
"document_sha256": "28aef96a2bbb94fbb10ade26a71238fee62a5a4d9fa6e7749ae98cfd0a65e560",
"anchor": {
"kind": "heading",
"value": "B-5 · B-6 — 저장소 상실과 키 회전",
"line": 859
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "설정이 실제 저장 매체에 닿는가가 지배적 질문이다. 경로의 끝이 어디인가이므로 component-flow 를 골랐다."
},
"groups": [],
"nodes": [
{
"id": "change",
"label": "운영 변경",
"kind": "process",
"role": "source",
"emphasis": "normal",
"description": "저장 설정과 realm 키 회전을 각각 수행한다.",
"details": [
"B-5 · B-6"
],
"evidence": [
{
"start_line": 861,
"end_line": 872
}
],
"assumption": false
},
{
"id": "datadir",
"label": "Redis /data",
"kind": "datastore",
"role": "control",
"emphasis": "warning",
"description": "AOF가 기록되는 컨테이너 파일시스템이다.",
"details": [
"appendonly yes · 볼륨 없음"
],
"evidence": [
{
"start_line": 861,
"end_line": 863
}
],
"assumption": false
},
{
"id": "lost",
"label": "Redis 재시작",
"kind": "component",
"role": "target",
"emphasis": "warning",
"description": "볼륨이 없어 데이터가 함께 사라진다.",
"details": [
"영속화 실패"
],
"evidence": [
{
"start_line": 861,
"end_line": 863
}
],
"assumption": false
},
{
"id": "replicas",
"label": "echo replica 2개",
"kind": "service",
"role": "control",
"emphasis": "warning",
"description": "JWKS cache를 인스턴스마다 따로 가진다.",
"details": [
"replica별 cache"
],
"evidence": [
{
"start_line": 868,
"end_line": 872
}
],
"assumption": false
},
{
"id": "mixed",
"label": "교차 응답",
"kind": "component",
"role": "target",
"emphasis": "primary",
"description": "같은 옛 토큰의 검증 결과가 replica에 따라 갈린다.",
"details": [
"401 · 200 · 반복"
],
"evidence": [
{
"start_line": 868,
"end_line": 877
}
],
"assumption": false
}
],
"edges": [
{
"id": "c-d",
"from": "change",
"to": "datadir",
"label": "AOF 설정",
"kind": "write",
"evidence": [
{
"start_line": 861,
"end_line": 863
}
],
"assumption": false
},
{
"id": "d-l",
"from": "datadir",
"to": "lost",
"label": "볼륨 없음",
"kind": "blocked",
"evidence": [
{
"start_line": 861,
"end_line": 863
}
],
"assumption": false
},
{
"id": "c-r",
"from": "change",
"to": "replicas",
"label": "키 회전",
"kind": "request",
"evidence": [
{
"start_line": 865,
"end_line": 872
}
],
"assumption": false
},
{
"id": "r-m",
"from": "replicas",
"to": "mixed",
"label": "cache 상태",
"kind": "request",
"evidence": [
{
"start_line": 868,
"end_line": 877
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "B-5와 B-6를 같은 실패로 합치지 않고, 설정이 실제 매체와 인스턴스별 cache에 닿을 때 각각 어떤 결과가 나는지 두 갈래로 연결했다."
}
}