기록 84편을 계약 에이전트로 다시 썼다. 기존 71편(kss 25 · virt 46)과, 계약에만 있고 안 쓰여 있던 새 글감 13편이다. 원장 84개를 열어 단계마다 스킬 영수증과 관문 종료 코드를 적었고 verify-pipeline-run.py 가 error 0 으로 닫는다. SSOT 결함 둘을 고쳤다. - kss 의 `약 58일` 이 반입 중 `약 59일` 로 바뀌어 있었다. 원 증거 파일이 「남은 일수: 88일 … 실제 갱신까지 약 58일」로 산수를 직접 적는다. D-4a 쪽 `약 59일` 은 강제 갱신 뒤(`VALID: 89 days`)라 맞는 값이라 그대로 뒀다. - virt §198 의 `11.6GB` 는 §178 의 원 측정 `Mem: 11648`(MiB)과 어긋나는데 원 가이드의 표기 그대로라 고치지 않고 쓰이는 자리에 대조를 적었다. 기록의 수치 오류 셋을 고쳤다 — CASE 요약의 「게스트 셋에 8240MB」(5120+3120 은 둘이다), k3s 편이 같은 것을 여섯·일곱·여덟로 세던 것, no-docker 편의 「셋을 더 든다」(§281 의 표는 네 행이고 디스크 행이 빠져 있었다). 계약을 셋 고쳤다. - kss 의 sourceRepository 리비전이 cdac9b8 이었는데 그 커밋에는 docs/guides/** 28개가 아예 없다. 9465582b 로 바꾸고, 반입한 바이트가 어느 커밋과도 같지 않다는 것을 측정값과 함께 적었다 — 반입은 커밋이 아니라 그 시점의 작업 트리에서 떠 온 것이다(kss 297/306 · virt 12/14 가 작업 트리와 같고, 200 커밋을 거슬러 전수 대조했을 때 가장 가까운 커밋도 28개가 어긋났다). - virt 계약이 「2026-09-11 재배분」이라고 적는데 SSOT 는 재배분 날짜를 적지 않고 재배분 뒤 값은 이미 2026-09-10 측정에 찍혀 있다. - kss 후보 대장이 지나친 절 아홉에 처분을 적었다(warn 9 → 0). 새 글감은 0건이고 넷은 앵커가 h3 슬러그의 접두가 아니라 중간 토막이라 검사기가 못 본 것이었다. style_profile.mjs 의 결함 둘을 고쳤다 — frontmatter 가 문장으로 세어져 (실측 398자짜리 「문장」 하나) 평균 길이를 기준 안으로 밀어 올리고 있었고, engPerSent 의 분자는 목록을 포함한 글에서, 분모는 목록을 걷어낸 글에서 세고 있었다(Question 기록에서 11.94 → 3.86). verify-pipeline.py 전 항목 PASS · error 0 · unittest 334건 OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7.8 KiB
id, kind, slug, title, topic, topicName, project, status, questionStatus, studio, sourceRevision, source
| id | kind | slug | title | topic | topicName | project | status | questionStatus | studio | sourceRevision | source | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 116b806c-b176-401c-9363-1489fffb721c | QUESTION | throttling-vs-contention | cgroup CPU 제한과 호스트 vCPU 경쟁을 지표로 가를 수 있는가 | cpu-virtualization | CPU 가상화 | virtualization | 초안 | OPEN | https://hyeonworks.com/studio/documents/116b806c-b176-401c-9363-1489fffb721c/edit | no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다 |
|
cgroup CPU 제한과 호스트 vCPU 경쟁을 지표로 가를 수 있는가
이 호스트에서 throttled time 도 steal time 도 잰 값이 없다. 가상 머신 안에서 K3s 를 돌리는 구성이라, 파드가 자기 CPU 상한에 막힌 것과 호스트 CPU 를 제때 못 받은 것이 같은 애플리케이션 지연으로 보일 수 있다. §25 가 두 원인에 갈라 적은 확인 항목이 실제로 갈리는지는 두 원인을 각각 재현해야 안다.
관계
- KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지 호스트 CPU 경쟁이 게스트 안에서 어떤 값으로 드러나는지를 이 개념이 설명한다.
- Keycloak 동시 refresh 실험 중 CPU 가상화 계층이 결과를 흔들 만큼 포화되는가 그쪽에서 가상화 계층 지표가 움직인다는 답이 나오면, 그 움직임을 cgroup 쪽 제한과 가를 수 있는지는 이 질문이 받는다.
사실
- 가상 머신 안에서 K3s 를 돌리면 물리 CPU 와 Keycloak 파드 사이에 호스트·하이퍼바이저, 게스트 Linux, K3s, cgroup CPU limit 이 차례로 놓인다.
- 호스트 CPU 에 여유가 있어도 Keycloak 파드는 설정된 CPU 상한 때문에 실행이 제한될 수 있다.
- 호스트 CPU 를 받지 못해 생긴 문제와 파드가 자신의 CPU 상한을 넘겨 생긴 문제는 서로 다른 계층에 있다. 앞의 것은 경쟁과 steal time, 스케줄링 쪽이고 뒤의 것은 cgroup 제한 쪽이다.
- cgroup 제한 자체는 KVM 문제가 아니다. 그래도 가상 머신 안에서 K3s 를 운영하는 지금 실험에서는 두 원인이 같은 애플리케이션 지연으로 관찰될 수 있어 진단 경계에 넣었다. 개념 문서가 다루기로 한 범위는 CPU 가상화 하나인데, cgroup 제한은 그 범위 밖에서 진단 경계 안으로 들여온 항목이다.
- 계층별 진단표가 적은 우선 확인 항목은 이렇게 갈린다. CPU throttling : CPU limit · throttled time CPU contention : 호스트 CPU · 실행 대기열 · CPU 별 사용률
- 같은 표가 두 원인의 대표적인 현상도 갈라 적었다. cgroup 쪽은 파드가 CPU 를 더 쓰려 해도 상한에 막힌 것이고, 경쟁 쪽은 실행 가능한 작업이 늘면서 지연이 늘어난 것이다. 갈라 적힌 현상은 각 계층에서 보이는 모습이라, 애플리케이션 지연만 보고 있으면 그 구분이 드러나지 않는다.
- 그 표는 지표 하나로 원인을 확정하려고 만든 것이 아니라 어느 계층부터 조사할지 범위를 줄인다.
- §197 은 2026-09-10 에 이 호스트의 논리 코어를 8 로, 실험대가 잡은 vCPU 를 2 + 2 + 1 = 5 로 적었다. §218 은 kc-lab-1 과 kc-lab-2 에 각각 vCPU 2 를 적었다.
- 이 호스트에서 throttled time 도 steal time 도 잰 값이 없다.
가정
- 같은 크기의 Keycloak 지연 증가를 두 원인으로 각각 만들어 낼 수 있다고 보고 비교를 짠다. 두 재현이 실제로 같은 크기가 되는지는 해 보기 전에 알 수 없다.
- 다른 가상 머신에 CPU 부하를 걸면 호스트 쪽 경쟁이 생긴다고 본다. 이 호스트에서 두 가상 머신 동시 부하가 경쟁을 만드는지는 아직 관측하지 않았다.
- Keycloak 파드의 cgroup CPU limit 은 실험을 위해 낮췄다가 되돌릴 수 있다고 본다.
- 두 재현 사이에 다른 조건이 바뀌지 않는다는 것을 전제로 두 실행을 견준다.
미지수
- 두 원인을 각각 재현했을 때 throttled time · CPU limit · 게스트 CPU 와 %st, 호스트 CPU 와 실행 대기열이 서로 다른 조합으로 움직이는지.
- 갈린다면 어느 항목이 가장 먼저 갈리는지.
- 지금 Keycloak 파드에 CPU limit 이 걸려 있는지, 걸려 있다면 얼마인지. 개념 문서에 적혀 있지 않다.
- throttled time 을 이 환경에서 어떤 경로로 읽는지. 개념 문서는 확인 항목으로만 적고 실제로 읽는 명령을 적지 않았다.
- 두 원인이 동시에 걸린 구간에서도 지표가 갈리는지. 이번 검증은 하나씩 만든 두 실행만 견준다.
제약
- 두 재현이 비슷한 크기의 지연 증가를 만들어야 지표 조합을 견줄 수 있다.
- 지표 하나로 원인을 확정하지 않는다. 게스트 · 호스트 · K3s 세 쪽을 같은 시각에 받아 적는다.
- refresh 경쟁 실험은 CPU 자원을 여유 있게 둔 상태에서 먼저 돌리므로 이 재현은 그 실험과 같은 시간에 걸지 않는다.
- 두 게스트의 vCPU 합 4 가 논리 코어 8 보다 적어서, 부하 쪽 재현이 경쟁을 만들려면 호스트 쪽 작업까지 같은 코어를 써야 한다. 부하를 걸었는데 경쟁이 나오지 않는 것도 이 재현의 결과로 받는다.
선택지
1. 두 원인을 따로 재현해 지표 조합을 나란히 놓는다
Keycloak 파드의 cgroup CPU limit 을 낮춰 한 번, 다른 가상 머신에 CPU 부하를 걸어 한 번, 같은 크기의 지연을 두 번 만든다. 두 실행에서 게스트 · 호스트 · K3s 쪽 항목을 같은 이름으로 받아 적으면 어느 항목이 두 재현에서 다르게 움직이는지 그대로 보인다.
셋 가운데 손이 가장 많이 간다. 부하 쪽 재현은 다른 가상 머신을 함께 써야 하고, cgroup 쪽 재현은 파드 설정을 바꿨다가 되돌려야 한다.
2. 호스트 쪽 항목부터 보고 범위를 줄인다
호스트 CPU 와 실행 대기열, CPU 별 사용률을 먼저 본다. 호스트에 여유가 있는데 파드만 느리면 조사 범위가 cgroup 쪽으로 줄어든다.
호스트가 포화된 것으로 나오면 거기서 끝나지 않는다. 그 구간에 파드의 상한도 함께 걸려 있었는지는 이 순서로 가려낼 수 없어서, 결국 첫 번째 선택지의 두 재현으로 돌아간다.
3. throttled time 하나로 가른다 — 제외
throttled time 이 0 이 아니면 cgroup 제한, 0 이면 호스트 경쟁으로 읽는 방법이다. 진단표는 두 행에 각각 두 항목 이상을 적어 두었다. 지표 하나로 원인을 확정하지 않기로 하고 만든 표이므로 이 순서는 쓰지 않는다.
다음 검증
- 부하를 걸기 전에 파드의 throttled time 과 CPU limit, 게스트 CPU 와 게스트에서 top 으로 본 %st, 호스트 CPU 와 실행 대기열을 한 번 찍어 기준값으로 둔다.
- Keycloak 파드의 cgroup CPU limit 을 낮춰 Keycloak 지연을 올리고 같은 다섯 항목을 같은 시각에 받아 적는다.
- limit 을 되돌린 뒤, 이번에는 다른 가상 머신에 CPU 부하를 걸어 비슷한 크기의 지연을 만들고 같은 다섯 항목을 다시 받아 적는다.
- 두 실행의 기록을 기준값과 함께 한 표에 나란히 놓는다.
닫는 조건 : 두 재현에서 지표 조합이 갈리면 그 대조표가 Case 가 되고, 진단표의 두 행을 어떤 순서로 보는지 정하는 근거가 된다. 갈리지 않으면 「이 지표들로는 두 원인이 구분되지 않는다」를 적고, 무엇을 더 봐야 하는지를 새 Question 으로 낸 뒤 이 질문은 닫는다.