기록 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>
00 — lab host 준비
이 단계가 끝나면
virsh list 가 sudo 없이 돌고, VM 을 만들 수 있는 상태가 된다.
전제
물리 기계 한 대. 이 실험대는 Arch Linux 를 썼지만 배포판은 상관없다 — 패키지 이름만 다르다.
0. 저장소를 lab host 에 받는다
뒤 단계가 deploy/ 아래 파일을 쓴다. 05·06 의 kubectl apply -f deploy/lab/k8s/... 가 그것이고, 경로는 저장소 루트 기준이다. lab host 에
저장소가 없으면 cp: cannot stat / error: the path ... does not exist 로
막힌다 — 이 실험대에서 실제로 겪은 형태다.
하기 — [lab host]
git clone https://git.learn.hyeonworks.com/donghyeon.kang/keycloak-pattern.git ~/workspace/keycloak-pattern
cd ~/workspace/keycloak-pattern
확인
ls deploy/lab/k8s/
어디를 봐야 하는가 — keycloak-cluster.yaml 과 observability.yaml 이
보이는가.
이 결과가 의미하는 것 — 이후 단계에서 deploy/... 로 시작하는 상대경로가
나오면 전부 이 디렉터리 안에서 치는 것이다. 다른 데서 치면 파일을 못 찾는다.
★ 이미 한 번 실험대를 세웠다가 철거했다면 이 디렉터리가 없을 수 있다.
철거는 VM·디스크·네트워크만 지우고 저장소는 각자 관리라, ~/workspace 에
cloud-init seed 만 남아 있는 상태가 흔하다. ls ~/workspace 로 먼저 본다.
1. CPU 가상화가 켜져 있는가
BIOS 에서 꺼져 있으면 아무것도 못 한다. 먼저 본다.
확인 — CPU 가 하드웨어 가상화 확장을 내놓고 있는가
grep -Eo 'vmx|svm' /proc/cpuinfo | head -1
어디를 봐야 하는가 — 출력 한 줄이 전부다. vmx(Intel) 또는 svm(AMD)
중 하나가 찍히는가, 아니면 아무것도 안 찍히는가.
이 결과가 의미하는 것 — 찍혔으면 이 호스트에서 KVM 을 쓸 수 있다. 다음 단계로 간다. 빈 출력은 「CPU 가 못 한다」가 아니라 대개 BIOS 에서 꺼져 있다는 뜻이다 — 재부팅해 Intel VT-x / AMD-V 를 켜고 다시 잰다. 여기서 막히면 뒤의 어떤 단계도 의미가 없으므로 진행하지 않는다.
실측 — 이 실험대의 호스트는 16 코어 전부에서 지원한다.
2. KVM 모듈이 올라와 있는가
확인 — 커널이 그 확장을 실제로 잡고 있는가
lsmod | grep kvm
형태 (이 실험대에서 캡처해 두지 않았다 — 줄 모양만)
kvm_intel ...
kvm ...
어디를 봐야 하는가 — 왼쪽 첫 열의 모듈 이름 두 개. 벤더 모듈
(kvm_intel 또는 kvm_amd)과 공용 kvm 이 둘 다 있어야 한다. 셋째 열은
이 모듈을 쓰고 있는 쪽의 수라서, 아직 VM 이 없으면 0 인 것이 정상이다.
이 결과가 의미하는 것 — 두 줄이면 커널이 하드웨어 가상화를 쓸 준비가 됐고
virt-install 이 KVM 가속으로 뜬다. kvm 만 있고 벤더 모듈이 없으면 1번의
BIOS 설정이 커널까지 안 넘어온 것이다 — sudo modprobe kvm_intel 로 직접
올려 보면 거부 사유가 그대로 나온다. 아무것도 없으면 1번으로 돌아간다.
왜 이걸 먼저 보나. KVM 없이도 QEMU 는 돌지만 소프트웨어 에뮬레이션이 되어 수십 배 느리다. VM 두 대가 「뜨긴 뜨는데 느리다」면 대개 여기다.
3. 패키지 설치
하기 (Arch)
sudo pacman -S --needed qemu-full libvirt virt-install dnsmasq
Debian/Ubuntu 면 이름이 다르다.
sudo apt install qemu-system-x86 libvirt-daemon-system virtinst cloud-image-utils
| 무엇 | 하는 일 |
|---|---|
| qemu | 실제로 가상 기계를 돌리는 것 |
| libvirt | qemu 를 관리하는 층 (virsh 가 여기 붙는다) |
| virt-install | VM 을 만드는 명령 |
| dnsmasq | 가상 네트워크의 DHCP·DNS |
확인 — 두 실행 파일이 PATH 에 들어왔는가
virsh --version
qemu-system-x86_64 --version
어디를 봐야 하는가 — 판 번호 두 줄. 명령을 못 찾는다(command not found)면
패키지가 안 깔린 것이고, 번호가 나오면 깔린 것이다.
이 결과가 의미하는 것 — 여기서 나오는 libvirt 판 번호가 뒤의 옵션 이름을
가른다. 이 실험대는 libvirt 12.7.0 · QEMU emulator version 11.1.1 이었다
(문서 끝 실측값 블록). 훨씬 낮은 판이면 virt-install --cloud-init 같은
옵션의 동작이 다를 수 있으니, 01 에서 막힐 때 이 번호를 같이 본다.
4. libvirt 를 띄우고 권한을 받는다
하기
sudo systemctl enable --now libvirtd.socket
sudo usermod -aG libvirt "$USER"
그리고 로그아웃했다 다시 들어온다. 보조 그룹은 로그인할 때 정해지므로
usermod 만으로는 지금 셸에 반영되지 않는다.
확인 — 지금 이 셸이 libvirt 에 sudo 없이 붙는가
groups # libvirt 가 보여야 한다
virsh list --all # sudo 없이 돌아야 한다
실측
donghyeon libvirt wheel
어디를 봐야 하는가 — groups 출력에 libvirt 가 끼어 있는가, 그리고
virsh list --all 이 머리글만 있는 빈 표라도 오류 없이 끝나는가. 아직
VM 을 안 만들었으므로 표가 비어 있는 것이 정상이다 — 봐야 할 것은 표의
내용이 아니라 명령이 통과했다는 사실이다.
이 결과가 의미하는 것 — 둘 다 통과하면 이 셸에서 VM 을 만들 수 있고,
01 로 넘어가도 된다. groups 에 libvirt 가 없으면 usermod 는 됐지만
지금 로그인 세션이 옛 그룹 목록을 들고 있는 것이다 — 로그아웃/로그인
한다. groups 에는 있는데 virsh 가 Permission denied 면 그룹이 아니라
소켓 문제이므로 systemctl status libvirtd.socket 을 본다.
libvirtd.service가 아니라.socket을 켠 이유. 소켓 활성화라서 데몬이 미리 떠 있지 않아도virsh가 접속하는 순간 systemd 가 띄운다. 자원을 아끼고, 데몬을 재시작해도 클라이언트가 끊기지 않는다.
5. 연결 URI 를 고정한다
virsh 는 기본으로 qemu:///session(사용자 단위)에 붙는데, VM 은
qemu:///system(시스템 단위)에 만들어야 한다. 이걸 안 맞추면 만든 VM 이
안 보인다.
하기 — 셸 프로필에 넣는다
echo 'export LIBVIRT_DEFAULT_URI=qemu:///system' >> ~/.bashrc
확인 — 지금 셸이 어느 하이퍼바이저를 보고 있는가
virsh uri
qemu:///system
어디를 봐야 하는가 — 끝의 한 낱말. system 인가 session 인가.
이 결과가 의미하는 것 — qemu:///system 이면 뒤에서 만들 VM 과 지금
virsh 가 같은 곳을 본다. qemu:///session 이면 사용자 단위 하이퍼바이저를
보고 있어 VM 은 만들어졌는데 virsh list 에 안 나오는 상태가 된다.
.bashrc 에 넣은 것은 새로 여는 셸에만 적용되므로, 지금 셸에서는
export LIBVIRT_DEFAULT_URI=qemu:///system 을 한 번 더 치거나 새 셸을 연다.
6. 기본 네트워크
확인 — VM 이 붙을 가상 네트워크가 살아 있는가
virsh net-list --all
실측
Name State Autostart Persistent
--------------------------------------------
default active yes yes
어디를 봐야 하는가 — default 행의 State 와 Autostart 두 칸.
--all 을 준 이유가 여기 있다 — 빼면 inactive 인 네트워크는 아예 목록에
안 나와서 「없음」과 「꺼짐」을 구분할 수 없다.
이 결과가 의미하는 것 — active + yes 면 지금도, 호스트를 재부팅한
뒤에도 virbr0 와 192.168.122.0/24 가 있다. inactive 면 VM 을 만들어도
DHCP 가 없어 IP 를 못 받는다. Autostart 가 no 면 지금은 되지만 호스트를
재부팅한 다음 01 의 SSH 가 전부 실패하고, 원인을 게스트에서 찾게 된다.
둘 중 하나라도 어긋나면 아래 두 줄로 맞춘다.
virsh net-start default
virsh net-autostart default
이 네트워크가 virbr0 브리지와 192.168.122.0/24 대역을 만든다. VM 들이
여기 붙는다.
막히면
| 증상 | 원인 | 확인 |
|---|---|---|
virsh list 에 permission denied |
그룹 반영 안 됨 | 로그아웃/로그인 했는가. groups 에 libvirt 가 있는가 |
| 만든 VM 이 목록에 없다 | URI 가 session |
virsh uri |
| VM 이 극단적으로 느리다 | KVM 미사용 | lsmod | grep kvm · BIOS |
net-start default 실패 |
dnsmasq 없음 | 패키지 설치 확인 |
이 단계의 실측값
돌고 있는 실험대에서 그대로 읽은 것이다.
libvirt 12.7.0
qemu QEMU emulator version 11.1.1
그룹 donghyeon libvirt wheel
네트워크 default / active / autostart yes