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>
56 lines
2.5 KiB
Bash
Executable File
56 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Experiment 0c — where does a session entry actually live?
|
|
#
|
|
# Experiment 0b showed keycloak-1's session cache never moved when keycloak-0
|
|
# handled a login. That leaves two explanations:
|
|
#
|
|
# (a) a DISTRIBUTED cache with owners=1 — entries are spread across nodes by
|
|
# consistent hashing, and this one happened to land on keycloak-0;
|
|
# (b) a LOCAL cache — each node only ever caches what it handled itself.
|
|
#
|
|
# They are distinguished by driving logins at the OTHER node. Under (a) the
|
|
# entries would keep landing on both nodes regardless of who was asked. Under
|
|
# (b) the count rises only on the node that received the request.
|
|
set -uo pipefail
|
|
|
|
NS="${NS:-keycloak-lab}"
|
|
N="${N:-5}"
|
|
K0_IP=$(kubectl -n "$NS" get pod keycloak-0 -o jsonpath='{.status.podIP}')
|
|
K1_IP=$(kubectl -n "$NS" get pod keycloak-1 -o jsonpath='{.status.podIP}')
|
|
ADMIN_PW=$(kubectl -n "$NS" get secret keycloak-lab-secrets \
|
|
-o jsonpath='{.data.KC_BOOTSTRAP_ADMIN_PASSWORD}' | base64 -d)
|
|
|
|
echo "수집 시각: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
|
echo " keycloak-0 = $K0_IP ($(kubectl -n "$NS" get pod keycloak-0 -o jsonpath='{.spec.nodeName}'))"
|
|
echo " keycloak-1 = $K1_IP ($(kubectl -n "$NS" get pod keycloak-1 -o jsonpath='{.spec.nodeName}'))"
|
|
echo
|
|
|
|
kubectl -n "$NS" run kc-own --rm -i --restart=Never \
|
|
--image=curlimages/curl:8.11.1 --quiet --command -- sh -c "
|
|
O=/tmp/o; : > \$O
|
|
ent() {
|
|
curl -s --retry 3 --max-time 20 http://\$1:9000/metrics \
|
|
| grep -E '^vendor_statistics_approximate_entries_unique.cache=.sessions' \
|
|
| awk '{print \$NF}'
|
|
}
|
|
login() { i=0; while [ \$i -lt $N ]; do
|
|
curl -s -o /dev/null -X POST http://\$1:8080/realms/master/protocol/openid-connect/token \
|
|
-d grant_type=password -d client_id=admin-cli \
|
|
-d username=admin -d 'password=$ADMIN_PW'
|
|
i=\$((i+1)); done; sleep 5; }
|
|
{
|
|
printf '%-32s %12s %12s\n' '단계' 'k0 entries' 'k1 entries'
|
|
printf '%-32s %12s %12s\n' '시작' \"\$(ent $K0_IP)\" \"\$(ent $K1_IP)\"
|
|
login $K1_IP
|
|
printf '%-32s %12s %12s\n' 'keycloak-1 에 로그인 ${N}회' \"\$(ent $K0_IP)\" \"\$(ent $K1_IP)\"
|
|
login $K0_IP
|
|
printf '%-32s %12s %12s\n' 'keycloak-0 에 로그인 ${N}회' \"\$(ent $K0_IP)\" \"\$(ent $K1_IP)\"
|
|
} >> \$O
|
|
cat \$O
|
|
" 2>&1 | grep -v '^pod .* deleted$'
|
|
|
|
echo
|
|
echo "=== 대조: PostgreSQL 에는 몇 건인가 ==="
|
|
kubectl -n "$NS" exec deploy/postgres -- psql -U keycloak -d keycloak -tAc \
|
|
"select count(*) from offline_user_session where offline_flag='0'" 2>/dev/null | sed 's/^/ online 세션 /'
|