docs(guides): hands-on guides for the seven setup stages
The experiment documents record what was found. These record what to type to
reproduce it, in folders per stage.
Two kinds of command are kept apart. 하기/확인 is what somebody actually types
at a terminal — short, one at a time. 근거를 재려면 is the long measuring form
this lab used to put evidence in a document, marked as not needed day to day.
The same split applies to curl: -I to look once, -w '%{http_code}' only when
comparing across repetitions.
No placeholders. Where a value is needed the command that produces it is
given, and secrets are checked by length rather than printed:
TOKEN=$(ssh kc-lab-1 'sudo cat /var/lib/rancher/k3s/server/node-token')
echo "${#TOKEN} 자"
Stage 05 verifies resources in layers, because a Secret existing and a pod
having received it are different facts: keys, then length, then the value
inside the container, then which env var came from which Secret. Same for
workloads — Deployment to ReplicaSet to Pod, with the seven ReplicaSets this
cluster actually carries as the worked example.
Two commands were wrong and re-running them caught it. kubectl get endpoints
prints a deprecation warning on v1.33+, so the guide uses describe svc and
EndpointSlice. And the Keycloak image has no curl, so reading metrics from
inside the container fails with exit 127 — the guide asks Prometheus instead,
or runs a throwaway curl pod.
Read-only checks were executed against the running lab and their output is
quoted verbatim. Creating commands could not be re-run without destroying the
lab, so they are the ones used at build time; the README says which is which.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cdac9b8178
commit
88b7bd4bf0
@@ -0,0 +1,170 @@
|
||||
# 03 — 호스트 nginx 라우팅
|
||||
|
||||
## 이 단계가 끝나면
|
||||
|
||||
밖에서 보낸 요청이 **nginx → Traefik → 파드**로 닿는다. 아직 TLS 는 없다.
|
||||
|
||||
## 전제
|
||||
|
||||
[02](../02-k3s/) 가 끝나 두 노드가 `Ready`.
|
||||
|
||||
## 왜 프록시가 두 겹인가
|
||||
|
||||
nginx 와 Traefik 이 하는 일이 다르다.
|
||||
|
||||
| | 맡는 것 |
|
||||
|---|---|
|
||||
| 호스트 nginx | 바깥세상과의 접점 — TLS 종단 · 인증서 · `X-Forwarded-*` |
|
||||
| Traefik | 클러스터 안의 동적 라우팅 — Ingress 를 보고 서비스를 고른다 |
|
||||
|
||||
**이 2홉이 운영 구조와 같다는 것이 이 배치의 핵심**이고, 동시에 B-4 의 헤더
|
||||
실험이 성립하는 이유다. 1홉을 가정하고 쓴 계약이 2홉에서도 유효한지를
|
||||
재려면 두 겹이 있어야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 설정을 쓴다
|
||||
|
||||
원본은 [`deploy/lab/host/nginx-keycloak-lab.conf`](../../../deploy/lab/host/nginx-keycloak-lab.conf).
|
||||
|
||||
**하기**
|
||||
```bash
|
||||
sudo tee /etc/nginx/sites-available/keycloak-lab > /dev/null <<'EOF'
|
||||
upstream k3s_traefik {
|
||||
server 192.168.122.11:80;
|
||||
server 192.168.122.12:80;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl default_server;
|
||||
http2 on;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/auth.hyeonworks.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/auth.hyeonworks.com/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
location / {
|
||||
proxy_pass http://k3s_traefik;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Port 443;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_read_timeout 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
> **인증서 경로는 아직 없다.** [04](../04-tls/) 에서 만든다. 그전까지는 443
|
||||
> 블록을 주석 처리하고 80 만 `proxy_pass` 로 두면 이 단계를 먼저 확인할 수 있다.
|
||||
|
||||
Arch 는 `sites-available` 관례가 없다. 직접 만들고 `nginx.conf` 의 `http` 블록
|
||||
안에서 include 한다.
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/nginx/sites-{available,enabled}
|
||||
sudo ln -s /etc/nginx/sites-available/keycloak-lab /etc/nginx/sites-enabled/
|
||||
# nginx.conf 의 http { } 안에: include /etc/nginx/sites-enabled/*;
|
||||
```
|
||||
|
||||
## 2. 문법을 보고 적용한다
|
||||
|
||||
**하기**
|
||||
```bash
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
**`&&` 가 중요하다.** 설정이 깨진 상태에서 reload 하면 nginx 가 새 워커를
|
||||
띄우지 못한다. `-t` 를 먼저 통과시키고 그때만 reload 한다.
|
||||
|
||||
## 3. 층별로 확인한다 — 아래에서 위로
|
||||
|
||||
한 번에 밖에서 치지 말고, **가까운 층부터** 본다. 어디서 끊겼는지가 바로 나온다.
|
||||
|
||||
**확인 ①** Traefik 이 듣고 있나 (nginx 를 건너뛴다)
|
||||
```bash
|
||||
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.122.11
|
||||
```
|
||||
```
|
||||
404
|
||||
```
|
||||
|
||||
**`404` 가 성공 신호다.** Traefik 까지 닿았는데 매칭되는 Ingress 규칙이 없다는
|
||||
뜻이다. `502` 나 연결 거부면 그 아래에서 끊긴 것이다.
|
||||
|
||||
**확인 ②** nginx 가 80 에서 리다이렉트하나
|
||||
```bash
|
||||
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://auth.hyeonworks.com
|
||||
```
|
||||
```
|
||||
301 https://auth.hyeonworks.com/
|
||||
```
|
||||
|
||||
**확인 ③** 끝까지 닿나 (TLS 이후)
|
||||
```bash
|
||||
curl -s -o /dev/null -w '%{http_code}\n' https://auth.hyeonworks.com/realms/master
|
||||
```
|
||||
```
|
||||
200
|
||||
```
|
||||
|
||||
## 4. upstream 이 둘인 이유
|
||||
|
||||
```
|
||||
upstream k3s_traefik {
|
||||
server 192.168.122.11:80;
|
||||
server 192.168.122.12:80;
|
||||
}
|
||||
```
|
||||
|
||||
두 노드 모두 Traefik 이 뜨므로 어느 쪽으로 보내도 된다. nginx 는 기본
|
||||
라운드로빈으로 번갈아 보내고, **한쪽이 죽으면 자동으로 뺀다.**
|
||||
|
||||
그 「빼는」 동작이 로그에 이렇게 남는다.
|
||||
|
||||
```
|
||||
connect() failed (113: No route to host) ← 호스트에 못 닿는다
|
||||
connect() failed (111: Connection refused) ← 포트에 아무도 없다
|
||||
no live upstreams ← 둘 다 죽었다고 판단
|
||||
```
|
||||
|
||||
**113 과 111 은 대응이 다르다.** 113 은 네트워크, 111 은 프로세스다.
|
||||
A-4 에서 노드를 잃었을 때 이 세 줄이 1분 안에 순서대로 나왔다.
|
||||
|
||||
---
|
||||
|
||||
## 막히면
|
||||
|
||||
| 증상 | 어디서 끊겼나 | 확인 |
|
||||
|---|---|---|
|
||||
| ① 이 연결 거부 | Traefik 이 안 떴거나 게스트가 죽음 | `kubectl get pods -n kube-system` |
|
||||
| ① 이 `502` | Traefik 은 떴는데 백엔드가 없음 | Ingress 확인 |
|
||||
| ② 가 응답 없음 | nginx 가 안 떴거나 방화벽 | `systemctl status nginx` |
|
||||
| ③ 이 `502` | 인증서 문제 또는 upstream 다운 | [04](../04-tls/) · 아래 로그 |
|
||||
|
||||
**로그를 볼 때** — 실무자가 치는 형태다.
|
||||
```bash
|
||||
journalctl -u nginx -p err -n 5 # 최근 에러만
|
||||
journalctl -u nginx -f # 지금 벌어지는 것
|
||||
```
|
||||
|
||||
**★ nginx 에러 로그는 2048바이트에서 잘린다.** 긴 URL 이 끝에서 단어 중간에
|
||||
끊겨 보이면 그것이다. 되찾으려면 **access 로그를 본다** — 거기엔 제한이 없다.
|
||||
|
||||
```bash
|
||||
grep oauth2/callback /var/log/nginx/access.log | tail -1
|
||||
```
|
||||
|
||||
이 실험대에서 B-7 의 502 원인이 error 로그에 있었는데 잘려 있었고, access
|
||||
로그에는 3492자로 온전히 남아 있었다.
|
||||
Reference in New Issue
Block a user