쿠버네티스 배포판 — 직접 세운다 · Talos Linux · 실습
SSH 로 들어가려는데 셸이 없다
목표
셸도 SSH 도 없는 Talos Linux 노드를 talosctl 과 API 만으로 들여다보고, 머신 설정을 재부팅 없이 바꾸고 되돌리며, 검증이 막는 실수와 막지 못하는 실수를 로그로 구별합니다.
왜 중요한가
k3s·k0s·kubeadm 은 리눅스 위에 쿠버네티스를 설치하는 방식이라, 문제가 생기면 노드에 들어가 로그를 보고 파일을 고치는 습관이 통합니다. Talos 는 OS 자체가 쿠버네티스 전용으로 다시 쓰여 셸·SSH·패키지 관리자가 없고 루트 파일 시스템은 읽기 전용입니다.
대신 노드마다 gRPC API(apid)가 있고, 모든 확인과 변경이 그 API 로 들어가며, 머신 설정은 버전이 붙은 리소스로 남습니다. 이 설계는 "그 노드에만 누가 손댄 설정" 이라는 눈송이 서버를 원천적으로 막는 대신, 들어가서 고치는 응급처치를 불가능하게 합니다.
그래서 운영자는 설정이 검증에서 거절되는 경우와, 검증은 통과했는데 서비스가 죽는 경우를 API 로 읽어 구별할 줄 알아야 합니다. 이 실습은 그 두 경우를 일부러 만들어 봅니다.
단계
1. 컨트롤 플레인 노드 컨테이너 talos-default-controlplane-1 에 docker exec 로 sh 를 실행해 보고, 노드 IP 의 TCP 22번과 50000번이 열려 있는지 확인하세요. 결과를 /root/talos-lab/noshell.json 에 container, node_ip(도커 네트워크 talos-default 의 주소), exec_sh_exit(docker exec 의 종료 코드, 숫자), exec_sh_error(오류 메시지 한 줄), port22_open, port50000_open(불리언)으로 적으세요.
2. talosctl 로 두 노드(컨트롤 플레인 10.5.0.2, 워커 10.5.0.3)의 서비스 목록을 읽어 /root/talos-lab/services.json 에 controlplane, worker(각 노드의 서비스 ID 를 정렬한 배열)와 controlplane_only(컨트롤 플레인에만 있는 서비스 ID 를 정렬한 배열)를 적으세요.
3. talosctl get members 로 멤버를 읽고 /root/talos-lab/members.json 에 talos_version(10.5.0.2 서버의 Talos 태그, 예 v0.0.0 꼴), members(호스트 이름 → {"type": 머신 종류, "addresses": 주소 배열}), worker_mc_version(워커 10.5.0.3 의 MachineConfig 리소스 v1alpha1 의 metadata.version, 숫자)을 적으세요.
4. talosctl kubeconfig 로 컨트롤 플레인(10.5.0.2)에서 kubeconfig 를 받아 /root/talos-lab/kubeconfig 에 저장하고(심볼릭 링크 금지), 그 파일로 kubectl 을 써서 /root/talos-lab/cluster.json 에 api_server(그 kubeconfig 의 server 주소), nodes(노드 이름 → InternalIP), kubelet_version, pod_subnets, service_subnets(컨트롤 플레인 머신 설정의 cluster.network 값), overlaps_host(두 대역 중 하나라도 호스트 클러스터의 10.244.0.0/16 이나 10.96.0.0/12 와 겹치면 true)를 적으세요.
5. /root/talos-lab/05-labels.yaml 에 워커의 machine.nodeLabels 에 lab.talos.dev/pool: blue 를 더하는 strategic merge 패치를 쓰고, 워커(10.5.0.3)에만 --mode=no-reboot 로 적용하세요. 적용 명령의 출력(표준 출력과 오류)을 /root/talos-lab/patch-out.txt 에 저장하고, /root/talos-lab/patch.json 에 node, mc_version_before, mc_version_after(적용 전후 워커 MachineConfig version), container_started_at(워커 컨테이너 talos-default-worker-1 의 State.StartedAt)을 적으세요. 쿠버네티스 Node 에 라벨이 붙어야 합니다.
6. 워커에 라벨 lab.talos.dev/canary: "on" 을 --mode=try --timeout=30s 로 적용하세요. 적용 직후 워커 MachineConfig version 을 읽고, 쿠버네티스 Node 에 라벨이 붙는 것을 확인한 뒤, 되돌아가 라벨이 사라질 때까지 기다려 다시 version 을 읽으세요. /root/talos-lab/try.json 에 timeout_sec(숫자), version_during, seen_on_node(불리언), version_after_revert 를 적으세요. 5단계의 pool 라벨은 남아 있어야 합니다.
7. /root/talos-lab/07-bad.yaml 에 워커 machine.nodeLabels 에 이름이 lab.talos.dev/team name(공백이 든 이름), 값이 platform 인 라벨을 더하는 패치를 쓰고 워커에 적용해 보세요. 출력을 /root/talos-lab/rejected.txt 에 저장하고, 적용 전후 워커 MachineConfig version 을 /root/talos-lab/rejected.json 에 version_before, version_after 로 적으세요.
8. /root/talos-lab/08-kubelet.yaml 에 워커 machine.kubelet.extraArgs 에 max-pod: "150" 을 더하는 패치를 쓰고 워커에 적용하세요. 받아들여진 직후 version 을 읽고, talosctl 로 kubelet 서비스 상태와 로그를 보고 원인을 찾아 /root/talos-lab/kubelet-diag.json 에 accepted_version(적용 직후 워커 MachineConfig version), service_state(그때 본 kubelet 서비스 STATE), error_line(원인이 적힌 로그 한 줄)을 적으세요. 그다음 /root/talos-lab/08-fix.yaml 에 $patch: delete 로 그 인자만 지우는 패치를 써서 적용하고, kubelet 이 건강하고 워커 Node 가 Ready 로 돌아오게 하세요.
9. /root/talos-lab/report.json 에 shell_in_node(불리언), ssh_port_open(불리언), api_port(Talos API 포트 숫자), worker_config_changes(워커 MachineConfig 가 처음 이후 바뀐 횟수 = 지금 version - 1), worker_restarts(워커 컨테이너가 5단계 이후 다시 시작된 횟수), rejected_field(7단계에서 검증에 걸린 설정 경로, 예 machine.x 꼴), broken_service(8단계에서 죽은 서비스 ID), apply_log_line(워커 talosctl logs machined 에서 설정 적용 API 호출이 기록된 한 줄), summary(불변 OS 와 API 기반 관리가 이 실습에서 무엇을 뜻했는지 80자 이상)를 적으세요.
참고
- VM 안에서 도커로 Talos v1.13.10 노드 두 대(컨트롤 플레인 10.5.0.2, 워커 10.5.0.3)가 떠 있습니다. talosconfig 는
/root/.talos/config, kubeconfig 는/root/.kube/config에 이미 있습니다. - 노드 지정:
talosctl -n 10.5.0.3 services—-n을 빼면 "nodes are not set" 류로 실패합니다. - 리소스 읽기:
talosctl -n <ip> get members,talosctl -n <ip> get mc v1alpha1 -o yaml, JSON 은-o json | jq -s - 흔한 실수: JSON6902(op/path) 패치를 넣는 것. 이 클러스터 설정은 여러 문서라 거절됩니다. strategic merge YAML 을 쓰세요.
- 흔한 실수: try 모드를 기다리는 동안 다른 patch 를 넣는 것. 되돌리기가 취소됩니다.
- 이 VM 에서는
talosctl dmesg가 VM 자신의 커널 로그를 보여 줍니다(컨테이너 모드). 서비스 원인은talosctl logs <서비스>에서 찾습니다. - [Docker 에서 Talos 띄우기](https://docs.siderolabs.com/talos/v1.13/platform-specific-installations/local-platforms/docker) · [머신 설정 편집과 적용 모드](https://docs.siderolabs.com/talos/v1.13/configure-your-talos-cluster/system-configuration/editing-machine-configuration) · [설정 패치](https://docs.siderolabs.com/talos/v1.13/configure-your-talos-cluster/system-configuration/patching)
단계 9개
- SSH 로 들어가려는데 셸이 없다
- 셸 대신 무엇이 돌고 있나
- 누가 이 클러스터의 멤버인가
- kubeconfig 도 API 로 받는다
- 재부팅 없이 노드 라벨을 붙인다
- 30초 뒤 저절로 되돌아간 라벨
- 검증이 거절한 패치
- 받아들여졌는데 kubelet 이 죽었다
- 셸 없는 노드를 어떻게 운영했나