Files
document-haness/docs/virtualization/tech-log-studio/network-virtualization/question/question-network-virtualization-cpu-cost-under-load.md
T
DongHyeonkaandClaude Opus 5 2109f726fe feat(pipeline): keycloak-session-store 25편·virtualization 59편을 S3→S5→S6 으로 돌린다
기록 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>
2026-09-17 11:01:55 +09:00

12 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
79ac61d6-cbe6-483b-9961-02ca8c02b5c2 QUESTION network-virtualization-cpu-cost-under-load 부하 중 network 가상화가 지연을 바꿀 만큼 호스트 CPU 를 쓰는가 network-virtualization 네트워크 가상화 virtualization 초안 OPEN https://hyeonworks.com/studio/documents/79ac61d6-cbe6-483b-9961-02ca8c02b5c2/edit no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
final/document.md#122-open-question-oq-7
final/document.md#117-이-구조에서-발생할-수-있는-문제-117-7
final/document.md#107-vhost-net-최적화
final/document.md#111-interrupt-notification-최적화
final/document.md#120-keycloak-refresh-token-실험과의-관계

부하 중 network 가상화가 지연을 바꿀 만큼 호스트 CPU 를 쓰는가

§117.7 은 vhost-net 과 QEMU 스레드와 softirq 도 호스트 CPU 를 쓰므로, 네트워크 문제처럼 보이는 것이 CPU 스케줄링 문제일 수 있다고 적었다. 그 셋 가운데 QEMU 스레드와 게스트 쪽 지표는 CPU 가상화를 다루는 물음 둘이 같은 실험 구간에서 이미 재기로 해 두었다. 그래서 여기서는 Keycloak 부하 시험 구간에서 vhost 커널 스레드와 softirq 가 호스트 CPU 를 얼마나 쓰는지, 그 사용량이 네트워크 지연과 같이 움직이는지만 본다.

관계

  • Guest 의 packet 이 Host Physical NIC 에 닿기까지 — virtio-net · virtqueue · vhost-net · TAP · Bridge vhost-net 이 데이터 경로의 어느 구간을 맡는지를 이 개념이 설명한다. 여기서 재려는 커널 스레드가 그 구간을 돌린다.
  • Keycloak 실험 결과를 애플리케이션 원인으로 읽기 전에 network 계층을 따로 검증한다 §120 이 요구한 별도 검증을 규칙으로 편 기준이다. 이 측정이 없으면 그 검증을 마쳤다고 적을 수 없다.
  • QEMU backend 와 vhost-net 의 차이가 이 호스트에서 실제로 보이는가 백엔드를 바꿔 견주는 물음이라 §122 가 든 관찰 대상을 상당 부분 함께 쓴다. 여기서 찍은 기준값을 그쪽이 그대로 받는다.
  • 이 가상 머신들의 virtio-net 에 multi-queue 가 켜져 있는가 큐가 하나로 나오면 §117.5 가 든 쏠림이 이 측정의 vCPU 별 사용량에서 드러난다.
  • Keycloak 동시 refresh 실험 중 CPU 가상화 계층이 결과를 흔들 만큼 포화되는가 Guest steal time 과 QEMU vCPU 스레드는 그쪽이 잰다. 같은 실험 구간에서 두 기록을 함께 남기고 여기서는 vhost 커널 스레드와 softirq 만 새로 잰다.

사실

  • §117.7 은 vhost-net · QEMU thread · softirq 도 호스트 CPU 를 쓰고, 따라서 네트워크 문제처럼 보여도 CPU 스케줄링 문제일 수 있다고 적었다.
  • §107 은 QEMU 사용자 공간이 패킷마다 I/O 를 처리하면 호스트 커널과 사용자 공간을 오가는 전환 비용이 쌓인다고 밝혔다. 초당 지나는 패킷이 많아질수록 userspace/kernel transition · scheduling · copy · notification 비용이 커질 수 있다.
  • §111 은 게스트와 호스트가 큐에 새 패킷이나 버퍼가 있음을 서로 알려야 한다고 적었다. 패킷마다 인터럽트나 알림이 지나치게 많이 발생하면 오버헤드가 커지므로 batching · interrupt moderation · queueing 이 중요하다고 밝혔다.
  • §120 은 Refresh Token 경쟁 자체가 virtio-net 문제는 아니지만 클라이언트부터 PostgreSQL/Redis 까지 같은 경로를 공유하므로 네트워크 경로를 별도로 검증한다고 적었다.
  • §120 이 Refresh Token 경쟁이나 DB lock 으로 오해할 수 있다고 든 다섯 Node1 요청만 지연 VM2 packet loss Host bridge misconfiguration NAT/conntrack issue Host CPU contention으로 vhost 처리 지연
  • §122 OQ-7 이 든 관찰 대상 여섯 QEMU CPU vhost thread softirq Host CPU Guest CPU network latency
  • 이 여섯 가운데 QEMU CPU 와 Guest CPU 는 CPU 가상화 쪽 물음이 같은 실험 구간에서 이미 잰다. §14.7 이 호스트 스레드를 보는 명령으로 적은 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 는 이름이 qemu 인 스레드만 걸러 내므로 vhost 커널 스레드는 그 출력에 나오지 않는다.
  • softirq 시간을 읽는 명령이 근거 문서에 없다. §118 의 네트워크 확인 명령 목록에도, CPU 관측 명령을 모아 둔 §14 에도 softirq 항목이 없고 이 낱말은 §117.7 과 §122 OQ-7 두 곳에만 나온다.
  • §108 은 vhost-net 을 써도 QEMU 가 VM lifecycle · virtio device 생성 · feature negotiation · queue configuration · backend 연결 · device reset 을 계속 맡는다고 적었다.
  • §179 는 nginx 를 물리 호스트에서 엣지 게스트로 옮기고 호스트에는 커널 DNAT 만 두었다고 관측으로 적었다. 지금 호스트에는 :443 을 듣는 리스너가 없다.
  • §197 과 §218 은 이 호스트의 논리 코어가 8 이고 게스트 셋에 vCPU 2 · 2 · 1 을 배분했다고 적었다. 부하 구간의 호스트 CPU 사용량은 이 수와 나란히 읽는다.
  • §192 가 적은 스크레이프 대상은 keycloak · kubelet · node-exporter · prometheus 넷이고 node-exporter 는 게스트 노드마다 하나씩 붙는다. §193 은 이 실험대가 호스트 쪽 지표를 긁지 않는다고 적었다.
  • 이 호스트에서 부하 구간의 vhost 스레드 CPU 사용량이나 softirq 시간을 잰 기록이 없다.

가정

  • Keycloak 부하 시험을 돌릴 수 있고, 부하 구간과 그 직전 구간을 나눠 기록할 수 있다고 본다.
  • 호스트에서 vhost 커널 스레드를 스레드 단위로 구분해 볼 수 있다고 전제한다. §108 이 vhost-net 을 써도 QEMU 가 설정과 수명 주기를 계속 맡는다고 적었으므로, QEMU 프로세스의 CPU 사용량과 vhost 커널 스레드의 CPU 사용량을 따로 세야 한다.
  • 부하 도구가 네트워크 지연을 이미 내고 있다고 전제한다. 그 도구가 어떤 값을 어떤 주기로 내는지는 근거 문서에 적혀 있지 않다.
  • 호스트와 게스트 둘의 시각을 맞춰 읽을 수 있다. 시계가 어긋나면 세 값을 같은 부하 구간에 겹쳐 놓지 못한다.
  • 엣지 게스트의 nginx 가 쓰는 CPU 는 그 게스트를 돌리는 QEMU 프로세스 쪽에 나타난다고 본다. §179 가 nginx 를 게스트로 옮긴 뒤로 호스트에는 그 프로세스가 없으므로, 부하 구간의 호스트 CPU 상승을 전부 네트워크 가상화 몫으로 읽으면 이 전제가 깨진다.

미지수

  • 부하를 걸기 전 vhost 커널 스레드의 CPU 사용량과 softirq 시간.
  • 부하 구간에서 그 둘이 얼마나 오르는지.
  • 오른 몫이 QEMU vCPU 스레드 사용량과 어떻게 나뉘는지. 게스트가 셋이라 엣지 게스트를 돌리는 QEMU 프로세스의 몫도 k3s 노드 두 대와 갈라 세야 한다.
  • vhost 커널 스레드와 softirq 의 움직임이 네트워크 지연과 같은 시간축에서 함께 움직이는지.
  • 두 지표가 얼마나 움직여야 실험 결과를 다르게 읽어야 하는지. 그 문턱을 아직 정하지 않았다.
  • softirq 시간을 이 환경에서 어떤 도구로 읽는지. 근거 문서가 명령을 적지 않아 실행하는 쪽이 정한다.

제약

  • 실험 조건을 바꾸지 않고 관찰만 덧붙인다. CPU 가상화 쪽 물음이 같은 실험 구간을 쓰기로 되어 있어 부하 수준을 바꾸면 두 기록을 겹쳐 읽지 못한다.
  • 기준값을 먼저 찍는다. 부하 구간의 값만 있으면 그것이 평소 값인지 부하 때문에 오른 값인지 판정할 수 없다.
  • 이 물음이 새로 만드는 값은 vhost 커널 스레드 사용량과 softirq 시간 둘이다. QEMU CPU 와 Guest CPU 와 steal time 은 CPU 가상화 쪽 기록을 그대로 쓰고, 네트워크 지연은 부하 도구가 낸 값을 쓴다.
  • 호스트 쪽 값은 손으로 읽어 남긴다. §192 의 관측 스택은 게스트 안에서 돌고 §193 이 적은 대로 호스트 지표를 긁지 않는다. §193 은 node-exporter 가 게스트 커널이 내놓는 값을 읽으므로 그 값이 전부 게스트가 본 것이고 호스트에서 같은 것을 재면 다른 수가 나올 수 있다고 추론으로 덧붙였다.
  • 두 지표가 움직이지 않았다는 결과가 나와도 Refresh Token 실험의 결론이 바뀌지는 않는다. §120 이 Refresh Token 경쟁과 네트워크 가상화를 별개 문제로 놓았기 때문에, 여기서 갈리는 것은 그 실험 결과를 애플리케이션과 저장소 쪽으로 읽어도 되는지 하나다.
  • 스레드가 어느 논리 CPU 에서 돌았는지는 §14.7 의 psr 로 읽히지만, 그 번호가 어느 물리 코어인지는 SSOT 에서 나오지 않는다. §197 이 남긴 lscpu 출력이 grep 으로 걸러져 Model name 과 CPU(s), Thread(s) per core, Core(s) per socket 네 줄뿐이기 때문이다. vhost 스레드를 어느 CPU 에 둘지를 나중에 정하려면 그 배치를 호스트에서 다시 읽어야 한다.
  • 이 호스트에서 잰 값이 없어 다른 장비의 수치를 근거로 삼지 않는다.

선택지

1. 실험을 그대로 두고 vhost 스레드와 softirq 만 덧붙여 잰다

CPU 가상화 쪽 물음이 이미 같은 구간에서 Guest steal time 과 QEMU vCPU 스레드를 기록하므로, 여기서는 그 기록에 없는 둘을 같은 시각에 붙인다. 실험 조건을 건드리지 않아서 두 기록을 겹쳐 읽을 수 있다.

이 방법으로는 이번 부하 수준에서 두 지표가 움직였는지 하나만 알 수 있다.

2. 부하 직전 구간을 기준값으로 따로 찍는다

부하를 걸기 전에 §122 OQ-7 의 여섯을 한 번 찍어 두면 부하 구간의 값을 견줄 대상이 생긴다. 기준값 없이 부하 구간만 찍으면 vhost 스레드 사용량이 어떤 값으로 나오든 그것이 평소 값인지 부하 때문에 오른 값인지 판정하지 못한다.

3. network latency 를 같은 시간축에 올려 함께 본다

vhost 스레드와 softirq 가 올라도 지연이 그대로면 이 부하 수준에서는 지연을 바꾸지 않았다고 적을 수 있다. §122 OQ-7 이 network latency 를 여섯째 관찰 대상으로 둔 이유가 여기에 있다. 대신 호스트와 부하 도구의 시각을 맞춰야 세 값을 겹쳐 놓을 수 있다.

4. 제외 — 초당 패킷 수를 올려 vhost 처리를 포화시켜 견준다

§107 은 초당 지나는 패킷이 많아질수록 전환과 복사와 알림 비용이 커질 수 있다고 적었으므로, 그 수를 올리면 vhost 처리 비용이 더 잘 드러난다. 그러나 이 물음은 Keycloak 부하 시험 구간에서 네트워크 가상화가 결과를 흔들었는지를 묻는 것이라, 부하를 다르게 걸고 잰 값은 그 답이 되지 않는다. 포화 구간과 견주는 측정은 별도 부하 Case 로 뺀다.

다음 검증

  1. 부하를 걸기 전 §122 OQ-7 이 든 여섯을 한 번 찍어 기준값으로 둔다.
  2. Keycloak 부하 시험을 돌리면서 같은 여섯을 같은 시각에 기록한다. 호스트에서는 QEMU 프로세스와 vhost 커널 스레드의 CPU 사용량을 스레드 단위로, softirq 시간을, 호스트 전체 CPU 를 적는다.
  3. 각 게스트의 CPU 사용량과 부하 도구가 낸 네트워크 지연을 같은 구간에서 적는다.
  4. vhost 커널 스레드와 softirq 를 읽는 데 쓴 명령을 함께 남긴다. §14.7 의 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 는 qemu 로 걸러 내 vhost 커널 스레드를 내지 않고, softirq 를 읽는 명령은 근거 문서에 없다.
  5. Guest steal time 과 QEMU vCPU 스레드 쪽은 「Keycloak 동시 refresh 실험 중 CPU 가상화 계층이 결과를 흔들 만큼 포화되는가」가 같은 구간에서 재므로, 두 기록을 한 실험에서 함께 남긴다.

닫는 조건 : 부하 구간의 vhost 커널 스레드 사용량과 softirq 시간이 기준값과 다르지 않고 네트워크 지연도 움직이지 않으면, 이 부하 수준에서는 네트워크 가상화가 지연에 영향을 줄 만큼 호스트 CPU 를 쓰지 않는다고 적고 닫는다. 셋 중 하나라도 움직이면 그 부하 전후 표가 Case 가 되고, vhost 스레드를 어느 CPU 에 둘지나 multi-queue 를 켤지는 그 Case 뒤에 Decision 으로 넘긴다. 어느 쪽이든 이 결과가 없으면 §120 이 경고한 오귀속, 곧 네트워크 지연을 Refresh Token 경쟁으로 읽는 것을 배제했다고 적을 근거가 없다.