incus-kr2 freeze 사건 분석으로 확정된 IOMMU 부분 hang 메커니즘과 운영 규칙(`iommu=pt` 선제 적용)을 별도 reference 문서로 분리. 호스트 사연(history)과 메커니즘(reference)을 분리해 다른 AMD Ryzen 호스트 도입 시 재사용 가능한 정본으로 정리. - infra/compute/amd-vi-iommu.md 신규 (메커니즘 + 차단 + 운영 규칙) - compute _index.md, hosts/incus-kr2.md, history 문서에 링크
4.7 KiB
date, topic, areas, tags
| date | topic | areas | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-05-04 | incus-kr2 AMD-Vi (IOMMU) Completion-Wait timeout 호스트 부분 hang |
|
|
배경
incus-kr2가 약 2주 간격으로 호스트 freeze 재발. 이전 두 사건(2026-04-04-usb-25g-hang USB autosuspend, 2026-04-19 OOM)은 각각 usbcore.autosuspend=-1과 kubelet system-reserved=8Gi로 막은 상태였으나 또 다른 원인으로 hang. Tapo 스마트플러그를 kr2에 연결하여 강제 리부팅 가능하도록 사전 대비된 상태.
인시던트
시각: 2026-05-04 12:36 KST (호스트 시계 PDT로 잘못 설정되어 있어 May 03 20:36 기록 — KST 12:36)
복구: 2026-05-04 12:50 KST 사용자가 Tapo로 강제 리부팅
다운타임: 약 2시간 13분 (10:37 NotReady → 12:50 reboot)
영향: leewell.com 포함 inbest 7 컨테이너 응답 일부만 동작 (LXC 커널 namespace로 nginx는 살아 외부에 nginx 404 반환), K3s 워크로드 일부 Terminating (argocd redis, db pgpool, external-secrets, longhorn csi)
증상 vs 가설 부정 매트릭스
| 가설 | 증거 | 결론 |
|---|---|---|
| NIC (USB r8152 autosuspend) | carrier=1, 다른 노드에서 wget 응답 정상, 평소 트래픽 14~70 B/s | ❌ |
| NFS hard mount D-state | procs_blocked=0 8:43 KST까지 |
❌ |
| OOM | MemoryPressure=False, MemAvailable 23 GiB | ❌ |
| 디스크 hardware | SMART Critical=0, Errors=0, Percentage Used 1% | ❌ |
| AMD IOMMU Completion-Wait | dmesg AMD-Vi: Completion-Wait loop timed out (12:36, 12:46 x2) → 그 직후 hang |
✅ |
진단 핵심
- ICMP/메모리 매핑된 프로세스(node-exporter, nginx)는 응답 유지
- containerd, incus 데몬, sshd 새 세션 fork만 동시에 hang
- kubelet 마지막 이벤트:
failed to read podLogsDirectory "/var/log/pods": readdirent: input/output error(91회 반복) - node-exporter의
up=1은 끊긴 적 없음 — 헤임달 1차 진단 "kr2 호스트 자체 다운 2일 2시간"은 시간대/로그 해석 오류, 실제는 당일 약 2시간 13분 - 이 패턴은 IOMMU가 stall되어 DMA 통하는 디바이스(NVMe, USB 컨트롤러)가 응답 못 하지만 커널 자체와 메모리 매핑된 프로세스는 동작하는 부분 hang의 전형
직접 검증 데이터 (메트릭)
freeze 직전 (08:31~08:44 KST 호스트 시계 기준 — 실제 KST는 +9h가 아니라 호스트 시계가 PDT라서 변환 필요. K3s NotReady transition 기준 10:37:43 KST):
- load1 = 2.22 (정상)
- MemAvailable = 23.13 GiB
procs_blocked= 0nvme0n1io_time fraction = 2%, write 34 IOPS- NVMe 온도 41~42 °C
→ 점진적 자원 고갈 흔적 0. "갑자기 정지" 패턴 = 펌웨어/IOMMU level hang.
재부팅 후 검증
[ 0.641598] iommu: Default domain type: Passthrough (set via kernel command line)
이전 부팅에서 부팅 후 24분 만에 첫 Completion-Wait timeout 발생, 이후 누적되며 hang. iommu=pt 적용 부팅 후 동일 시점 검증 필요.
조치
GRUB cmdline에 iommu=pt 추가:
sudo cp /etc/default/grub /etc/default/grub.bak.20260504-iommu
sudo sed -i -E 's/^(GRUB_CMDLINE_LINUX_DEFAULT="[^"]*)(")/\1 iommu=pt\2/' /etc/default/grub
sudo update-grub
sudo systemctl reboot
적용 후 cmdline:
ro usbcore.autosuspend=-1 quiet iommu=pt
부수 조치:
- 호스트 시간대
America/Los_Angeles→Asia/Seoul수정 (timedatectl set-timezone Asia/Seoul). 이 잘못된 timezone이 헤임달 1차 진단의 "2일 2시간" 오판 원인.
교훈
- AMD Ryzen 미니 PC 베어메탈은 IOMMU passthrough 기본 적용 권장. 직전 부팅 24분 만에 첫 timeout이 떴다는 건 시간 문제로 hang 보장된 상태.
- IOMMU hang은 OOM/디스크/NIC와 다르게 메트릭에 점진적 흔적 안 남고 갑자기 정지.
node_procs_blocked0으로 끝나도 안전 신호 아님. dmesg | grep AMD-Vi가 새 호스트 도입 시 표준 점검 항목.- 호스트 timezone 통일 — 한국 인프라는
Asia/Seoul로 강제. 잘못된 timezone은 인시던트 분석 시 시간대 변환 오류로 잘못된 결론 유도. - 헤임달 1차 진단 "kr2 호스트 자체 다운"은 표면 ssh/incus refused만 보고 결론. 메트릭 시계열·외부 응답까지 교차 검증 안 함. 다음에 비슷한 진단 시 헤임달이 node-exporter
up, 외부 nginx 응답 등을 같이 보도록 운영 규칙 보강 검토.
관련 문서
- amd-vi-iommu — AMD-Vi 부분 hang 메커니즘 정본 (왜 일부 프로세스만 죽는가,
iommu=pt가 왜 해결하는가) - infra/compute/hosts/incus-kr2
- 2026-04-04-usb-25g-hang — 직전 freeze (USB)
- infra/compute/infra-hosts