Files
document-haness/docs/keycloak-session-store/final/evidence/raw/README.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

321 lines
21 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
raw — 명령 출력 원문 (정본)
===================
이 폴더가 증거의 정본이다. SVG 는 표현물이고 여기 원문 없이는 만들지 않는다.
파일 이름은 <실험 폴더>__<원본 파일명> 이다. 원본 저장소에서는 실험마다
폴더가 나뉘어 있었고 파일명이 겹쳤다(01-baseline.txt 등). 이 저장소의 감사
스크립트는 raw/ 최상위만 훑으므로 이름을 평평하게 펴고 접두사로 구분했다.
각 파일의 실행 메타는 ../meta/<같은 이름>.json 에 있다.
명령 전문은 그 json 의 sourceDoc 이 가리키는 해설 문서의 「재현 절차」 절에 있다.
[a1-jgroups-transport-block]
a1-jgroups-transport-block__01-baseline-cluster.txt
차단 전 — 양쪽이 뷰 ID 5·멤버 2로 일치, JGROUPS_PING 코디네이터 1명
a1-jgroups-transport-block__02-control-before-block.txt
대조군 — 차단 전 교차 노드 refresh 200, JGroups 지표 전부 0
a1-jgroups-transport-block__03-block-applied.txt
NetworkPolicy 적용. 빈 측정값을 "변화 감지"로 오판한 기록
a1-jgroups-transport-block__04-after-block-state.txt
차단 43초 후 — 지표 무변화, JGROUPS_PING 그대로
a1-jgroups-transport-block__05-conntrack-problem.txt
핵심 문제 — ESTABLISHED [ASSURED] 로 기존 연결이 살아 있음. FD_SOCK2 의 57800 포트도 함께 드러남
a1-jgroups-transport-block__06-partition-observed.txt
임시 curl 파드 폴링의 실패 — 빈 값·개수 불일치
a1-jgroups-transport-block__07-cluster-size.txt
vendor_cluster_size 가 25분 내내 2 — 분단이 일어나지 않았다는 결정적 증거
a1-jgroups-transport-block__08-restart-forced-partition.txt
재연결 강제 후 2 → 1
a1-jgroups-transport-block__09-cross-node-under-partition.txt
본 시험 — 교차 refresh 200(예측 적중), 로그아웃 후 재갱신 200(예측 빗나감)
a1-jgroups-transport-block__10-logout-not-propagated.txt
기제 확정 — DB 행 0건인데 keycloak-0 캐시에 1건, 헬스체크 cluster health: DOWN
a1-jgroups-transport-block__11-service-impact.txt
분단 노드가 Service 에서 빠짐. ready=[10.42.0.35] notReady=[10.42.1.67], 외부 로그인 200
a1-jgroups-transport-block__12-recovery.txt
90초 만에 자동 재형성, merge3_get_num_merge_events = 1, 코디네이터 재선출
[a2-database-loss]
a2-database-loss__01-baseline.txt
정지 전 — 양쪽 Ready, cluster_size=2
a2-database-loss__02-setup-sessions.txt
양쪽 노드에 세션 하나씩. 캐시는 각자 노드에만
a2-database-loss__03-four-paths.txt
네 경로 전부 500. 캐시를 가진 노드도 실패 — refresh 는 쓰기다
a2-database-loss__04-health-and-service.txt
전면 장애 증거 — Ready 파드 0개, ready 주소=[], 외부 503, database connections: DOWN. JWKS·.well-known 은 200
a2-database-loss__05-recovery.txt
up=1 인 채로 503. DB 복귀 15초 후 재시작 0회로 자동 회복, 세션 5건 생존
[a3-database-crash]
a3-database-crash__01-crash-injection.txt
첫 시도 실패 — 파드 안 백그라운드 루프가 exec 종료와 함께 죽어 0건 수집
a3-database-crash__02-design-check.txt
핵심 설계 확인 — 로그인 트랜잭션도 SET LOCAL synchronous_commit TO OFF 로 커밋한다
a3-database-crash__03-loss-measurement.txt
--grace-period=0 --force 주입
a3-database-crash__04-comparison.txt
유실 0건 — 그러나 crash recovery 가 안 돌았다. 죽인 적이 없는 것
a3-database-crash__05-true-crash.txt
kill -9 1 시도 — 컨테이너 안에서 PID 1 은 SIGKILL 을 무시한다
a3-database-crash__06-backend-kill-crash.txt
성공한 주입 — 백엔드에 SIGKILL → not properly shut down / redo starts / redo done
a3-database-crash__07-loss-result.txt
결과: 153건 중 4건 유실. 토큰은 발급됐는데 세션 행이 없는 sid 목록
a3-database-crash__08-wal-settings.txt
(원본 README 에 설명이 없다 — 파일 머리말 참조)
[a4-node-loss]
a4-node-loss__01-baseline.txt
차단 전 — 양쪽 Ready, PVC 가 kc-lab-2 에 못박혀 있음(재배치 불가의 원인), 외부 200
a4-node-loss__02-worker-node-killed.txt
virsh destroy kc-lab-2 — 40초간 노드가 Ready 로 남아 있고 외부는 이미 000. 이후 503
a4-node-loss__03-state-during-loss.txt
죽은 파드가 ready=true, 산 파드가 ready=false. up 은 정확히 0. unreachable taint
a4-node-loss__04-eviction-timing.txt
tolerationSeconds=300 — 5분 뒤 축출, 새 postgres 는 Pending
a4-node-loss__05-recovery.txt
FailedScheduling: didn't match PersistentVolume's node affinity, StatefulSet DESIRED=2 CURRENT=1. 노드 복귀 후 60초
a4-node-loss__06-control-plane-inventory.txt
kc-lab-1 에 있는 것 목록 — Traefik replicas=1
a4-node-loss__07-control-plane-loss.txt
virsh destroy kc-lab-1 — 외부 000, kubectl 불통. 그런데 crictl ps 로 보면 keycloak-0 은 Running
a4-node-loss__08-control-plane-recovery.txt
60초 만에 복귀
[a5-asymmetric-partition]
a5-asymmetric-partition__01-injection.txt
첫 시도 — iptables -I FORWARD 1
a5-asymmetric-partition__02-injection-verify.txt
실패 확인 — kube-router 가 자기 체인을 위로 재삽입, DROP 규칙 0 패킷
a5-asymmetric-partition__03-raw-table-injection.txt
raw 테이블로 이동. 그래도 0 패킷
a5-asymmetric-partition__04-correct-direction.txt
연결 방향이 반대였다. 수신측 노드로 옮기니 19/21 패킷 차단
a5-asymmetric-partition__05-reconnect-observed.txt
핵심 — 연결이 열린 방향으로 뒤집혀 재연결. 뷰 변화 없음, suspected=0
a5-asymmetric-partition__06-view-history-and-cleanup.txt
뷰 ID 이력. 주입 이후 변화 없음 확인
a5-asymmetric-partition__07-bidirectional-block.txt
양방향 차단 → 뷰 14, 멤버 1개씩. 그런데 ready=[10.42.1.77] 로 한쪽은 남고 외부 200
a5-asymmetric-partition__08-coordinator-and-recovery.txt
15] (2)
[a6-latency-injection]
a6-latency-injection__01-baseline.txt
배치 설명(A/B 가 되는 이유), agroal_* 지표 목록, 기준선 70ms / 66ms
a6-latency-injection__02-delay-injected.txt
첫 시도 실패 — Cannot find device "eth0" (Debian 은 enp1s0)
a6-latency-injection__03-flannel-injection.txt
성공 — flannel.1 에 걸어야 파드 IP 가 보인다. netem Sent 150 pkt 로 검증. k0=41ms vs k1=1872ms
a6-latency-injection__04-pool-under-load.txt
동시 20건 — 응답이 1.9초에서 22.2초까지 계단. blocking_time_max=20000ms, max_used_count=19, readiness 프로브 타임아웃
a6-latency-injection__05-recovery.txt
해제 즉시 43ms / 51ms 회복. 낙관적 락 충돌 0건(예측 빗나감)
[a7-volatile-comparison]
a7-volatile-comparison__01-switch-to-volatile.txt
--features-disabled=persistent-user-sessions 적용, args 확인
a7-volatile-comparison__02-a0-rerun.txt
DB 0건인데 교차 노드 refresh 200 — 경로가 DB 에서 클러스터로 바뀌었다
a7-volatile-comparison__03-a8-rerun-restart.txt
롤링 재시작 후 400 Session not active — persistent 에서는 200 이었다
a7-volatile-comparison__04-a1-rerun-partition.txt
7800 차단 시 교차 노드 400 — persistent 에서는 200. 대조군(같은 노드)은 200 유지
a7-volatile-comparison__05-a2-rerun-db-loss.txt
DB 정지 중 새 로그인 200(persistent 에서는 500), refresh 는 500
a7-volatile-comparison__06-restore-persistent.txt
원복 확인 — args: ["start"], 로그인 후 DB 1건, 외부 200
[a7a-volatile-cause]
a7a-volatile-cause__01-cause-determined.txt
가설이 틀렸다. REVOKED_TOKEN 이 아니라 CLIENT_SCOPE_CLIENT 조회다. 문장 로깅으로 잡고, 실패 로그가 그 SQL 을 직접 지목한다. 그리고 같은 설정에서 캐시 온도만으로 400/500/200 셋이 나온다
[a8-rolling-restart]
a8-rolling-restart__01-restart-availability.txt
재시작 전 로그인(sid 기록), 롤링 재시작 중 외부 진입점 9회 모두 200
a8-rolling-restart__02-session-survival.txt
재시작 전 토큰으로 refresh 200, DB 행 생존(last_session_refresh 갱신 확인), 세션 수 151 → 151, 캐시 0으로 초기화, 파드 나이 44초/66초
[b0-bff-redis-deploy]
b0-bff-redis-deploy__01-deploy.txt
배포 전 자원, Redis·BFF 롤아웃, 두 노드에 하나씩 배치됨
b0-bff-redis-deploy__02-autoconfiguration.txt
첫 조회 시도(파싱 실패)와 외부 진입점 HTTP 200
b0-bff-redis-deploy__03-beans-analysis.txt
B-0 의 답 — InMemoryOAuth2AuthorizedClientService, AuthenticatedPrincipalOAuth2AuthorizedClientRepository, Redis·Spring Session 없음
[b1-redis-session-store]
b1-redis-session-store__01-servicelinks-trap.txt
enableServiceLinks: false 적용 후 롤아웃 성공 — 쿠버네티스가 주입한 REDIS_PORT=tcp://... 가 설정을 덮어쓴 문제
b1-redis-session-store__02-autoconfig-after.txt
핵심 — 빈 321→402(+81). sessionRepository → RedisSessionRepository 로 바뀌었지만 authorizedClientService 는 InMemory 그대로
b1-redis-session-store__03-redis-contents.txt
Redis 키 1개, 필드는 SPRING_SECURITY_CONTEXT 뿐. 토큰 없음. Java 직렬화(\xac\xed), TTL 1772초
[b2-multi-instance-session]
b2-multi-instance-session__01-jdbc-store-deploy.txt
JDBC 저장소로 배포. 테이블이 조용히 안 만들어졌다
b2-multi-instance-session__02-schema.txt
원인 — 기본 DDL 은 blob(PostgreSQL 에 없음), -postgres.sql 판본이 따로 있다. PRIMARY KEY (client_registration_id, principal_name) — 조회 키 문제가 DDL 에 박혀 있다
b2-multi-instance-session__03-plaintext-tokens.txt
Q3 검증 2번 — bytea 안이 JWT 문자열 그대로. 디코드하면 {"alg":"HS512",...}
b2-multi-instance-session__04-overwrite-test.txt
Q1 검증 3번 — 같은 사용자 재로그인 시 행 수 1 그대로, issued_at 과 md5 만 바뀜 = UPDATE(덮어쓰기)
b2-multi-instance-session__05-logout-cleanup.txt
Q1 검증 4번 — Redis 0키 / PostgreSQL 1행 잔존 / Keycloak SSO 2세션 잔존
[b3-refresh-contention]
b3-refresh-contention__01-concurrent-refresh.txt
같은 토큰으로 동시 5회 — 1개만 200, 나머지는 Maximum allowed refresh token reuse exceeded 와 Session doesn't have required client 두 종류 오류
b3-refresh-contention__02-session-impact.txt
★ 이긴 요청의 새 토큰조차 400. user_session 행은 남아 있고 revoked_token 은 0건
b3-refresh-contention__03-client-session-removed.txt
기제 확정 (대조군 포함) — 경쟁 세션 client_sessions=0, 정상 세션 client_sessions=1
b3-refresh-contention__04-policy-comparison.txt
정책 3종 비교 — rotation OFF 는 5/5 성공·세션 생존, maxReuse=1 은 여전히 세션 파괴
[b4-edge-authorization]
b4-edge-authorization__01-header-handling.txt
① 동명 헤더가 둘 다 도착(['admin','editor'])하고 값 안의 쉼표를 구분자와 구별할 수 없다 · ② 8KB 에서 Tomcat 400, 16KB 에서 연결 끊김 — 자르지 않고 거부 · ④ 위조 신원 헤더가 그대로 도착, JWT 경로는 401
[b5-redis-loss]
b5-redis-loss__01-baseline.txt
정지 전 — Redis 1키, PostgreSQL 1행, save/appendonly no, 외부 200
b5-redis-loss__02-redis-down.txt
정지 후 — /bff/token-boundary HTTP 000(멈춤), /actuator/health 503, 파드는 1/1 Ready 유지, Lettuce 재연결 스택
b5-redis-loss__03-health-groups.txt
핵심 — /actuator/health 503 인데 /actuator/health/readiness 는 {"status":"UP"}. Service 엔드포인트에 두 파드 모두 남아 있다
b5-redis-loss__04-persistence.txt
복구는 자동(재시작 0회) · AOF 를 켰는데 파드 삭제 후 dbsize 0 · PVC 를 붙인 뒤 written-on-pvc 생존
[b6-key-rotation]
b6-key-rotation__01-before-rotation.txt
회전 전 — 토큰 kid=OY-caYDN..., JWKS RS256 1개, /api/me 200
b6-key-rotation__02-rotation.txt
우선순위 200 공급자 추가 → JWKS RS256 2개, 새 토큰은 새 kid, 옛 토큰도 새 토큰도 200 (무중단)
b6-key-rotation__03-old-key-removed.txt
옛 공급자 제거 → JWKS 1개, 옛 토큰 즉시 401. 리소스 서버 재시작 후에도 동일
[b7-cookie-secret]
b7-cookie-secret__01-deploy.txt
양 노드에 replica 하나씩. / 302, /ping 200
b7-cookie-secret__02-cookie-portability.txt
curl 로 흐름을 완주하려던 시도 — 파드 IP 는 호스트에서 안 닿는다
b7-cookie-secret__03-rotation.txt
--cookie-secret string 단수 확인 · 교체 후 session ticket cookie failed validation · Error removing session · Redis 에 고아 세션 2개
[b7a-orphan-session]
b7a-orphan-session__01-orphan-lifecycle.txt
회전 2회로 고아가 누적하는 것 · TTL 이 1초/초로 줄고 요청으로 갱신되지 않는 것 · Redis 만으로는 구분 불가(이름·타입·크기 동일, 값 암호화) · redis-cli del 로 지워도 산 세션은 200 · TTL 역산 정리 규칙이 1초 오차로 맞는 것
[c1-multi-app-sso]
c1-multi-app-sso__01-baseline.txt
초기화 시도 — logout-all 이 안 먹어 세션 4개가 남았다
c1-multi-app-sso__02-after-app1-login.txt
app1 로그인 후 — user session 1 · client session 1 · Redis 1 · DB 1행
c1-multi-app-sso__03-after-app2-visit.txt
app2 방문 후 client session 1 → 2, bff-confidential 과 oauth2-proxy 가 같은 user session 에 붙음. Redis 에 두 종류 세션
c1-multi-app-sso__04-sso-session-killed.txt
IdP 세션 삭제 후 — 앱 세션 셋 다 남아 있다. realm 을 join 해 보고서야 남은 것이 master 세션임을 확인
[c2-backchannel-logout]
c2-backchannel-logout__01-current-state.txt
두 클라이언트 모두 backchannelLogoutUrl 없음 · BFF 소스에 oidcLogout 없음 · 후보 경로 셋 다 302(핸들러 없음)
c2-backchannel-logout__02-configure-idp.txt
IdP 쪽에만 backchannel.logout.url 설정 (점 표기는 실패, JSON 으로 성공)
c2-backchannel-logout__03-logout-attempt.txt
살아 있는 세션(1)에 로그아웃 → IdP 세션 0, Redis 세션은 1 그대로. Keycloak·BFF 로그에 흔적 없음
c2-backchannel-logout__04-reachability.txt
Keycloak 파드가 app1.hyeonworks.com 에 HTTP 200 으로 닿는다 — 네트워크 문제가 아님
[d1-backup-restore]
d1-backup-restore__01-backup.txt
pg_dump --clean --if-exists — 395KB · 101 테이블 · 세션 데이터 포함
d1-backup-restore__02-destruction.txt
DROP SCHEMA public CASCADE → 테이블 0개. 그런데 외부는 HTTP 200 — Keycloak 이 realm 캐시로 서빙한다
d1-backup-restore__03-restore.txt
깨지는 것과 안 깨지는 것(certs 200 / well-known 500 / 토큰 400) · 복구 1초 · 오류 0건 · 데이터 완전 일치 · 재시작 0회
[d2-version-upgrade]
d2-version-upgrade__01-pre-upgrade.txt
백업 396KB · 이미지 26.7.0 · 마이그레이션 210건 · 세션 4
d2-version-upgrade__02-rollback-attempt.txt
26.0 으로 내리자 Running(0/1) → Error → CrashLoopBackOff. liquibase.exception.ValidationFailedException
d2-version-upgrade__03-roll-forward.txt
서비스는 HTTP 200 유지(ready 주소 1개) · 오류 원인 1 changesets check sum · 26.7.0 복귀 후 마이그레이션 210·세션 4 그대로
[d3-secret-management]
d3-secret-management__01-base64-not-encryption.txt
실험대의 모든 비밀이 명령 네 줄로 평문 출력. describe 는 14 bytes 만 보여줘 착각을 준다
d3-secret-management__02-at-rest.txt
Encryption Status: Disabled · state.db 안에 비밀번호 평문 2회 일치 · 파드 안에서는 KEYCLOAK_CLIENT_SECRET=bff-lab-secret 환경변수 · default SA 는 읽을 수 없음
[d4-certificate-renewal]
d4-certificate-renewal__01-certificate-state.txt
SAN 3개(와일드카드 아님) · 체인 4단계, Verify return code: 0 · certbot-renew.timer enabled·active, 11시간 전 실행 · 88일 남음 · sudo: a password is required 로 강제 갱신 불가
d4-certificate-renewal__05-control-no-injection.txt
대조군 1 — 잡음 바닥. 0.2초 × 900회 / 180초 동안 900 전부 200, 오류 0. 중앙 98ms · p95 195ms. TLS 핸드셰이크 900/900 = 매 요청이 새 연결
d4-certificate-renewal__06-inflight-control.txt
대조군 2 — '진행 중이던 요청' 장치. 845KB 를 --limit-rate 20k 로 받아 요청을 42초간 살려 둔다. 무주입 시 200 · 845361바이트 · 연결수 1
d4-certificate-renewal__07-renewal-hook-missing.txt
nginx 는 reload 된 적이 없다 — 마스터 585·워커 586 이 같은 시각 기동, 22.4시간째. 유닛은 ExecStart=certbot -q renew 가 전부. crt.sh 는 SCT 가 박힌 인증서를 0건으로 답한다
d4-certificate-renewal__08-inflight-artifact.txt
76건 실패는 서버 탓이 아니다 — 같은 순간 폴링 49건 전부 200, 연결수=0, 50µs, 재현 0/100. 대조군이 오보를 막았다
d4-certificate-renewal__09-serial-timeline.txt
일련번호 564표본. 08:10:51 ~ 08:58:47 옛 것 → 08:58:52 새 것
d4-certificate-renewal__10-reload-poll-window.txt
reload 전후 60초 새 연결 원문 — 비200 0건, 최대 373ms
d4-certificate-renewal__11-inflight-full.txt
in-flight 전체 50건. 08:58:40 시작 요청이 08:58:52 reload 를 관통해 845361바이트 전량 수신
d4-certificate-renewal__12-certbot-state.txt
cert2.pem 09-04 17:22:13 기록됨 · renewal-hooks/{deploy,post,pre}/ 셋 다 비었음 · 플러그인 목록에 nginx 없음
d4-certificate-renewal__13-verdict.txt
판정 전문 — 38분 25초 공백(428회 관측) + reload 무중단(8856건 0실패)
[d4a-deploy-hook]
d4a-deploy-hook__01-hook-verified.txt
판정 전문. 훅 실행 로그 · 워커 PID 교체 · 시계 보정과 SCT 교차검증 · D-4 와의 대조
d4a-deploy-hook__02-certbot-with-hook.txt
certbot renew --force-renewal 원문. Hook 'deploy-hook' ran 과 all renewals succeeded
d4a-deploy-hook__03-after-state.txt
실행 후 nginx 프로세스와 서빙 인증서
[followup]
followup__01-d2-forward-upgrade.txt
D-2 정방향 26.7.0 → 26.7.3. 백업 396KB · 87회 요청 전부 200(무중단) · 마이그레이션 210 → 210(스키마 변경 없음) · 세션 3 유지 · Infinispan 16.0.12 → 16.0.14
followup__02-d2-rollback-same-schema.txt
스키마가 안 바뀌면 롤백이 된다 — 26.7.3 → 26.7.0 성공. 다만 전환 순간 000 1회(3초 타임아웃)
followup__03-b4-role-propagation.txt
B-4 ③ IdP 에서 값을 바꿔도 12회 요청·6초 동안 옛 값. 세션 삭제 후 재인증에서야 새 값
followup__04-observability-gap.txt
B층에 관측이 없다 — Prometheus 는 keycloak·kubelet·node-exporter·prometheus 만 긁는다. Redis·BFF·PostgreSQL 지표가 0개
followup__05-command-reproducibility.txt
재현 절차 명령을 실제로 돌려본 기록. 산문이던 측정 장치를 셸 실행형으로 바꾼 뒤 실행 검증 — 4건 중 1건(동시 20건 부하)이 조용히 실패했고 상주 탐침 방식으로 고쳐 20/20 수집
[keycloak-multinode-cluster]
keycloak-multinode-cluster__01-cluster-formed.txt
파드 배치·클러스터 뷰 로그·JGROUPS_PING·OIDC discovery·자원
[session-replication]
session-replication__01-cross-node-session.txt
클러스터 2멤버 확인 → keycloak-0 로그인 → 같은 sid 가 양쪽에서 보임 → keycloak-1 이 refresh 성공(200) → keycloak-1 로그아웃 → keycloak-0 갱신 실패(400) → DB 행 삭제 확인
session-replication__02-cache-delta.txt
로그인 하나를 사이에 둔 양쪽 노드의 캐시 계수기. keycloak-1 은 전부 +0
session-replication__03-cache-ownership.txt
로그인을 반대편에 몰아준 결과. 요청을 받은 노드에서만 엔트리가 는다. 캐시 합 7+5 = DB 12
session-replication__04-read-path-sql.txt
PostgreSQL 문장 로깅으로 잡은 keycloak-1 이 실제로 날린 SQL. SELECT ... FROM OFFLINE_USER_SESSION 로 남의 세션을 읽고 UPDATE ... where VERSION=$5 로 쓴다. 같은 트랜잭션에 SET LOCAL synchronous_commit TO OFF 가 들어 있다
[two-hop-proxy-headers]
two-hop-proxy-headers__01-environment.txt
수정 전 세 계층의 설정 스냅샷
two-hop-proxy-headers__02-measurements.txt
수정 전 측정 · 대조 실험 · 위조 테스트 · 분배
two-hop-proxy-headers__04-after-fix.txt
최종 측정 · 위조 테스트 · 분배
two-hop-proxy-headers__05-networkpolicy.txt
(원본 README 에 설명이 없다 — 파일 머리말 참조)