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>
3.9 KiB
3.9 KiB
02 — k3s 두 노드
이 단계가 끝나면
kubectl get nodes 에 두 노드가 Ready 로 나온다.
전제
01 이 끝나 두 게스트에 SSH 가 붙는다.
1. server 를 깐다 (kc-lab-1)
하기
ssh kc-lab-1
curl -sfL https://get.k3s.io | sudo sh -s - server --node-ip 192.168.122.11
--node-ip 를 준다. 게스트에 인터페이스가 여럿이면 k3s 가 엉뚱한 것을 고를 수
있고, 그러면 두 노드가 서로를 다른 주소로 알게 된다.
확인
sudo kubectl get nodes
sudo systemctl is-active k3s
2. 토큰을 꺼낸다
하기 — 화면에 찍어 눈으로 옮기지 말고 변수로 받는다
TOKEN=$(ssh kc-lab-1 'sudo cat /var/lib/rancher/k3s/server/node-token')
echo "${#TOKEN} 자" # 값이 아니라 길이만 확인한다
실측 — 이 실험대에서는 56자였다. 0 이면 server 가 아직 안 떴거나 경로가 다르다.
3. agent 를 붙인다 (kc-lab-2)
하기 — 토큰을 그대로 넘긴다
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"
토큰을 셸 히스토리에 남기고 싶지 않으면 파일로 넘긴다.
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 쪽에서
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 |
확인
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 집행 |
확인
sudo kubectl get pods -A
sudo kubectl get storageclass
local-path가 기본이라는 것이 A-4 에서 비용을 청구한다. PVC 가 만들어진 노드에 묶여 다른 노드로 재배치되지 않는다.
6. 워크스테이션에서 쓰려면
하기
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 로 강제 |