# 실습 가이드 — 직접 쳐보면서 만드는 실험대 이 문서 묶음은 **읽는 문서가 아니라 따라 치는 문서**다. 기존 [`experiment-*.md`](../) 가 「무엇을 발견했나」를 적었다면, 여기는 「그 발견을 재현하려면 무엇을 어떤 순서로 치는가」를 적는다. ## 두 종류의 명령을 구별해 적는다 실무자가 터미널에서 치는 명령과, 근거를 남기려고 재는 명령은 길이도 목적도 다르다. 이 가이드는 둘을 섞지 않는다. | 표시 | 무엇인가 | |---|---| | **하기** · **확인** | 실무자가 실제로 치는 형태. 짧고, 한 번에 하나씩 | | **근거를 재려면** | 이 실험대가 문서에 남기려고 쓴 긴 형태. 평소에는 필요 없다 | 예를 들어 nginx 에러 로그가 잘렸을 때, 실무자는 잘린 걸 보고 access 로그로 넘어간다. 길이를 재서 2048인지 확인하는 것은 **몰라서 재는** 것이고, 알면 재지 않는다. 같은 이유로 `curl` 도 두 형태가 있다. ```bash curl -I https://auth.hyeonworks.com/realms/master # 한 번 볼 때 curl -s -o /dev/null -w '%{http_code}\n' # 여러 번 재서 비교할 때 ``` 이 가이드의 **확인**은 값을 대조해야 해서 두 번째 형태를 자주 쓴다. 실제로 터미널에서 눈으로 볼 때는 첫 번째로 충분하다. ## 자리표시자를 두지 않는다 `<토큰>` 처럼 적어 두면 그 값을 어디서 가져오는지가 문서 밖으로 나간다. 이 가이드는 **값을 찾는 명령을 함께 적는다.** ```bash TOKEN=$(ssh kc-lab-1 'sudo cat /var/lib/rancher/k3s/server/node-token') echo "${#TOKEN} 자" # 값이 아니라 길이만 확인한다 ``` 비밀은 길이나 존재 여부만 확인하고 값을 찍지 않는다. 터미널 스크롤백과 화면 공유에 남기 때문이다. ## 어느 기계에서 치는가 이 실험대에는 셸이 네 개 있고, **같은 명령이 어디서 도느냐에 따라 결과가 달라진다.** 그래서 모든 코드 블록 앞에 어디서 치는지를 붙인다. | 표시 | 어느 기계 | 어떻게 들어가나 | |---|---|---| | `[워크스테이션]` | 평소 쓰는 개발 머신 | — | | `[lab host]` | `test-server`. `virsh` 가 도는 곳 | `ssh test-server` | | `[kc-lab-edge]` | 엣지 게스트 — nginx · certbot | `ssh kc-lab-edge` (**lab host 에서만**) | | `[kc-lab-1]` | k3s server 게스트 | `ssh kc-lab-1` (**lab host 에서만**) | | `[kc-lab-2]` | k3s agent 게스트 | `ssh kc-lab-2` (**lab host 에서만**) | **기본은 `[lab host]` 다.** 게스트는 libvirt NAT(`192.168.122.0/24`) 안에 있어서 워크스테이션에서 직접 닿지 않는다. `ssh kc-lab-1` 이라는 별칭도 lab host 의 `~/.ssh/config` 에만 있다. ```bash [워크스테이션] $ ping -c1 192.168.122.11 1 packets transmitted, 0 received, 100% packet loss # 경로가 없다 ``` **게스트 안에 들어가서 다음 단계를 치지 않는다.** 게스트에는 lab host 의 개인키도 `~/.ssh/config` 도 없으므로, 게스트 안에서 `ssh kc-lab-1` 을 치면 이렇게 끝난다. ```bash [kc-lab-1] $ ssh kc-lab-1 'sudo cat /var/lib/rancher/k3s/server/node-token' Host key verification failed. ``` **이 실패가 조용한 이유** — 위 명령을 `TOKEN=$(...)` 로 감싸면 오류는 stderr 로 흘러가고 `TOKEN` 에는 **빈 문자열**이 담긴다. 셸은 아무 불평도 하지 않는다. 그래서 게스트에 로그인한 채 다음 단계를 치면 몇 단계 뒤에 가서야 증상이 나타난다. 그래서 이 가이드는 게스트에 **로그인하지 않고** lab host 에서 `ssh kc-lab-1 '...'` 형태로 원격 실행한다. 셸이 하나뿐이면 「지금 어디 있더라」가 생기지 않는다. ## 순서 앞 단계가 끝나야 다음이 된다. 각 단계 첫머리에 「이 단계가 끝나면」이 있고, 그 상태를 확인하는 명령이 있다. **그것이 통과해야 다음으로 넘어간다.** | 단계 | 무엇을 세우나 | 끝나면 확인되는 것 | |---|---|---| | [00](00-lab-host/) | lab host 가상화 준비 | `virsh list` 가 돈다 | | [01](01-vms/) | VM 세 대 (엣지 + k3s 2노드) | 세 게스트에 SSH 가 붙는다 | | [02](02-k3s/) | k3s server + agent | `kubectl get nodes` 에 둘 다 Ready | | [03](03-nginx/) | 엣지 nginx 라우팅 + 호스트 DNAT | 밖에서 요청이 파드까지 닿는다 | | [04](04-tls/) | Let's Encrypt | `https://` 가 열리고 체인이 4단계 | | [05](05-keycloak/) | Keycloak 2노드 + PostgreSQL | 관리 콘솔 로그인이 된다 | | [06](06-observability/) | Prometheus · Grafana | `vendor_cluster_size` 가 2 | | [experiments](experiments/) | 실험 26건 | 각 실험의 판정 기준 | ## 이 가이드가 검증된 방식 **읽기 전용 확인은 돌아가는 실험대에서 실제로 실행해 출력을 그대로 실었다.** 버전·IP·메모리 같은 값은 지어내지 않았다. **만드는 명령은 다르다.** VM 을 다시 만들거나 k3s 를 다시 깔면 지금 돌고 있는 실험대가 없어지므로, 그 명령들은 **실제로 구축할 때 쓴 것을 그대로 옮겼고** 결과 상태를 확인하는 것으로 대신했다. 어느 쪽인지 각 단계에 표시한다. ## 막혔을 때 각 단계 끝에 **「막히면」** 표가 있다. 거기 적힌 증상은 전부 이 실험대가 실제로 겪은 것이고, 원문은 [`../evidence/`](../evidence/) 에 있다. 지어낸 실패 사례는 없다.