292 lines
18 KiB
Markdown
292 lines
18 KiB
Markdown
---
|
|
id: 87e0138d-dedc-4734-89b3-4ebe7c2df56d
|
|
kind: SETUP
|
|
slug: tear-down-the-lab-and-know-what-survives
|
|
title: 실험대를 철거하고 무엇이 남는지 확인한다
|
|
topic: lab-environment-build
|
|
topicName: 실험대 환경 구성
|
|
project: virtualization
|
|
status: 게시 전
|
|
studio: "https://hyeonworks.com/studio/documents/87e0138d-dedc-4734-89b3-4ebe7c2df56d/edit"
|
|
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: import-head 9465582b5d1630eb4ae7c4e078021486919bf6b6 · uncommitted-working-tree snapshot
|
|
evidence:
|
|
- ../../../final/evidence/raw/lab-state-before-rebuild/58-authenticator-and-token.txt
|
|
---
|
|
|
|
# 실험대를 철거하고 무엇이 남는지 확인한다
|
|
|
|
게스트 세 대와 DHCP 예약을 지우고 무엇이 남았는지까지 확인하는 절차다. 세우는 가이드에는 이 부분이 없어서 2026-09-10 에 직접 돌리며 명령과 출력을 적었다. 되돌리는 명령은 이 절차에 없다.
|
|
|
|
## 관계
|
|
|
|
- **cloud-init 시드로 게스트 세 대를 만들고 SSH 가 키로 붙게 한다**
|
|
여기서 지우는 것을 그 절차가 만들고, 다시 세울 때 돌아갈 곳도 거기다.
|
|
- **실험대를 껐다 켜고 게스트 메모리를 다시 나눈다**
|
|
워크로드를 정상으로 내리고 싶으면 그 편의 종료 순서를 먼저 돌고 온다. 여기서는 지우는 것이 목적이라 전원을 뽑는다.
|
|
- **5120MB 를 줬는데 353MB 를 쓰고 있었다 — 선언한 양과 실제로 드는 양**
|
|
회수된 디스크 3.1GB 를 읽는 방법이 그 기록과 같다. 선언한 크기와 실제로 차지한 크기는 다른 값이다.
|
|
- **이 실험대의 certbot 은 HTTP-01 로 받고 있는가 DNS-01 로 받고 있는가**
|
|
이 물음은 `dns-cloudflare` 관측으로 닫혔다. 여기서는 그 사실과 별개로 현재 자격증명이 재발급에 쓸 수 있는지를 철거 조건으로 본다.
|
|
- **가이드대로 다시 쳐서 이 실험대가 같은 상태로 서는가**
|
|
철거는 그 물음을 재기 위한 전제라, 지우고 다시 세워 봐야 답이 나온다.
|
|
- **도구가 낸 출력은 대상의 상태가 아니다 — 그 명령이 무엇을 세는지부터 가른다**
|
|
`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 였다.
|
|
|
|
**이 결과가 의미하는 것** — 이 네 값이 철거의 성공 판정 기준이 된다. 여기를 건너뛰면 지운 뒤에 「원래 몇 개였지」를 되짚을 방법이 없다.
|
|
|
|
2026-09-17 에 다시 세운 실험대에서 같은 네 줄을 쳤다(observed). 도메인 3 대에 볼륨 7 개, 예약 3 줄까지는 2026-09-10 과 같고 **디스크만 11G 가 아니라 18G 다.** 그사이에 k3s 와 컨테이너 이미지가 쌓였다. 그래서 이 네 값은 「이 호스트의 정답」이 아니라 **지금 이 실행에서 받아 두는 대조군**이다 — 위에 실은 숫자와 다르다고 잘못된 것이 아니다.
|
|
|
|
```text label="2026-09-17 의 네 값"
|
|
도메인 kc-lab-1 · kc-lab-edge · kc-lab-2 (셋 다 running)
|
|
볼륨 base.qcow2 + kc-lab-{1,2,edge}.qcow2 + seed-kc-lab-{1,2,edge}.iso = 7
|
|
예약 52:54:00:aa:bb:{10,11,12} = 3 줄
|
|
디스크 /dev/nvme0n1p3 226G 18G 197G 9% /
|
|
```
|
|
|
|
## 실행 절차
|
|
|
|
### 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=""` 이 된다. 세 줄을 값 그대로 쓰는 편이 안전하다.
|
|
|
|
## 인증서는 edge guest에서 백업한다
|
|
|
|
2026-09-17 현재 서빙하는 인증서는 **`kc-lab-edge` 안의 `/etc/letsencrypt/`** 에 있다(observed). 03에서 nginx를 edge guest로 옮겼고 04에서 certbot도 그 guest에 설치했다. 이 절차의 1번은 guest를 `--remove-all-storage`로 지우므로, 인증서도 백업하지 않으면 guest 디스크와 함께 사라진다.
|
|
|
|
두 기계를 나란히 열어 보면 이렇다.
|
|
|
|
```bash label="[lab host] 어느 쪽에 무엇이 있나"
|
|
ls -la /etc/letsencrypt/
|
|
ssh kc-lab-edge 'sudo ls -la /etc/letsencrypt/'
|
|
```
|
|
|
|
| 기계 | `/etc/letsencrypt/` | certbot | 타이머 | 서빙 |
|
|
|---|---|---|---|---|
|
|
| 랩 호스트 | 있다 (읽으려면 `sudo`) | `/usr/bin/certbot` | 없다 | 안 한다 — 80·443 을 안 듣는다 |
|
|
| `kc-lab-edge` | 있다 — `cli.ini` · `renewal-hooks` | `/usr/bin/certbot` | `certbot.timer` | **한다** |
|
|
|
|
따라서 **철거 전에 백업할 대상은 edge guest의 `/etc/letsencrypt/` 하나다.** 파일 이름은 host에서 한 번 만든 시각값으로 고정해, 원격 tar와 scp가 같은 파일을 가리키게 한다.
|
|
|
|
```bash label="[lab host] 실제로 서빙하는 인증서를 edge guest에서 묶는다"
|
|
STAMP=$(date +%Y%m%d-%H%M%S)
|
|
ssh kc-lab-edge "sudo tar czf /tmp/letsencrypt-backup-$STAMP.tgz -C /etc letsencrypt"
|
|
scp "kc-lab-edge:/tmp/letsencrypt-backup-$STAMP.tgz" "$HOME/"
|
|
```
|
|
|
|
**예상 결과** — host의 `$HOME/letsencrypt-backup-$STAMP.tgz`가 생긴다. 이 파일은 edge guest를 `--remove-all-storage`로 지우기 전에 host 쪽으로 빠져나온 복구본이다.
|
|
|
|
패키지도 host와 guest를 나눠 본다. `kc-lab-edge` 안의 `nginx`와 `certbot`은 guest와 함께 사라지고, host에는 `libvirt`·`qemu`·`kubectl`과 현재 서빙에는 쓰이지 않는 host `certbot`이 남는다.
|
|
|
|
정책으로 남기는 것은 guest 안의 디렉터리 자체가 아니라 **host로 복사한 인증서 backup tar**다. 한도 때문도 아니고 검증 방식이 미확정이어서도 아니다. 2026-09-17 renewal 설정에서 `authenticator = dns-cloudflare` 를 직접 읽어 **DNS-01 등록은 확인했다**.
|
|
|
|
backup tar를 남기는 까닭은 **현재 자격증명으로 다시 받을 수 있는지가 확인되지 않았기 때문**이다. 같은 후속 원문에서 `/etc/letsencrypt/cloudflare.ini` 의 토큰 길이는 0자로 측정됐고 Cloudflare 검증은 `Invalid request headers` 로 실패했다. 따라서 DNS-01이라는 사실만으로 “guest를 지워도 다시 받으면 된다”고 결론내리지 않는다.
|
|
|
|
유효한 Cloudflare 토큰을 다시 준비하고 `certbot renew --dry-run` 이 성공한 원문까지 남기면 그때 보존 정책을 완화할 수 있다. 그 전에는 guest를 지우기 전에 실제 서빙 중인 `/etc/letsencrypt/` 를 host로 백업하고 그 tar를 보존한다.
|
|
|
|
복원도 **새로 만든 `kc-lab-edge` 안으로** 되돌린다. host의 `/etc`에 풀지 않는다. `{{STAMP}}`에는 백업 파일 이름의 시각값을 넣는다.
|
|
|
|
```bash label="[lab host] 백업을 새 edge guest로 되돌린다"
|
|
BACKUP="$HOME/letsencrypt-backup-{{STAMP}}.tgz"
|
|
scp "$BACKUP" kc-lab-edge:/tmp/letsencrypt-backup.tgz
|
|
ssh kc-lab-edge 'sudo tar xzf /tmp/letsencrypt-backup.tgz -C /etc'
|
|
ssh kc-lab-edge 'sudo certbot certificates && sudo nginx -t'
|
|
```
|
|
|
|
마지막 줄이 둘 다 성공해야 복원이 끝난 것이다. 인증서 파일이 돌아왔는지와 nginx가 그 경로를 실제로 읽을 수 있는지를 따로 확인한다.
|
|
|
|
## 구성 값
|
|
|
|
지우는 대상은 게스트 셋과 그 셋의 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 안팎인데 그것은 잰 값이 아니라 역산한 값이다.
|
|
|
|
**그 역산은 아마 너무 컸다**(2026-09-17, observed). 같은 호스트에 다시 세운 실험대의 볼륨 일곱을 `virsh vol-info` 로 재 보니 엣지가 가장 작다. 선언한 크기와 실제로 먹는 양이 크게 다르고, 오버레이라 쓴 만큼만 먹는다.
|
|
|
|
```bash label="[lab host] 볼륨이 실제로 먹는 양을 본다"
|
|
virsh vol-info --pool default kc-lab-edge.qcow2
|
|
```
|
|
|
|
```text
|
|
base.qcow2 Capacity=3.00 GiB Allocation=323.25 MiB
|
|
kc-lab-1.qcow2 Capacity=20.00 GiB Allocation=5.40 GiB
|
|
kc-lab-2.qcow2 Capacity=20.00 GiB Allocation=3.85 GiB
|
|
kc-lab-edge.qcow2 Capacity=10.00 GiB Allocation=316.26 MiB
|
|
seed-kc-lab-{1,2,edge}.iso Capacity=370.00 KiB Allocation=372.00 KiB
|
|
```
|
|
|
|
**이 값을 2026-09-10 의 역산 대신 그대로 끼워 넣지는 않는다** — 다른 날 다른 실험대이고 그 위에 올린 것도 다르다. 다만 엣지가 nginx 하나만 돌리는 게스트라 300MB 대에 머문다는 것은 두 실행에서 같을 가능성이 높고, 그렇다면 그때의 「1GB 안팎」은 과대 추정이다. **다시 철거할 때는 역산하지 말고 지우기 전에 이 명령으로 세 볼륨을 직접 잰다.**
|
|
|
|
`virbr0` 가 `DOWN` 인 것은 고장이 아니다. 브리지에 붙은 tap 인터페이스가 하나도 없어서 캐리어가 없는 것으로 표시될 뿐이고, 주소 `192.168.122.1/24` 는 그대로 있다. VM 을 다시 띄우면 그 VM 의 `vnetN` 인터페이스가 브리지에 붙으면서 `UP` 이 된다. `virsh net-start` 를 찾아 헤매지 않는다.
|
|
|
|
## 철거해도 남는 것과 사라지는 것
|
|
|
|
이걸 모르면 재구축이 「왜 이건 이미 있지」와 「왜 이건 없지」의 반복이 된다.
|
|
|
|
| 무엇 | 어떻게 되나 | 왜 |
|
|
|---|---|---|
|
|
| `base.qcow2` (335MB) | 남는다 | 다음 오버레이의 바닥 |
|
|
| host 패키지 (`libvirt` · `qemu` · `kubectl`, 쓰이지 않는 host `certbot`) | 남는다 | guest 삭제와 무관한 host 설치 상태 |
|
|
| edge guest의 `nginx` · `certbot` | 사라진다 | `kc-lab-edge` 디스크와 함께 삭제된다 |
|
|
| `~/workspace/cloud/kc-lab-{1,2}.yaml` | 남는다 | 키와 비밀번호가 들어 있다 |
|
|
| `~/.ssh/config` 의 `kc-lab-*` 항목 | 남는다 | 재구축해도 IP 가 같다 |
|
|
| libvirt `default` 네트워크 정의 | 남는다 | 예약만 지웠다 |
|
|
| edge guest의 `/etc/letsencrypt/` | 사라진다 | guest 삭제 전에 host의 `$HOME/letsencrypt-backup-<stamp>.tgz`로 백업한다 |
|
|
| host에 복사한 인증서 백업 tar | 남긴다 (정책) | DNS-01 등록은 확인됐지만 credential 유효성과 `certbot renew --dry-run` 성공은 아직 미확인 |
|
|
| 게스트 디스크 · 시드 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 -->
|