The guides were written before the skill existed and a scored audit found
three gaps. Fixed by a subagent running under the skill, with measured
values, versions, IPs and quoted output declared off limits.
The big one: every step showed a command and its output, and almost none
said which line to look at or what it meant. 64 interpretation pairs added
across the seven files, weighted where the reading is hardest — 20 in the
Keycloak stage, where a Secret existing and a pod having received it are
different facts.
Only the extracting form of curl appeared. Where the reader meets a response
for the first time the guides now open with curl -I or curl -v and name the
lines worth reading; -w '%{http_code}' survives only where the code is a
value being compared — two upstream nodes against each other, or the 900-run
control loop.
Listing Secret keys went from a three-stage pipe to kubectl describe secret,
which prints the key names and their byte counts in one native command
without exposing a value.
And a tool assumption: jq and yamllint are installed on neither the lab host
nor the guests. The guides now say so where JSON is read by eye, rather than
sending the reader to install something mid-diagnosis. cloud-init schema is
on the guests and is now the guest-side check.
Also removes a stray Playwright screenshot committed at the repository root
in 919547a; the evidence copy under docs/evidence/b7a-orphan-session/ is the
one the document references.
Four things the audit left standing are recorded in the agent's report rather
than papered over — notably that 04's reload measurements are stated without
a reproduction procedure, and that 05 and 06 reference each other as
prerequisites.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
00 — lab host 준비
이 단계가 끝나면
virsh list 가 sudo 없이 돌고, VM 을 만들 수 있는 상태가 된다.
전제
물리 기계 한 대. 이 실험대는 Arch Linux 를 썼지만 배포판은 상관없다 — 패키지 이름만 다르다.
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