diff --git a/history/2026-05-20-kr2-multus-shim-etxtbsy.md b/history/2026-05-20-kr2-multus-shim-etxtbsy.md new file mode 100644 index 0000000..a7d2c37 --- /dev/null +++ b/history/2026-05-20-kr2-multus-shim-etxtbsy.md @@ -0,0 +1,85 @@ +--- +date: 2026-05-20 +topic: kr2 multus-shim ETXTBSY 데드락 — k3s 재시작 후 CNI 복구 불가 +areas: [infra/compute/infra-hosts, infra/platform] +--- + +# 2026-05-20 / kr2 multus-shim ETXTBSY 데드락 + +## 증상 + +`/sc:test` 와 무관, NAS NFS 점검 중 발견. kr2 노드는 K8s `Ready` 인데 노드 위 Pod 8개가 stuck: + +- `Unknown`: traefik, kube-multus-ds, kube-system/descheduler, vector, longhorn-manager / longhorn-csi-plugin / engine-image +- `ContainerCreating` 장시간 (16–29h): critical-backup, critical-snapshot, descheduler + +`kubelet` 에러: + +``` +plugin type="multus-shim" name="multus-cni-network" failed (add): +CmdAdd (shim): timed out waiting for the condition +``` + +## 데드락 구조 + +1. 2026-05-19 11:11:59 KST kr2 `k3s.service` 재시작 직후 `kube-multus-ds` Pod이 init 단계에서 깨끗하게 복구 안 됨. +2. `install-multus-binary` initContainer 가 `cp` 로 `/host/opt/cni/bin/multus-shim` 갱신 시도 → `cp: cannot create regular file '/host/opt/cni/bin/multus-shim': Text file busy` (**ETXTBSY**). +3. ETXTBSY 원인: kubelet 이 stuck Pod sandbox 재생성 시도 → `/opt/cni/bin/multus-shim` 을 자식 프로세스로 spawn → multus daemon socket 부재로 RPC hang → shim 프로세스가 inode 잡은 채로 매달림. +4. shim 누적 (관찰 시 8 → 14 → 매달림 지속). cp 는 영원히 fail. multus daemon 영원히 안 뜸. **완전한 데드락.** +5. `pkill -9 multus-shim`, `fuser -k` 모두 즉시 새 shim 이 spawn 되어 효과 없음. `systemctl restart k3s` 도 마찬가지 — 재시작 후 kubelet 이 sandbox cleanup retry 하면서 shim 다시 누적. + +## 해결 키 + +```bash +sudo rm /opt/cni/bin/multus-shim +``` + +`unlink(2)` 는 매달린 프로세스의 fd 가 잡고 있는 inode 를 보존한 채 path 만 제거. 다음 `install-multus-binary` retry 의 `cp` 는 **fresh inode** 로 새 파일 생성 → ETXTBSY 회피 → multus daemon 정상 기동 → 매달린 shim 들이 응답 받고 자연 종료. + +## 복구 절차 (실제 수행) + +```bash +# 1. stuck pod force delete (kubelet retry 루프 끊기) +kubectl delete pod --force --grace-period=0 -n kube-system descheduler-* traefik-* +kubectl delete pod --force --grace-period=0 -n logging vector-* +kubectl delete pod --force --grace-period=0 -n longhorn-system \ + critical-{backup,snapshot}-* engine-image-* longhorn-{csi-plugin,manager}-* + +# 2. kr2 호스트에서 multus-shim 파일 unlink (핵심) +ssh kaffa@kr2 'sudo rm /opt/cni/bin/multus-shim' + +# 3. multus DS pod 재생성 → backoff 카운터 리셋 +kubectl delete pod -n kube-system kube-multus-ds- --force --grace-period=0 +``` + +3분 내 모든 stuck Pod 정상화. 잔여 shim 0개 자동 정리. instance-manager 등 cascade로 띄워지는 Pod도 자동 복구. + +## 검증 + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system kube-multus-ds-9lxxn 1/1 Running 0 29s +kube-system traefik-kjts5 1/1 Running 0 3m10s +kube-system descheduler-... 0/1 Completed 0 3m10s +logging vector-rc6ph 1/1 Running 0 3m9s +longhorn-system engine-image-... 1/1 Running 0 3m9s +longhorn-system instance-manager-... 1/1 Running 0 43s +longhorn-system longhorn-csi-plugin-* 3/3 Running 0 3m9s +longhorn-system longhorn-manager-* 2/2 Running 0 3m9s +longhorn-system critical-snapshot-* 0/1 Completed 0 3m8s +``` + +전 클러스터 비정상 Pod 0개. 4 노드 모두 Ready. + +## 교훈 + +- **ETXTBSY 데드락 패턴**: CNI plugin daemon이 정상 socket을 listen하지 않으면 kubelet retry가 shim을 누적 spawn → 바이너리 갱신 불가. 같은 패턴은 calico, cilium 등 다른 CNI 에서도 발생 가능. +- **`rm` 으로 unlink → fresh inode** 가 표준 회피책. `pkill` / `fuser -k` / 데몬 재시작 모두 retry 루프 못 끊음. +- **재발 방지**: kr2 k3s 재시작 시 `kube-multus-ds` 가 다시 init 단계에서 깨질 수 있음. 재시작 직후 60초 안에 multus DS Pod 상태 확인하고 backoff 회수가 빠르게 늘면 즉시 위 절차 적용. +- 발견 경위: NAS NFS 연결 점검 중 `kubectl get pods -A` 부수 확인에서 우연히 노출. NFS 점검과 인과 무관. + +## 관련 문서 + +- [[infra-hosts]] — K3s 4 노드 구성 (kr1, kr2, hp1, hp2) +- [[longhorn]] — instance-manager / engine-image / manager / csi-plugin DS 구조 +- multus CNI 공식: diff --git a/infra/compute/infra-hosts.md b/infra/compute/infra-hosts.md index 537bc93..a7d3b90 100644 --- a/infra/compute/infra-hosts.md +++ b/infra/compute/infra-hosts.md @@ -3,12 +3,13 @@ title: 인프라 호스트 및 네트워크 updated: - 2026-05-04 incus-kr2 GRUB `iommu=pt` 적용 (AMD-Vi Completion-Wait timeout 차단) - 2026-05-14 K3s 4노드 patch 업그레이드 v1.34.5+k3s1 → v1.34.7+k3s1 (containerd 2.1.5 → 2.2.3) + - 2026-05-20 incus-hp1 storage-net 2.5G 참여 사실 확인 (192.168.205.227, MAC 20:e1:5d:6a:2b:2e, MTU 9000 JF OK) — 이전 표기 "1GbE only" 수정 tags: [infra, network, kr-zone, openwrt] --- ## SSH 접속 정보 -인프라 호스트 SSH 접속 정보: incus-jp1 (공인 42.125.196.116, Tailscale 100.109.123.1), incus-kr1 (공인 220.120.65.245, Tailscale 100.84.111.28), incus-hp2 (Tailscale 100.100.52.34), osaka(gw) (ssh root@100.108.39.107, 공인 172.233.93.180), Synology NAS (SSH 불가, Tailscale 100.126.100.82) +인프라 호스트 SSH 접속 정보: incus-jp1 (공인 42.125.196.116, Tailscale 100.109.123.1), incus-kr1 (공인 220.120.65.245, Tailscale 100.84.111.28), incus-hp1 (LAN 192.168.9.227 only, **Tailscale 미설치 + kappa 키 미배포 → 호스트 직접 SSH 불가**, K3s API 경유만 가능), incus-hp2 (Tailscale 100.100.52.34), osaka(gw) (ssh root@100.108.39.107, 공인 172.233.93.180), Synology NAS (SSH 불가, Tailscale 100.126.100.82) ## 서버 상세 @@ -18,7 +19,7 @@ tags: [infra, network, kr-zone, openwrt] | incus-jp1 | 100.109.123.1 | Incus 호스트 (도쿄) | agents, db, default, monitoring 프로젝트 | | incus-kr1 | 100.84.111.28 | Incus+K3s 호스트 (서울) | GTX 1080 Ti, K3s control-plane (LAN 192.168.9.214), default 프로젝트 | | incus-kr2 | 100.119.109.41 | [[incus-kr2\|Incus+K3s 호스트 (서울)]] | **AMD Ryzen 9 6900HX, 30 GiB RAM, Bosgame mini PC**, K3s control-plane (LAN 192.168.9.135), default, inbest 프로젝트, GRUB `iommu=pt` (AMD-Vi hang 차단, [[2026-05-04-amd-iommu-freeze]]), Tapo 스마트플러그 OOB | -| incus-hp1 | — | Incus+K3s 호스트 (서울) | **HP ProLiant DL360p Gen8** 베어메탈, Xeon E5-2670 32코어, 188GB RAM, K3s worker/k3s-agent (LAN 192.168.9.227), 1GbE only (2.5G 미탑재), Tailscale 미설치, default 프로젝트, 2026-04-16 신규 | +| incus-hp1 | — | Incus+K3s 호스트 (서울) | **HP ProLiant DL360p Gen8** 베어메탈, Xeon E5-2670 32코어, 188GB RAM, Debian 13 trixie kernel 6.12.85, K3s worker/k3s-agent (LAN 192.168.9.227), **storage-net 192.168.205.227 (MAC 20:e1:5d:6a:2b:2e, MTU 9000 JF 검증 2026-05-20)**, Tailscale 미설치 + kappa SSH 키 미배포 (호스트 직접 접근 불가, K3s API 경유만), 2026-04-16 신규 | | incus-hp2 | 100.100.52.34 | Incus+K3s 호스트 (서울) | **HP ProLiant DL360p Gen8** 베어메탈, Xeon E5-2670 32코어, 188GB RAM, 커널 6.12.74+deb13+1 (2026-04-14 업데이트), K3s worker/k3s-agent (LAN 192.168.9.134), default, inbest 프로젝트 | | openwrt-gw | 100.66.60.66 | **OpenWrt 라우터 (서울, critical)** | HAProxy: 80/443 → MetalLB Traefik(192.168.9.53:80/443), 9080/9443 → MetalLB APISIX(192.168.9.50:80/443), **5432 → Patroni PostgreSQL Leader (K3s kine 데이터스토어 진입점, [[postgresql-ha]] 참조)**. 이 노드 다운 시 K3s API/HTTP 진입 모두 중단 | | zlambda (구 sandbox-tokyo) | 100.78.51.18 | [[zlambda|NixOS 베이스 호스트]] (도쿄, Linode `zlambda`) | NixOS 25.05 (Warbler), 공인 139.162.71.52, sshd+tailscale+docker, 2026-04-08 Debian→NixOS 전환 (이전 APISIX/etcd/microsocks/tlsproxy/vault-prod/wg-easy 모두 제거됨), Linode 프로필 kernel=`linode/direct-disk`, BBR+fq+sysctl 튜닝, configuration: Gitea [`kaffa/nixos-infra`](https://gitea.inouter.com/kaffa/nixos-infra) (kaffa-macmini `~/nixos-infra/`, zlambda `/root/nixos-infra/`) | @@ -232,7 +233,7 @@ db (proxysql, pgcat), kroki, mq (RabbitmqCluster CR), openmemory (mcp/ui/qdrant) 스토리지 풀: jp1=`btrfs-pool` (btrfs, /dev/sda1 268G/109G used), kr1=`default` (dir, NVMe 937G/115G used), kr2=`default` (dir, NVMe 937G/115G used), hp2=`default` (btrfs, `/dev/mapper/pve-root` 126G/63G used — Proxmox 잔재 LVM 레이아웃). -호스트 자원: jp1=Xeon E5-2670 32core/31GiB, kr1=28core/62GiB+GTX 1080 Ti, kr2=Ryzen 9 6900HX 16core/30GiB, hp2=Xeon E5-2670 32core/188GiB. +호스트 자원: jp1=Xeon E5-2670 32core/31GiB, kr1=28core/62GiB+GTX 1080 Ti, kr2=Ryzen 9 6900HX 16core/30GiB, hp1=Xeon E5-2670 32core/188GiB (DL360p Gen8 추정, hp2와 동일 스펙), hp2=Xeon E5-2670 32core/188GiB. hp1 incus 사용 여부 미확인 (호스트 SSH 불가). ### jp1 컨테이너 @@ -302,7 +303,7 @@ Docker: `--runtime=nvidia` 또는 `--gpus all`로 GPU 사용. Podman: CDI 방식 └── OpenWrt 라우터 (공인 IP: 220.120.65.245, 내부: 192.168.9.1) ├── incus-kr1 (192.168.9.214) ← K3s control-plane ├── incus-kr2 (192.168.9.135, br-uplink 고정) ← K3s control-plane - ├── incus-hp1 (192.168.9.227, 1GbE) ← K3s worker (k3s-agent) + ├── incus-hp1 (192.168.9.227, 2.5G storage-net 192.168.205.227) ← K3s worker (k3s-agent) └── incus-hp2 (192.168.9.134) ← K3s worker (k3s-agent) 외부 트래픽 흐름 (TCP): @@ -345,8 +346,9 @@ Docker: `--runtime=nvidia` 또는 `--gpus all`로 GPU 사용. Podman: CDI 방식 |--------|-----|-----|---------|-----| | kr1 | enp7s0 (Realtek RTL8125 PCIe) | b8:fb:b3:c6:07:cf | 192.168.205.214 | 9000 | | kr2 | enx803f5dd34c9f (USB r8152) | 80:3f:5d:d3:4c:9f | 192.168.205.135 | 9000 | +| hp1 | (NIC명 미확인, 호스트 SSH 불가) | 20:e1:5d:6a:2b:2e | 192.168.205.227 | 9000 (JF OK 2026-05-20) | | hp2 | ens2 (Realtek RTL8125 PCIe) | b8:fb:b3:c6:06:f0 | 192.168.205.134 | 9000 | -| NAS | USB cdc_ncm | - | 192.168.205.100 | 9000 | +| NAS | eth2 (USB r8152, RTL8157 chip rev 14) | c8:4d:44:27:a9:63 | 192.168.205.100 | 9000 | 마지막 옥텟은 1G LAN(192.168.9.x)과 동일하게 통일. diff --git a/infra/data/nas-storage.md b/infra/data/nas-storage.md index 6bf14fd..86794c5 100644 --- a/infra/data/nas-storage.md +++ b/infra/data/nas-storage.md @@ -1,6 +1,8 @@ --- title: NAS StorageClass (NFS + iSCSI) -updated: 2026-05-20 eth2 USB 2.5GbE 카드 교체 반영 (rev 17 → rev 14, USB 4-1 → 2-2, 라인레이트 재검증) +updated: + - 2026-05-20 eth2 USB 2.5GbE 카드 교체 반영 (rev 17 → rev 14, USB 4-1 → 2-2, 라인레이트 재검증) + - 2026-05-20 K3s 노드 표 4 노드로 갱신 (hp1 storage-net 192.168.205.227 참여 확인) tags: [infra, k3s, storage, nfs, iscsi, synology] --- @@ -19,12 +21,13 @@ Synology NAS(DS916+)를 K3s NFS/iSCSI StorageClass로 사용. Longhorn(로컬 | NFS export | `/volume1/k3s-nfs` | | NFS 옵션 | `rw,async,no_wdelay,crossmnt,no_root_squash,insecure_locks,sec=sys,anonuid=1025,anongid=100` | -K3s 노드는 모두 192.168.205.0/24 서브넷에 참여하고 있음 (2026-04-14 검증): +K3s 노드는 4 노드 모두 192.168.205.0/24 서브넷에 참여하고 있음 (kr1/kr2/hp2 2026-04-14 검증, hp1 2026-05-20 확인): | 노드 | 출구 NIC | src IP | |------|---------|--------| | incus-kr1 | enp7s0 (PCIe 2.5G) | 192.168.205.214 | | incus-kr2 | enx803f5dd34c9f (USB 2.5G) | 192.168.205.135 | +| incus-hp1 | NIC명 미확인 (호스트 SSH 불가, MAC 20:e1:5d:6a:2b:2e) | 192.168.205.227 | | incus-hp2 | ens2 | 192.168.205.134 | ## K3s 설정 @@ -37,7 +40,7 @@ K3s 노드는 모두 192.168.205.0/24 서브넷에 참여하고 있음 (2026-04- | NFS 경로 | `/volume1/k3s-nfs` | | 마운트 옵션 | `soft,timeo=50,retrans=3` | | archiveOnDelete | true (PVC 삭제 시 데이터 archived- 접두사로 보존) | -| nodeAffinity | **없음 (제약 없이 배포)** — 2026-04-14 기준 Deployment에 nodeSelector/affinity 미설정. 3 노드(kr1/kr2/hp2) 전부 192.168.205.0/24 도달 가능해 스케줄 자유 | +| nodeAffinity | **없음 (제약 없이 배포)** — 2026-04-14 기준 Deployment에 nodeSelector/affinity 미설정. 4 노드(kr1/kr2/hp1/hp2) 전부 192.168.205.0/24 도달 가능해 스케줄 자유 | ### Helm 설치 명령