Experiment 0 with three probes: cross-node refresh/logout, cache counter deltas around a single login, and cache entry ownership. Each node caches only what it handled; cache totals sum exactly to the database count. 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 세션 /'
|