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,136 @@
|
||||
# 02 — k3s 두 노드
|
||||
|
||||
## 이 단계가 끝나면
|
||||
|
||||
`kubectl get nodes` 에 두 노드가 `Ready` 로 나온다.
|
||||
|
||||
## 전제
|
||||
|
||||
[01](../01-vms/) 이 끝나 두 게스트에 SSH 가 붙는다.
|
||||
|
||||
---
|
||||
|
||||
## 1. server 를 깐다 (kc-lab-1)
|
||||
|
||||
**하기**
|
||||
```bash
|
||||
ssh kc-lab-1
|
||||
curl -sfL https://get.k3s.io | sudo sh -s - server --node-ip 192.168.122.11
|
||||
```
|
||||
|
||||
`--node-ip` 를 준다. 게스트에 인터페이스가 여럿이면 k3s 가 엉뚱한 것을 고를 수
|
||||
있고, 그러면 두 노드가 서로를 다른 주소로 알게 된다.
|
||||
|
||||
**확인**
|
||||
```bash
|
||||
sudo kubectl get nodes
|
||||
sudo systemctl is-active k3s
|
||||
```
|
||||
|
||||
## 2. 토큰을 꺼낸다
|
||||
|
||||
**하기** — 화면에 찍어 눈으로 옮기지 말고 변수로 받는다
|
||||
```bash
|
||||
TOKEN=$(ssh kc-lab-1 'sudo cat /var/lib/rancher/k3s/server/node-token')
|
||||
echo "${#TOKEN} 자" # 값이 아니라 길이만 확인한다
|
||||
```
|
||||
|
||||
**실측** — 이 실험대에서는 56자였다. 0 이면 server 가 아직 안 떴거나 경로가 다르다.
|
||||
|
||||
## 3. agent 를 붙인다 (kc-lab-2)
|
||||
|
||||
**하기** — 토큰을 그대로 넘긴다
|
||||
```bash
|
||||
ssh kc-lab-2 "curl -sfL https://get.k3s.io | sudo sh -s - agent \
|
||||
--server https://192.168.122.11:6443 \
|
||||
--token '$TOKEN' \
|
||||
--node-ip 192.168.122.12"
|
||||
```
|
||||
|
||||
> 토큰을 셸 히스토리에 남기고 싶지 않으면 파일로 넘긴다.
|
||||
> ```bash
|
||||
> ssh kc-lab-1 'sudo cat /var/lib/rancher/k3s/server/node-token' \
|
||||
> | ssh kc-lab-2 'sudo tee /tmp/token >/dev/null'
|
||||
> ssh kc-lab-2 "curl -sfL https://get.k3s.io | sudo sh -s - agent \
|
||||
> --server https://192.168.122.11:6443 --token-file /tmp/token \
|
||||
> --node-ip 192.168.122.12; rm -f /tmp/token"
|
||||
> ```
|
||||
|
||||
**확인** — server 쪽에서
|
||||
```bash
|
||||
sudo kubectl get nodes -o wide
|
||||
```
|
||||
|
||||
**실측**
|
||||
```
|
||||
kc-lab-1 Ready control-plane v1.36.4+k3s1 192.168.122.11
|
||||
kc-lab-2 Ready <none> v1.36.4+k3s1 192.168.122.12
|
||||
```
|
||||
|
||||
`<none>` 은 오류가 아니라 **역할 라벨이 없다**는 뜻이다. agent 는 원래 그렇다.
|
||||
|
||||
## 4. 유닛 이름이 다르다
|
||||
|
||||
| 노드 | 유닛 |
|
||||
|---|---|
|
||||
| server | `k3s.service` |
|
||||
| agent | `k3s-agent.service` |
|
||||
|
||||
**확인**
|
||||
```bash
|
||||
ssh kc-lab-1 'systemctl cat k3s | grep -A3 ExecStart='
|
||||
ssh kc-lab-2 'systemctl cat k3s-agent | grep -A4 ExecStart='
|
||||
```
|
||||
|
||||
**실측**
|
||||
```
|
||||
ExecStart=/usr/local/bin/k3s server '--node-ip' '192.168.122.11'
|
||||
ExecStart=/usr/local/bin/k3s agent '--node-ip' '192.168.122.12'
|
||||
```
|
||||
|
||||
> 이 차이가 A-4 에서 결과를 갈랐다. server 노드를 잃으면 `kubectl` 자체가
|
||||
> 불통이 되고, agent 를 잃으면 `kubectl` 은 되지만 그 위의 워크로드가 사라진다.
|
||||
|
||||
## 5. k3s 가 기본으로 딸려 오는 것
|
||||
|
||||
따로 설치하지 않아도 이미 있다.
|
||||
|
||||
| | 무엇 |
|
||||
|---|---|
|
||||
| Traefik | 인그레스 컨트롤러. `:80` 을 듣는다 |
|
||||
| servicelb (klipper-lb) | LoadBalancer 타입을 호스트 포트로 매핑 |
|
||||
| local-path | 기본 StorageClass. **노드 로컬 디스크** |
|
||||
| flannel | 파드 네트워크 (VXLAN) |
|
||||
| kube-router | NetworkPolicy 집행 |
|
||||
|
||||
**확인**
|
||||
```bash
|
||||
sudo kubectl get pods -A
|
||||
sudo kubectl get storageclass
|
||||
```
|
||||
|
||||
> `local-path` 가 기본이라는 것이 A-4 에서 비용을 청구한다. PVC 가 **만들어진
|
||||
> 노드에 묶여** 다른 노드로 재배치되지 않는다.
|
||||
|
||||
## 6. 워크스테이션에서 쓰려면
|
||||
|
||||
**하기**
|
||||
```bash
|
||||
ssh kc-lab-1 'sudo cat /etc/rancher/k3s/k3s.yaml' > ~/.kube/kc-lab.yaml
|
||||
sed -i 's|127.0.0.1|192.168.122.11|' ~/.kube/kc-lab.yaml
|
||||
export KUBECONFIG=~/.kube/kc-lab.yaml
|
||||
```
|
||||
|
||||
kubeconfig 안의 서버 주소가 `127.0.0.1` 이다. **게스트 안에서만 맞는 주소**라
|
||||
밖에서 쓰려면 바꿔야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 막히면
|
||||
|
||||
| 증상 | 원인 | 확인 |
|
||||
|---|---|---|
|
||||
| agent 가 `NotReady` | 토큰·주소 오타 | `journalctl -u k3s-agent -n 30` |
|
||||
| 노드 IP 가 예상과 다름 | `--node-ip` 없이 설치 | `kubectl get nodes -o wide` |
|
||||
| 밖에서 kubectl 이 안 붙음 | kubeconfig 의 `127.0.0.1` | 위 6번 |
|
||||
| 파드가 한 노드에만 몰림 | 스케줄러 판단 | `topologySpreadConstraints` 로 강제 |
|
||||
Reference in New Issue
Block a user