Files
document-haness/docs/virtualization/tech-log-studio/lab-environment-build/setup/setup-tear-down-the-lab-and-know-what-survives.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

13 KiB

kind, slug, title, topic, topicName, project, status, pinnedVersions, source, sourceRevision
kind slug title topic topicName project status pinnedVersions source sourceRevision
SETUP tear-down-the-lab-and-know-what-survives 실험대를 철거하고 무엇이 남는지 확인한다 lab-environment-build 실험대 환경 구성 virtualization 게시 전
name version
libvirt 12.7.0
name version
QEMU 11.1.1
name version
커널 7.2.2-arch1-1
name version
호스트 Arch Linux · i5-1135G7 · RAM 11,648MiB
name version
게스트 Debian 12 genericcloud
final/document.md#202-철거-실제-출력-전문
final/document.md#204-재구축할-때-무엇이-남아-있나
final/document.md#195-이-부의-출처와-범위
9465582b5d1630eb4ae7c4e078021486919bf6b6

실험대를 철거하고 무엇이 남는지 확인한다

게스트 세 대와 DHCP 예약을 지우고 무엇이 남았는지까지 확인하는 절차다. 세우는 가이드에는 이 부분이 없어서 2026-09-10 에 직접 돌리며 명령과 출력을 적었다. 되돌리는 명령은 이 절차에 없다.

관계

  • cloud-init 시드로 게스트 세 대를 만들고 SSH 가 키로 붙게 한다 여기서 지우는 것을 그 절차가 만들고, 다시 세울 때 돌아갈 곳도 거기다.
  • 실험대를 껐다 켜고 게스트 메모리를 다시 나눈다 워크로드를 정상으로 내리고 싶으면 그 편의 종료 순서를 먼저 돌고 온다. 여기서는 지우는 것이 목적이라 전원을 뽑는다.
  • 5120MB 를 줬는데 353MB 를 쓰고 있었다 — 선언한 양과 실제로 드는 양 회수된 디스크 3.1GB 를 읽는 방법이 그 기록과 같다. 선언한 크기와 실제로 차지한 크기는 다른 값이다.
  • 이 실험대의 certbot 은 HTTP-01 로 받고 있는가 DNS-01 로 받고 있는가 인증서를 지우지 않고 남기는 까닭이 이 물음이 안 닫혔기 때문이다. 답이 나오면 정책이 바뀐다.
  • 가이드대로 다시 쳐서 이 실험대가 같은 상태로 서는가 철거는 그 물음을 재기 위한 전제라, 지우고 다시 세워 봐야 답이 나온다.
  • 도구가 낸 출력은 대상의 상태가 아니다 — 그 명령이 무엇을 세는지부터 가른다 virbr0DOWN 으로 보이는 것을 고장으로 읽지 않는 근거가 그 기준이다.

본문

읽기 전에 — 어디서 치는가

전부 [lab host] 다. 게스트를 통째로 지우는 절차라 게스트 안에서 칠 명령이 하나도 없다.

조회와 삭제뿐이라 편집기를 여는 곳도 없고 CLI 를 그대로 쓴다.

되돌리기가 없다

virsh undefine --remove-all-storage 는 도메인 정의와 오버레이 디스크와 시드 ISO 를 한 번에 지운다. 지운 뒤에 되살리는 명령이 libvirt 에 없다. 실험대를 다시 쓰려면 base.qcow2 위에 오버레이를 새로 만들고 시드 ISO 를 다시 구워야 하고, 그 절차는 게스트 세 대를 만드는 편이 받는다.

지우기 전에 알아 둘 것은 이 절차가 건드리지 않는 쪽이다. base.qcow2~/workspace/cloud/kc-lab-{1,2}.yaml~/.ssh/configkc-lab-* 항목은 그 자체로 살아 있어서 재구축 때 다시 쓴다. 무엇이 어느 쪽인지는 아래 표가 아홉 행으로 가른다.

지우기 전에 먼저 본다

무엇을 확인하는가 — 지금 무엇이 있는지. 철거 뒤와 견줄 값을 여기서 받아 둔다.

virsh list --all
virsh vol-list default
virsh net-dumpxml default | grep -A5 dhcp
df -h /

어디를 봐야 하는가 — 네 값이다. 도메인이 몇 대인가, 볼륨이 몇 개인가, <host> 예약이 몇 줄인가, 루트 파일시스템이 얼마나 찼는가. 2026-09-10 의 이 호스트에서는 도메인 3 대에 볼륨 7 개, 예약 3 줄, df -h / 가 11G 였다.

이 결과가 의미하는 것 — 이 네 값이 철거의 성공 판정 기준이 된다. 여기를 건너뛰면 지운 뒤에 「원래 몇 개였지」를 되짚을 방법이 없다.

실행 절차

1. 게스트 세 대를 지운다

목적 — 도메인 정의와 그 게스트가 쓰던 디스크를 함께 없앤다.

세 게스트의 전원을 뽑고 정의와 디스크를 지운 뒤, 무엇이 없어졌는지 바로 센다.

for v in kc-lab-edge kc-lab-2 kc-lab-1; do
  virsh destroy "$v"
  virsh undefine "$v" --remove-all-storage
done
virsh list --all
virsh vol-list default

예상 결과 — 게스트 한 대마다 네 줄이 나온다. 아래는 kc-lab-edge 한 대분이다(observed).

Domain 'kc-lab-edge' destroyed
Domain 'kc-lab-edge' has been undefined
Volume 'vda'(/var/lib/libvirt/images/kc-lab-edge.qcow2) removed.
Volume 'vdb'(/var/lib/libvirt/images/seed-kc-lab-edge.iso) removed.

왜 필요한가Volume 줄이 두 개 나오는지가 끝났다는 판정이다. vda 가 오버레이 디스크이고 vdb 가 시드 ISO 다. --remove-all-storage 를 빠뜨리면 도메인만 사라지고 디스크 파일은 지워지지 않아, 같은 이름으로 다음 virt-install 을 돌릴 때 「이미 있다」로 실패한다. 그리고 virsh destroy 는 종료 신호를 보내지 않고 전원을 뽑는다. 워크로드를 정상으로 내리고 싶으면 종료 순서를 다루는 편을 먼저 돌고 온다.

문제가 생기면 — ② 의 virsh vol-list default 에 게스트 디스크나 시드 ISO 가 보이면 --remove-all-storage 가 빠진 것이다. 남은 볼륨은 virsh vol-delete --pool default seed-kc-lab-1.iso 처럼 이름을 하나씩 대서 지운다.

2. DHCP 예약 세 줄을 지운다

목적 — libvirt default 네트워크에서 게스트 주소 예약을 빼고 동적 대역만 남긴다.

세 예약을 값 그대로 지운 뒤 네트워크 정의에 무엇이 남았는지 본다. 삭제할 때도 macnameip 세 속성을 다 준다.

virsh net-update default delete ip-dhcp-host \
  "<host mac='52:54:00:aa:bb:10' name='kc-lab-edge' ip='192.168.122.10'/>" \
  --live --config
virsh net-update default delete ip-dhcp-host \
  "<host mac='52:54:00:aa:bb:11' name='kc-lab-1' ip='192.168.122.11'/>" \
  --live --config
virsh net-update default delete ip-dhcp-host \
  "<host mac='52:54:00:aa:bb:12' name='kc-lab-2' ip='192.168.122.12'/>" \
  --live --config
virsh net-dumpxml default | grep -E "host mac|range start"

예상 결과 — ① 은 삭제마다 Updated network default persistent config and live state 를 낸다. ② 에는 <range> 한 줄만 남는다.

    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
    </dhcp>

왜 필요한가 — 예약을 남겨 두면 다음 구축에서 예약이 두 벌이 되거나, 넣으려 할 때 이미 있다고 거부당한다. --live--config 를 둘 다 주는 까닭도 넣을 때와 같다. --live 만 주면 재부팅에 예약이 되살아나고 --config 만 주면 지금 돌고 있는 dnsmasq 가 아직 예약을 들고 있다.

문제가 생기면 — 속성이 하나라도 비면 이렇게 거부된다.

error: Failed to update network default
error: XML error: Cannot use host name '' in network 'default'

zsh 에서 루프로 돌리면 이 오류를 만난다. zsh 는 따옴표 없는 변수를 단어 분리하지 않아서, bash 에서 되던 set -- $entry$1 에 문자열 전체를 넣고 $2$3 을 비워서 name="" 이 된다. 세 줄을 값 그대로 쓰는 편이 안전하다.

인증서는 건드리지 않는다

/etc/letsencrypt/ 는 정책으로 남긴다. 한도 때문이 아니다 — Let's Encrypt 의 「같은 이름 조합에 주당 중복 5장」 제한은 가끔 재구축하는 정도로는 근처에도 못 간다.

남기는 까닭은 지금 재발급이 되는지를 모르기 때문이다. 이 실험대의 이름 셋은 tailnet 주소를 가리키고, 100.64.0.0/10 은 CGNAT(Carrier-Grade NAT, 통신사 공용 주소 변환)용 예약 대역이라 공개 인터넷에서 라우팅되지 않는다. HTTP-01 검증은 Let's Encrypt 가 우리 서버로 들어오는 방식이므로 그 주소로는 검증이 성립하지 않는다. 지금 설정이 DNS-01 이면 지우고 다시 받으면 끝이고, HTTP-01 이면 검증 방식부터 손봐야 한다. 어느 쪽인지는 certbot 설정을 읽는 열린 물음이 한 줄로 닫는다.

§204 는 HTTP-01 인 경우를 「못 한다」가 아니라 「일이 하나 생긴다」로 적었다. 최악이라도 A 레코드를 공인 IP 로 잠깐 돌려 받거나 DNS-01 로 전환하면 되고, 다만 재구축을 시작하자마자 그 일부터 하게 된다. 그래서 이 정책은 「어느 쪽인지 모르는 채로는 지우지 않는다」가 전부다.

그래도 지워야 한다면 먼저 백업한다.

sudo tar czf ~/letsencrypt-backup-$(date +%Y%m%d-%H%M%S).tgz -C /etc letsencrypt

복원은 반대로 한 줄이다. {{STAMP}} 는 위 명령이 만든 파일 이름에 찍힌 시각을 그대로 옮겨 넣는다.

sudo tar xzf ~/letsencrypt-backup-{{STAMP}}.tgz -C /etc

구성 값

지우는 대상은 게스트 셋과 그 셋의 DHCP 예약이다.

게스트 예약의 MAC · IP 볼륨 둘
kc-lab-edge 52:54:00:aa:bb:10 · 192.168.122.10 kc-lab-edge.qcow2 · seed-kc-lab-edge.iso
kc-lab-1 52:54:00:aa:bb:11 · 192.168.122.11 kc-lab-1.qcow2 · seed-kc-lab-1.iso
kc-lab-2 52:54:00:aa:bb:12 · 192.168.122.12 kc-lab-2.qcow2 · seed-kc-lab-2.iso

지우는 순서는 kc-lab-edge · kc-lab-2 · kc-lab-1 이다. 1번의 for 목록이 그 순서로 적혀 있다.

확인 방법

무엇을 확인하는가 — 철거 전에 받아 둔 네 값이 전부 내려갔는지.

virsh list --all
virsh vol-list default
virsh net-dumpxml default | grep -A5 dhcp
df -h /
ip -br addr show virbr0

어디를 봐야 하는가 — 다섯 줄을 전후로 견준다(observed).

무엇을 보는가 철거 전 철거 후
virsh list --all 3 대 running (없음)
virsh vol-list default 7 개 base.qcow2 1 개
DHCP 예약 3 줄 0 줄
df -h / 11G 7.9G
virbr0 UP DOWN

이 결과가 의미하는 것 — 디스크에서 3.1GB 가 회수됐다. 잰 내역은 kc-lab-1 1.4GB 와 kc-lab-2 665MB 와 시드 ISO 세 개(각 370KB)이고, kc-lab-edge 의 디스크 크기는 재 두지 않았다. 합계에서 빼면 1GB 안팎인데 그것은 잰 값이 아니라 역산한 값이다.

virbr0DOWN 인 것은 고장이 아니다. 브리지에 붙은 tap 인터페이스가 하나도 없어서 캐리어가 없는 것으로 표시될 뿐이고, 주소 192.168.122.1/24 는 그대로 있다. VM 을 다시 띄우면 그 VM 의 vnetN 인터페이스가 브리지에 붙으면서 UP 이 된다. virsh net-start 를 찾아 헤매지 않는다.

철거해도 남는 것과 사라지는 것

이걸 모르면 재구축이 「왜 이건 이미 있지」와 「왜 이건 없지」의 반복이 된다.

무엇 어떻게 되나
base.qcow2 (335MB) 남는다 다음 오버레이의 바닥
패키지 (libvirt · qemu · nginx · certbot · kubectl) 남는다 재설치가 무의미
~/workspace/cloud/kc-lab-{1,2}.yaml 남는다 키와 비밀번호가 들어 있다
~/.ssh/configkc-lab-* 항목 남는다 재구축해도 IP 가 같다
libvirt default 네트워크 정의 남는다 예약만 지웠다
/etc/letsencrypt/ 남긴다 (정책) 재발급이 되는지를 아직 모른다
게스트 디스크 · 시드 ISO 사라진다 --remove-all-storage
DHCP 예약 사라진다 net-update delete
k3s · Keycloak · 모든 워크로드 사라진다 게스트와 함께

~/workspace/cloud/kc-lab-{1,2}.yaml 이 남는다는 것은 편한 일이면서 위험한 일이다. 그 파일에 SSH 공개키와 콘솔 로그인용 비밀번호가 들어 있으므로, 실험대를 접고 기계를 넘길 때는 이 절차만으로 끝났다고 보지 않는다.

이 절차가 감당하지 않는 것

호스트 계층 철거는 여기 없다. 원본이 deploy/lab/host/teardown-host.sh 를 가리키지만 그 스크립트가 반입되지 않아 내용을 모른다. nginx 설정과 DNAT 유닛과 certbot 훅을 어디까지 걷어내는지는 확인하지 못했다.

다시 세우는 쪽도 여기 없다. 게스트를 만드는 편부터 일곱 편이 그 순서를 받는다.

이 명령들은 2026-09-10 에 이 호스트에서 실제로 돌려 받은 출력이고, 그 뒤에 다시 돌려 검증하지는 않았다. 다시 돌리면 실험대가 없어지기 때문이다.