Files
keycloak-pattern/docs/experiment-index.md
DongHyeonkaandClaude Opus 5 cdac9b8178 docs: give the twelve experiments that had no architecture diagram one
An audit against the standard the series set — concepts, procedure,
commands, architecture diagram, evidence table, terminal output — found the
three new experiments met it while twelve of the original ones had no
diagram at all: A-0, A-1, A-3, A-4, A-5, A-6, A-8, B-0, B-2, B-7, C-2, D-2.

Each now has one drawn from what that experiment actually found, not filler:
A-0 shows sharing going through PostgreSQL rather than between the caches;
A-3 the gap between the 200 and the WAL flush, with both failed injections;
A-5 the three silent injection failures; A-6 the two places latency is
multiplied; B-0 the repository keyed by principal with no session id; B-2
the primary key that causes the overwrite; D-2 why the rolling update
stopped the accident halfway.

Also corrected the index's stale claim of 11 experiments without a
screenshot — it is 14, and the reason is recorded: those experiments were
measured from terminals, the database and logs, and the observability stack
does not scrape Redis, the BFF or PostgreSQL, so there is no console to
photograph.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 21:44:36 +09:00

8.4 KiB
Raw Permalink Blame History

실험 색인 — 23개 전부

각 실험은 자기 브랜치에 있고, 해설 문서와 증거 폴더가 한 벌이다.

# 실험 브랜치 한 줄 결과
A-0 세션 복제 확인 ...multinode-cluster-jdbc-ping 세션 공유는 Infinispan 이 아니라 PostgreSQL 이 한다
A-1 TCP 7800 차단 ...a1-jgroups-transport-block 세션은 견디지만 로그아웃 무효화가 7800 을 탄다
A-2 DB 정상 정지 ...a2-database-loss 전면 장애. 그런데 up 은 1이었다
A-3 DB 강제 종료 ...a3-database-crash 153건 중 4건의 로그인이 사라졌다
A-4 노드 전원 차단 ...a4-node-loss 죽은 파드가 산 파드보다 건강해 보인다
A-5 비대칭 파티션 ...a5-asymmetric-partition 단방향은 자가 치유. 완전 분단도 한쪽은 산다
A-6 지연 주입 ...a6-latency-injection 200ms → 22초 (왕복 × 풀 큐잉)
A-7 volatile 비교 ...a7-volatile-comparison 세 결과가 정반대로 뒤집힌다
A-8 롤링 재시작 ...a8-rolling-restart 무중단 + 세션 생존
B-0 자동구성 확인 ...b0-bff-redis-deploy 조회 키에 session id 가 없다
B-1 Redis 세션 ...b1-redis-session-store 세션만 옮겨지고 토큰은 남는다
B-2 다중 인스턴스 ...b2-multi-instance-session 공유는 되지만 평문·덮어쓰기·로그아웃 미정리
B-3 refresh 경쟁 ...b3-refresh-token-contention 경쟁이 아니라 세션이 파괴된다
B-4 Edge 인가 ...b4-edge-authorization-scope nginx 는 설정하지 않은 헤더를 덮어쓰지 않는다
B-5 Redis 상실 ...b5-redis-loss-persistence 파드가 Ready 인 채로 계속 실패한다
B-6 key 회전 ...b6-key-rotation 회전은 안전, 옛 키를 버리는 순간이 위험
B-7 cookie secret ...b7-cookie-secret-rotation 겹침 구간이 없고 세션이 고아로 남는다
C-1 다중 앱 SSO ...c1-multi-app-sso IdP 세션을 죽여도 아무도 로그아웃되지 않는다
C-2 백채널 로그아웃 ...c2-backchannel-logout 받는 쪽을 아무도 구현하지 않았다
D-1 백업·복구 ...d1-backup-restore 빈 데이터베이스가 200 을 냈다
D-2 버전 업그레이드 ...d2-version-upgrade 이미지를 되돌려도 스키마는 안 돌아온다
D-3 비밀 관리 ...d3-secret-management RBAC 만 실제로 감춘다
D-4 인증서 갱신 ...d4-certificate-renewal 갱신은 됐는데 38분 25초 반영 안 됨 (훅 3경로 전부 비었음). reload 자체는 무중단(8856건 0실패)
A-7a volatile refresh 500 원인 확정 ...a7a-volatile-cause 가설(REVOKED_TOKEN)은 틀렸다CLIENT_SCOPE_CLIENT 조회다. A-7 의 표는 캐시 온도에 따라 400/500/200
B-7a 고아 세션 정리 ...b7a-orphan-session 지울 수 있다 — 프록시가 못 할 뿐. TTL 역산으로 고아만 1초 오차로 골라낸다
D-4a deploy 훅 검증 ...d4a-deploy-hook 처방이 듣는다 — 발급→서빙 1~2초(D-4 는 38분 25초). test-server 시계가 106초 빨라 D-4 수치를 정정
후속 미측정 3항목 채우기 ...followup-untested-items 셋 다 완료. 정방향 업그레이드 무중단 · 롤백 불가는 조건부였다 · role 변경은 요청으로 반영 안 됨 · D-4 갱신 38분 25초 미반영

시각 자료

diagrams/lab-topology.svg 실험대 전체 구조
diagrams/_style.md 다이어그램 규약 (붉은 점선 = 죽인 것)
diagrams/*.svg 실험별 구조도 12개
evidence/*/*.png Grafana · 브라우저 스크린샷

스크린샷이 없는 실험은 14개다A-3 A-7 A-7a B-3 B-4 B-5 B-6 C-2 D-1 D-3 D-4 D-4a 후속 멀티노드. 없는 이유는 관측 대상에 그 지표가 없기 때문이지 안 찍어서가 아니다 — Prometheus 는 keycloak·kubelet·node-exporter·prometheus 만 긁는다 (followup/04-observability-gap.txt). 터미널·DB·로그로 측정한 실험은 브라우저에 띄울 화면 자체가 없다.

구조도(SVG)는 28개이고, 실험 문서 29개 중 28개가 하나 이상을 싣는다. 싣지 않는 하나는 후속 요약 문서이며, 세 실험의 구조도를 표로 참조한다. 그중 B층은 Prometheus 가 Redis·BFF·PostgreSQL 을 긁지 않아 만들 수가 없다 — followup/04-observability-gap.txt 에 측정해 두었다.

문서 지도

문서 용도
session-lab-prerequisites.md 먼저 읽을 것 — 왜 이런 걸 재는지
experiment-plan.md 23개의 구조도·주입 방법·예측
open-questions-coverage.md 공개 열린 질문 4개 대조
session-lab-concepts.md 등장 개념 전체 (13층)

문서가 자기 증거와 어긋났던 곳

서브에이전트 감사(2026-09-04)에서 찾아 정정한 것들이다.

문서 무엇이 틀렸나
C-1 세션 수를 0 으로 인쇄. 증거는 4
C-2 exit code 1 로 실패한 명령의 성공 출력을 인쇄
A-1 conntrack 삭제에 분단을 귀속. 실제로는 파드 재시작 4초 뒤
A-2 ④ 의 첫 측정이 오염됐는데 정제된 값만 인쇄
A-3 wal_writer_delay 를 재지 않고 "기본값과 맞는다"
A-6 대조군이 −41% 변했는데 "영향 없음"
A-8 표본 9개로 "무중단"
B-2 "두 브라우저" — 실제로는 세션만 지웠다. Liquibase 오귀속
D-1 RTO 30초 — 실제 41초
D-2 "롤백 불가" 단정 — 조건부였다

png 6장이 실은 3장(동일 내용이라 바이트가 같다)이고, a5/02-injection-verify.txt 는 0바이트였다. 각 증거 README 에 명시했다.

반복해서 배운 것 — 주입이 안 걸린 사례

아홉 번 있었다. 전부 "아무 일도 없었다" 로 보였다.

실험 안 걸린 주입 원인
A-1 NetworkPolicy 로 7800 차단 conntrack ESTABLISHED 가 먼저 통과시킨다
A-3 delete --grace-period=0 --force 컨테이너 런타임이 SIGTERM → 정상 종료
A-3 kill -9 1 컨테이너 안에서 PID 1 은 SIGKILL 을 무시한다
A-5 iptables -I FORWARD 1 kube-router 가 자기 체인을 위로 재삽입
A-5 raw 테이블, 반대 노드 연결 방향이 뒤집혀 있었다
A-6 tc ... dev eth0 인터페이스가 enp1s0 이다
A-6 enp1s0 에 파드 IP 필터 VXLAN 캡슐화로 안 보인다
B-2 spring.sql.init 스키마 PostgreSQL 에 없는 blob 타입 + continue-on-error
B-7·D-4 sudo nginx -T 호스트 sudo 가 비밀번호를 요구한다. D-4 는 사용자가 직접 실행해 해소했다

그래서 실험마다 "주입 성공 신호" 를 먼저 정하게 됐다cluster_size 하락, not properly shut down 로그, iptables 패킷 카운터, tc -s qdiscSent.

예측이 빗나간 곳

실험 예측 실제
A-1 로그아웃 전파는 안 깨진다 깨졌다 — 무효화는 7800 을 탄다
A-2 up 이 잡아줄 것 1로 평평했다
A-6 낙관적 락 충돌이 는다 0건 — 로그인은 새 행을 만든다
B-4 nginx 가 동명 헤더를 덮어쓴다 둘 다 도착했다
B-6 JWKS 캐시가 유예를 준다 즉시 401

말할 수 있는 것과 없는 것

말할 수 있다 — Keycloak 멀티노드에서 세션과 토큰이 어디에 저장되고 각 저장소가 죽으면 무엇이 어떻게 실패하는지 재현하고 복구했다. 버전에 따라 결론이 뒤집힌다는 것을 같은 주입으로 양쪽 다 측정했다.

말하면 안 된다 — "운영해봤다", "대규모 트래픽을 다뤄봤다". 규모·시간·다른 사람·실제 사용자·비용은 이 실험대에 없다.