incus-hp1 storage-net 참여 사실 반영 + kr2 multus-shim ETXTBSY 인시던트 기록

- infra-hosts.md: hp1 행 갱신 (이전 "1GbE only" → 2.5G 192.168.205.227, MAC 20:e1:5d:6a:2b:2e, MTU 9000 JF OK), 2.5G 표 hp1 행 추가, NAS NIC 정보(USB cdc_ncm → r8152 RTL8157 chip rev 14 + MAC)로 정확화, 호스트 자원 표에 hp1 추가, SSH 정보 라인에 hp1 접근 한계 명시
- nas-storage.md: K3s 노드 표 3→4 노드로 갱신 (hp1 추가), nodeAffinity 설명 표현 갱신
- history/2026-05-20-kr2-multus-shim-etxtbsy.md: ETXTBSY 데드락 RCA 및 `rm /opt/cni/bin/multus-shim` 회피책 기록
This commit is contained in:
kaffa
2026-05-20 17:10:07 +09:00
parent ba30121962
commit 5be51134c9
3 changed files with 98 additions and 8 deletions

View File

@@ -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` 장시간 (1629h): 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-<crashing-pod> --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 공식: <https://github.com/k8snetworkplumbingwg/multus-cni>

View File

@@ -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)과 동일하게 통일.

View File

@@ -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 설치 명령