docs: replace prose placeholders in reproduction steps with executable commands
The audit found ~80 placeholders, and the damaging ones were where the measuring apparatus itself was prose rather than a command: a6 "( curl ... ) & 를 20개 띄우고 wait" — the 22.2s headline came from this a3 "<로그인 반복, sid 를 /tmp/sids 에>" — the whole RPO measurement a3 "<sid 목록>" — the control it is compared against a5 "<수신 파드IP>" — the injection a8 writes /tmp/tok, reads /tmp/rt — self-inconsistent, sent an empty token b3 $KC / $RT / $NEW never assigned c2 bare kcadm.sh with no kubectl exec a1 conntrack tuples written by hand, though the direction flips per restart Each is now a shell-expandable form: pod IPs from jsonpath, the admin password from the secret, ids from kcadm --format csv, conntrack tuples derived from "conntrack -L" with awk rather than transcribed. Then the rewritten commands were executed against the live cluster, and one of them failed — the 20-way load generator, written as "kubectl run --rm -i", lost its output stream twice in a row. That is a trap this series already hit once, and the rewrite reintroduced it. A-6 now uses a resident probe pod that collects into a file and is cat-ed once; verified 20/20 lines. Evidence: docs/evidence/followup/05-command-reproducibility.txt Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f3f3a8da46
commit
74c9b3cea7
@@ -0,0 +1,76 @@
|
||||
재현 절차 명령 실행 검증 — 문서에 적힌 명령을 그대로 돌려본 기록
|
||||
====================================================================
|
||||
수집: 2026-09-04, kc-lab-1 에서 sudo kubectl (호스트 test-server 경유)
|
||||
대상: 감사에서 "산문이라 재현 불가"로 지적된 명령들을 셸 실행형으로 바꾼 뒤,
|
||||
바꾼 형태가 실제로 도는지 확인한 것.
|
||||
|
||||
왜 이 파일이 있나
|
||||
------------------
|
||||
바꾼 명령을 돌려보지 않고 "재현 가능하게 고쳤다"고 쓰면, 감사가 잡아낸 바로
|
||||
그 실수(측정하지 않고 단언)를 반복하는 것이다. 그래서 실행 기록을 남긴다.
|
||||
그리고 실제로 이 검증에서 한 건이 깨졌다 — 아래 [실패] 항목.
|
||||
|
||||
환경
|
||||
----
|
||||
K0 = 10.42.1.142 (keycloak-0, kc-lab-2)
|
||||
K1 = 10.42.0.62 (keycloak-1, kc-lab-1)
|
||||
PW = keycloak-lab-secrets/KC_BOOTSTRAP_ADMIN_PASSWORD, 19자
|
||||
TE = /realms/master/protocol/openid-connect/token
|
||||
|
||||
[통과] 검증 1 — A-3 의 sid 추출 파이프라인
|
||||
-------------------------------------------
|
||||
문서 experiment-a3-database-crash.md 2단계에 넣은 파이프라인
|
||||
(access_token → 2번째 세그먼트 → '==' 패딩 → base64 -d → sid) 을 그대로 실행.
|
||||
|
||||
추출된 sid = YWfXBHn08DNujXvJ6QV1lMAd
|
||||
/tmp/sids 줄수 = 1
|
||||
|
||||
sid 는 UUID 가 아니라 24자 문자열이다. RPO 대조에서 IN 절에 넣을 때
|
||||
따옴표가 필요한 이유가 이것이다.
|
||||
|
||||
[통과] 검증 2 — A-6 단일 요청 지연 (각 15회)
|
||||
---------------------------------------------
|
||||
keycloak-0 평균 46 ms (대조군: PostgreSQL 과 같은 노드)
|
||||
keycloak-1 평균 86 ms (시험군: 노드 간 홉이 하나 더 있다)
|
||||
|
||||
주입 없는 평시 값이다. A-6 본문의 22.2초는 지연 주입 상태의 값이므로
|
||||
이 숫자와 직접 비교하면 안 된다. 여기서 확인한 것은 "명령이 돈다" 뿐이다.
|
||||
|
||||
[실패 → 수정] 검증 3 — 동시 20건 부하
|
||||
--------------------------------------
|
||||
처음에 쓴 형태:
|
||||
kubectl -n keycloak-lab run load --rm -i --restart=Never \
|
||||
--image=curlimages/curl:8.11.1 --quiet --command -- sh -c '... & ... wait'
|
||||
|
||||
결과: 출력이 도착하지 않고 세션이 그대로 끊겼다. 두 번 시도해서 두 번 다.
|
||||
일회성 파드(--rm -i)의 stdout 스트림이 20개 동시 자식 프로세스의 출력을
|
||||
잃는 문제이며, 이 실험 시리즈에서 이미 한 번 겪은 함정이다.
|
||||
내가 재현 절차를 고치면서 그 깨진 패턴을 다시 써넣었다.
|
||||
|
||||
고친 형태 — 상주 탐침 + 파드 안 파일 수집 + 한 번 cat:
|
||||
kubectl run a6-probe ... -- sleep 1800
|
||||
kubectl exec a6-probe -- sh -c '... >> /tmp/load ) & ... wait'
|
||||
kubectl exec a6-probe -- cat /tmp/load > /tmp/load.txt
|
||||
|
||||
결과:
|
||||
exit=0
|
||||
수집된 줄수 = 20 ← 20 이어야 한다. 스트림 방식은 여기서 샜다.
|
||||
상태코드별:
|
||||
20 200
|
||||
최대 지연 = 0.968958 s
|
||||
|
||||
[통과] 검증 4 — 풀 지표
|
||||
------------------------
|
||||
agroal_max_used_count{datasource="default"} 4.0
|
||||
agroal_active_count{datasource="default"} 0.0
|
||||
agroal_awaiting_count{datasource="default"} 0.0
|
||||
agroal_blocking_time_average_milliseconds{datasource="default"} 0.0
|
||||
|
||||
동시 20건에도 max_used 가 4 에 그치고 awaiting 이 0 이다.
|
||||
평시에는 풀이 병목이 아니라는 뜻이며, A-6 이 지연을 주입해야만
|
||||
경합이 나타난다고 적은 것과 일치한다.
|
||||
|
||||
남는 교훈
|
||||
---------
|
||||
"명령을 실행 가능하게 고쳤다"와 "고친 명령이 동작한다"는 다른 주장이다.
|
||||
검증 3 이 그 차이를 보여준다 — 문법적으로는 멀쩡했고, 실행하면 조용히 실패했다.
|
||||
@@ -9,9 +9,11 @@
|
||||
| `02-d2-rollback-same-schema.txt` | **스키마가 안 바뀌면 롤백이 된다** — 26.7.3 → 26.7.0 성공. 다만 전환 순간 `000` 1회(3초 타임아웃) |
|
||||
| `03-b4-role-propagation.txt` | **B-4 ③** IdP 에서 값을 바꿔도 **12회 요청·6초 동안 옛 값**. 세션 삭제 후 재인증에서야 새 값 |
|
||||
| `04-observability-gap.txt` | **B층에 관측이 없다** — Prometheus 는 keycloak·kubelet·node-exporter·prometheus 만 긁는다. Redis·BFF·PostgreSQL 지표가 0개 |
|
||||
| `05-command-reproducibility.txt` | **재현 절차 명령을 실제로 돌려본 기록.** 산문이던 측정 장치를 셸 실행형으로 바꾼 뒤 실행 검증 — 4건 중 1건(동시 20건 부하)이 **조용히 실패**했고 상주 탐침 방식으로 고쳐 20/20 수집 |
|
||||
|
||||
## 핵심 세 줄
|
||||
|
||||
1. **"롤백은 안 된다" 는 조건부였다.** 스키마가 바뀌었으면 안 되고, 안 바뀌었으면 된다 — D-2 의 결론을 정밀화한다.
|
||||
2. **role 변경은 요청 횟수와 무관하게 반영되지 않는다.** `--cookie-refresh` 가 없으면 쿠키 만료나 재인증까지 옛 값이 간다.
|
||||
3. **B층 실험에 Grafana 증거가 없는 이유가 확인됐다** — 관측 대상에 애초에 없다. 스크린샷이 없는 것이 아니라 지표가 없다.
|
||||
3. **바꾼 명령은 돌려봐야 안다.** 문법이 멀쩡해도 일회성 파드는 동시 출력에서 조용히 샜다 — 05 참조.
|
||||
4. **B층 실험에 Grafana 증거가 없는 이유가 확인됐다** — 관측 대상에 애초에 없다. 스크린샷이 없는 것이 아니라 지표가 없다.
|
||||
|
||||
Reference in New Issue
Block a user