기록 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>
236 lines
13 KiB
Markdown
236 lines
13 KiB
Markdown
---
|
|
kind: SETUP
|
|
slug: tear-down-the-lab-and-know-what-survives
|
|
title: 실험대를 철거하고 무엇이 남는지 확인한다
|
|
topic: lab-environment-build
|
|
topicName: 실험대 환경 구성
|
|
project: virtualization
|
|
status: 게시 전
|
|
pinnedVersions:
|
|
- name: libvirt
|
|
version: 12.7.0
|
|
- name: QEMU
|
|
version: 11.1.1
|
|
- name: 커널
|
|
version: 7.2.2-arch1-1
|
|
- name: 호스트
|
|
version: Arch Linux · i5-1135G7 · RAM 11,648MiB
|
|
- name: 게스트
|
|
version: Debian 12 genericcloud
|
|
source:
|
|
- final/document.md#202-철거-실제-출력-전문
|
|
- final/document.md#204-재구축할-때-무엇이-남아-있나
|
|
- final/document.md#195-이-부의-출처와-범위
|
|
sourceRevision: 9465582b5d1630eb4ae7c4e078021486919bf6b6
|
|
---
|
|
|
|
# 실험대를 철거하고 무엇이 남는지 확인한다
|
|
|
|
게스트 세 대와 DHCP 예약을 지우고 무엇이 남았는지까지 확인하는 절차다. 세우는 가이드에는 이 부분이 없어서 2026-09-10 에 직접 돌리며 명령과 출력을 적었다. 되돌리는 명령은 이 절차에 없다.
|
|
|
|
## 관계
|
|
|
|
- **cloud-init 시드로 게스트 세 대를 만들고 SSH 가 키로 붙게 한다**
|
|
여기서 지우는 것을 그 절차가 만들고, 다시 세울 때 돌아갈 곳도 거기다.
|
|
- **실험대를 껐다 켜고 게스트 메모리를 다시 나눈다**
|
|
워크로드를 정상으로 내리고 싶으면 그 편의 종료 순서를 먼저 돌고 온다. 여기서는 지우는 것이 목적이라 전원을 뽑는다.
|
|
- **5120MB 를 줬는데 353MB 를 쓰고 있었다 — 선언한 양과 실제로 드는 양**
|
|
회수된 디스크 3.1GB 를 읽는 방법이 그 기록과 같다. 선언한 크기와 실제로 차지한 크기는 다른 값이다.
|
|
- **이 실험대의 certbot 은 HTTP-01 로 받고 있는가 DNS-01 로 받고 있는가**
|
|
인증서를 지우지 않고 남기는 까닭이 이 물음이 안 닫혔기 때문이다. 답이 나오면 정책이 바뀐다.
|
|
- **가이드대로 다시 쳐서 이 실험대가 같은 상태로 서는가**
|
|
철거는 그 물음을 재기 위한 전제라, 지우고 다시 세워 봐야 답이 나온다.
|
|
- **도구가 낸 출력은 대상의 상태가 아니다 — 그 명령이 무엇을 세는지부터 가른다**
|
|
`virbr0` 가 `DOWN` 으로 보이는 것을 고장으로 읽지 않는 근거가 그 기준이다.
|
|
|
|
## 본문
|
|
|
|
<!-- body:start -->
|
|
|
|
## 읽기 전에 — 어디서 치는가
|
|
|
|
전부 `[lab host]` 다. 게스트를 통째로 지우는 절차라 게스트 안에서 칠 명령이 하나도 없다.
|
|
|
|
조회와 삭제뿐이라 편집기를 여는 곳도 없고 CLI 를 그대로 쓴다.
|
|
|
|
## 되돌리기가 없다
|
|
|
|
`virsh undefine --remove-all-storage` 는 도메인 정의와 오버레이 디스크와 시드 ISO 를 한 번에 지운다. 지운 뒤에 되살리는 명령이 libvirt 에 없다. 실험대를 다시 쓰려면 `base.qcow2` 위에 오버레이를 새로 만들고 시드 ISO 를 다시 구워야 하고, 그 절차는 게스트 세 대를 만드는 편이 받는다.
|
|
|
|
지우기 전에 알아 둘 것은 이 절차가 건드리지 않는 쪽이다. `base.qcow2` 와 `~/workspace/cloud/kc-lab-{1,2}.yaml` 과 `~/.ssh/config` 의 `kc-lab-*` 항목은 그 자체로 살아 있어서 재구축 때 다시 쓴다. 무엇이 어느 쪽인지는 아래 표가 아홉 행으로 가른다.
|
|
|
|
## 지우기 전에 먼저 본다
|
|
|
|
**무엇을 확인하는가** — 지금 무엇이 있는지. 철거 뒤와 견줄 값을 여기서 받아 둔다.
|
|
|
|
```bash label="[lab host] 도메인 · 볼륨 · 예약 · 디스크 사용량을 한 번에 본다"
|
|
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. 게스트 세 대를 지운다
|
|
|
|
**목적** — 도메인 정의와 그 게스트가 쓰던 디스크를 함께 없앤다.
|
|
|
|
세 게스트의 전원을 뽑고 정의와 디스크를 지운 뒤, 무엇이 없어졌는지 바로 센다.
|
|
|
|
```bash label="[lab host] ① 게스트 셋을 전원부터 뽑고 정의와 디스크를 함께 지운다"
|
|
for v in kc-lab-edge kc-lab-2 kc-lab-1; do
|
|
virsh destroy "$v"
|
|
virsh undefine "$v" --remove-all-storage
|
|
done
|
|
```
|
|
|
|
```bash label="[lab host] ② 남은 도메인과 볼륨을 센다"
|
|
virsh list --all
|
|
virsh vol-list default
|
|
```
|
|
|
|
**예상 결과** — 게스트 한 대마다 네 줄이 나온다. 아래는 `kc-lab-edge` 한 대분이다(observed).
|
|
|
|
```text label="[lab host] ① 의 출력 — 한 대분"
|
|
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` 네트워크에서 게스트 주소 예약을 빼고 동적 대역만 남긴다.
|
|
|
|
세 예약을 값 그대로 지운 뒤 네트워크 정의에 무엇이 남았는지 본다. 삭제할 때도 `mac` 과 `name` 과 `ip` 세 속성을 다 준다.
|
|
|
|
```bash label="[lab host] ① 예약 세 줄을 값 그대로 지운다"
|
|
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
|
|
```
|
|
|
|
```bash label="[lab host] ② 예약이 빠지고 동적 대역만 남았는지 본다"
|
|
virsh net-dumpxml default | grep -E "host mac|range start"
|
|
```
|
|
|
|
**예상 결과** — ① 은 삭제마다 `Updated network default persistent config and live state` 를 낸다. ② 에는 `<range>` 한 줄만 남는다.
|
|
|
|
```text label="[lab host] ② 의 출력 — 동적 대역만 남았다"
|
|
<dhcp>
|
|
<range start='192.168.122.2' end='192.168.122.254'/>
|
|
</dhcp>
|
|
```
|
|
|
|
**왜 필요한가** — 예약을 남겨 두면 다음 구축에서 예약이 두 벌이 되거나, 넣으려 할 때 이미 있다고 거부당한다. `--live` 와 `--config` 를 둘 다 주는 까닭도 넣을 때와 같다. `--live` 만 주면 재부팅에 예약이 되살아나고 `--config` 만 주면 지금 돌고 있는 dnsmasq 가 아직 예약을 들고 있다.
|
|
|
|
**문제가 생기면** — 속성이 하나라도 비면 이렇게 거부된다.
|
|
|
|
```text label="[lab host] 이름이 빈 채로 삭제를 시도했을 때"
|
|
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 로 전환하면 되고, 다만 재구축을 시작하자마자 그 일부터 하게 된다. 그래서 이 정책은 「어느 쪽인지 모르는 채로는 지우지 않는다」가 전부다.
|
|
|
|
그래도 지워야 한다면 먼저 백업한다.
|
|
|
|
```bash label="[lab host] 인증서를 통째로 묶어 둔다"
|
|
sudo tar czf ~/letsencrypt-backup-$(date +%Y%m%d-%H%M%S).tgz -C /etc letsencrypt
|
|
```
|
|
|
|
복원은 반대로 한 줄이다. `{{STAMP}}` 는 위 명령이 만든 파일 이름에 찍힌 시각을 그대로 옮겨 넣는다.
|
|
|
|
```bash label="[lab host] 묶어 둔 인증서를 되돌린다"
|
|
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` 목록이 그 순서로 적혀 있다.
|
|
|
|
## 확인 방법
|
|
|
|
**무엇을 확인하는가** — 철거 전에 받아 둔 네 값이 전부 내려갔는지.
|
|
|
|
```bash label="[lab host] 철거 뒤 같은 네 값을 다시 본다"
|
|
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 안팎인데 그것은 잰 값이 아니라 역산한 값이다.
|
|
|
|
`virbr0` 가 `DOWN` 인 것은 고장이 아니다. 브리지에 붙은 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/config` 의 `kc-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 에 이 호스트에서 실제로 돌려 받은 출력이고, 그 뒤에 다시 돌려 검증하지는 않았다. 다시 돌리면 실험대가 없어지기 때문이다.
|
|
|
|
<!-- body:end -->
|