Files
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

10 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
397c4789-0272-449b-86d6-2c4a3a122401 QUESTION tap-interface-to-vm-mapping VM1 과 VM2 의 TAP/vnet interface 는 무엇이고 어디에 붙어 있는가 network-virtualization 네트워크 가상화 virtualization 초안 OPEN https://hyeonworks.com/studio/documents/397c4789-0272-449b-86d6-2c4a3a122401/edit no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
final/document.md#122-open-question-oq-2
final/document.md#99-tap의-역할
final/document.md#117-이-구조에서-발생할-수-있는-문제-117-1
final/document.md#118-실제-linux에서-확인할-명령어

VM1 과 VM2 의 TAP/vnet interface 는 무엇이고 어디에 붙어 있는가

§99 는 TAP 을 가상 머신의 이더넷 프레임과 호스트 리눅스 네트워크를 잇는 접점으로 놓았다. 그 접점의 이름은 호스트마다 다르게 붙는데, 이 호스트의 두 가상 머신에 무엇이 붙었는지는 SSOT 에 없다. 이름을 모르면 §119 의 계층별 tcpdump 가 대상을 채우지 못하고, §117.1 이 든 「특정 VM 만 통신 불가」도 어느 가상 머신인지 가릴 수 없다. 이 물음은 두 가상 머신의 호스트 쪽 인터페이스 이름과 붙어 있는 곳을 확정한다.

관계

  • Guest 의 packet 이 Host Physical NIC 에 닿기까지 — virtio-net · virtqueue · vhost-net · TAP · Bridge 그 경로에서 TAP 이 무엇을 하는지 이미 설명해 두었으므로 이 물음은 거기서 이어진다.
  • packet 이 어디서 끊겼는지는 계층마다 capture 해서 가른다 그 기준이 요구하는 캡처 지점의 이름을 이 물음이 댄다.
  • 이 호스트의 가상 머신 네트워크는 Bridge 인가 NAT 인가 Routing 인가 ip link 와 bridge link 를 두 물음이 같이 쓰므로 한 번 찍어 둘을 함께 읽는다.
  • Host Nginx 에서 Keycloak 까지 packet 은 실제로 어디를 지나는가 tcpdump 를 어느 인터페이스에 걸지가 이 물음의 답에서 나온다.

사실

  • §99 는 TAP 을 호스트 리눅스 커널이 제공하는 가상 이더넷 네트워크 인터페이스로 적었다. 물리 장치가 아니고, 이름의 예로 tap0 과 vnet0 을 들었다.
  • §99 가 적은 TAP 의 역할은 가상 머신의 이더넷 프레임과 호스트 리눅스 네트워크를 연결하는 접점이다. 수신 : Linux Bridge → TAP → VM 송신 : VM → TAP → Linux Bridge
  • §99 는 확인 명령으로 ip link · ip tuntap show · bridge link · virsh domiflist 넷을 들었고, §118 이 같은 명령을 계층별 목록으로 다시 적었다. TAP/vnet : ip link · ip tuntap show libvirt VM NIC : virsh domiflist 에 domain 이름을 넣는다 Linux Bridge : ip link show type bridge · bridge link · bridge fdb show
  • §122 OQ-2 는 이 호스트에서 돌릴 명령을 네 줄로 적었다. virsh domiflist vm1 virsh domiflist vm2 ip link bridge link
  • §99 와 §118 이 TAP 확인 명령으로 든 ip tuntap show 는 OQ-2 의 네 줄에 없다.
  • §117.1 은 TAP/Bridge 연결 오류의 증상 셋을 들었다. VM 외부 통신 불가 Host ↔ VM 통신 불가 특정 VM 만 통신 불가
  • §117.1 이 그 증상에서 확인하라고 든 명령은 ip link · bridge link · bridge fdb show · virsh domiflist 다.
  • §116 은 이 테스트 환경의 경로를 펼치면서 TAP 칸을 TAP(vm1) 과 TAP(vm2) 로 적었다. 호스트에서 읽은 이름은 그 그림에도 없다.
  • §178 은 이 실험대의 게스트를 Debian 12 genericcloud 3대로 적었다. 엣지 1대와 k3s 2노드이고, §122 OQ-2 가 vm1 과 vm2 로 적은 두 대가 그중 k3s 노드 쪽이다.
  • §202 는 2026-09-10 에 돌린 철거 명령의 출력을 그대로 남겼고, 거기서 libvirt domain 이름이 kc-lab-edge · kc-lab-1 · kc-lab-2 로 확인된다. 한 대분 출력의 첫 줄은 Domain 'kc-lab-edge' destroyed 다.
  • §201 과 §247 이 적은 세 게스트의 MAC 주소와 IP 주소 kc-lab-edge : 52:54:00:aa:bb:10 · 192.168.122.10 kc-lab-1 : 52:54:00:aa:bb:11 · 192.168.122.11 kc-lab-2 : 52:54:00:aa:bb:12 · 192.168.122.12
  • §247 은 52:54:00 이 QEMU/KVM 에 할당된 OUI(제조사 식별 접두사)라고 적고, 예약의 mac 과 VM 을 만들 때 준 mac 이 정확히 같아야 한다고 밝혔다. 다르면 예약이 조용히 무시되고 게스트가 동적 범위에서 아무 주소나 받는다.
  • §201 은 예약과 리스를 다른 것으로 갈라 적었다. virsh net-dumpxml 의 예약은 줄 의도이고 virsh net-dhcp-leases 는 실제로 준 기록이라 둘이 다를 수 있다. 실제로 준 기록에는 52:54:00:aa:bb:11 이 192.168.122.11/24 을, 52:54:00:aa:bb:12 가 192.168.122.12/24 을 각각 kc-lab-1 과 kc-lab-2 이름으로 받은 줄이 남아 있다.
  • §178 과 §245 는 게스트가 libvirt 의 default 네트워크에 붙는다고 적었다. §245 는 VM 이 한 대라도 뜨면 그 VM 의 vnetN 인터페이스가 virbr0 에 붙으면서 브리지가 UP 으로 바뀐다고 덧붙였다.
  • §201 은 VM 세 대가 돌 때 virbr0 이 UP 이고 전부 철거한 뒤에는 DOWN 이라는 출력을 남겼다. 상태가 갈린 이유를 브리지에 붙은 tap 인터페이스가 하나도 없어서라고 적었다.
  • 호스트 쪽 인터페이스의 이름은 SSOT 에 없다. virsh domiflist 를 돌린 출력도 ip link 출력도 없다.

가정

  • 호스트에 붙어 virsh 와 ip 계열 명령을 실행할 수 있다고 본다.
  • §122 OQ-2 는 명령에 vm1 과 vm2 를 적었지만 §202 의 철거 출력에 찍힌 domain 이름은 kc-lab-1 과 kc-lab-2 다. 그래서 명령에 넣을 이름은 뒤쪽을 쓴다. §99 와 §118 은 같은 명령에 넣을 domain 을 비워 두었다.
  • virsh domiflist 출력에 인터페이스 이름과 MAC 주소가 함께 나온다고 전제한다. §99 도 §118 도 이 명령의 출력 형식은 적지 않았다.
  • 두 가상 머신이 켜져 있는 동안 읽는다고 전제한다. 꺼진 가상 머신의 TAP 이 호스트에 남아 있는지는 SSOT 에 적혀 있지 않다.

미지수

  • kc-lab-1 과 kc-lab-2 의 호스트 쪽 인터페이스 이름이 각각 무엇인지. 엣지 게스트 kc-lab-edge 의 것도 같이 모른다.
  • 각 인터페이스의 NIC model 이 무엇인지. MAC 주소는 §247 의 예약이 대지만 virsh domiflist 가 같은 값을 내는지는 대조해야 갈린다.
  • 세 인터페이스가 모두 virbr0 에 붙어 있는지. §245 는 default 네트워크의 VM 들이 이 브리지에 연결된다고 적었고, bridge link 로 포트 목록을 읽은 출력은 없다.
  • ip tuntap show 에 나오는 TAP 목록과 virsh domiflist 가 대는 이름이 그대로 맞아떨어지는지.

제약

  • 이름과 어디에 붙어 있는지를 적는 데서 끊는다. 그 경로로 패킷이 실제로 흘렀는지는 tcpdump 를 쓰는 물음이 받는다.
  • 두 가상 머신을 같은 시점에 읽는다. 한쪽을 재시작한 뒤 다른 쪽을 읽으면 이름이 바뀌어도 알 수 없기 때문이다.
  • 이 호스트에서 읽은 출력이 없어 tap0 이나 vnet0 같은 §99 의 예시 이름을 이 호스트의 값으로 쓰지 않는다.
  • SSOT 가 마지막으로 적은 게스트 상태는 §202 의 철거다. 그 뒤에 다시 세웠는지는 적혀 있지 않으므로 세 게스트가 떠 있는 상태에서 읽는다. 철거된 상태로 읽으면 볼 것이 없다 — §201 은 세 대를 전부 철거한 뒤 virbr0 이 DOWN 인 이유를 브리지에 붙은 tap 인터페이스가 하나도 없어서라고 적었다.

선택지

1. libvirt 가 대는 이름을 먼저 받아 호스트에서 대조한다

virsh domiflist 로 가상 머신마다 붙은 인터페이스를 받고, 그 이름이 ip link 목록에 실재하는지 확인한 뒤 bridge link 로 어느 브리지의 포트인지 잡는다. §122 OQ-2 가 적은 네 줄이 이 순서다. 가상 머신과 인터페이스의 짝이 처음부터 정해져 나오므로 두 대의 것을 헷갈리지 않는다.

libvirt 가 모르는 인터페이스는 이 순서에서 빠진다.

2. 호스트의 인터페이스를 전부 세우고 가상 머신으로 되짚는다

ip link 와 ip tuntap show 로 호스트에 있는 TAP 을 모두 적고, bridge link 로 어느 브리지에 붙었는지 잡는다. 그다음 virsh domiflist 로 각각이 어느 가상 머신의 것인지 되짚는다. libvirt 밖에서 만들어진 TAP 이 있어도 목록에 남는다.

가상 머신이 두 대뿐인데 호스트에 TAP 이 여럿이면 짝짓는 데 MAC 주소를 다시 대조해야 한다.

3. 통신이 안 될 때 §117.1 의 확인 목록으로 함께 본다 — 제외

§117.1 이 증상과 확인 명령을 이미 묶어 두었으니 장애가 났을 때 같이 보자는 방법이다. 지금 필요한 것은 정상일 때의 이름과 붙어 있는 곳이고, 그것이 있어야 장애 때 무엇이 달라졌는지 견줄 수 있다. 증상이 난 뒤에 처음 읽으면 그 값이 원래 그랬는지 그때 바뀐 것인지 가릴 수 없다.

다음 검증

  1. virsh domiflist 에 §202 가 적은 domain 이름 kc-lab-1 · kc-lab-2 · kc-lab-edge 를 차례로 넣어 각 가상 머신에 붙은 인터페이스를 읽는다.
  2. ip link 로 그 이름이 호스트에 실재하는지 대조한다.
  3. bridge link 로 각 인터페이스가 어느 브리지의 포트인지 적는다.
  4. 두 가상 머신의 결과를 인터페이스 이름 · MAC 주소 · 붙어 있는 브리지로 나란히 적고, 실행한 명령과 출력을 함께 증거로 남긴다.

닫는 조건 : 가상 머신마다 인터페이스 이름과 MAC 주소와 붙어 있는 브리지를 적어 두 대를 나란히 놓으면 닫는다. 이 목록이 계층별 캡처 기준이 요구하는 지점의 이름이 되고, 이것이 없으면 실제 패킷 경로를 묻는 물음의 tcpdump 를 어느 인터페이스에 걸지 정할 수 없다. 두 가상 머신이 서로 다른 브리지에 붙어 있으면 §117.1 의 「특정 VM 만 통신 불가」를 진단할 때 그 사실을 먼저 본다고 적는다.