AMD-Vi (IOMMU) Completion-Wait timeout 메커니즘 정본 신설

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 문서에 링크
This commit is contained in:
kaffa
2026-05-05 11:47:31 +09:00
parent 35f1e16f09
commit 0a45e0536c
4 changed files with 138 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
---
title: compute 인덱스
updated: 2026-04-16
updated: 2026-05-05
tags: [moc, compute]
---
@@ -9,5 +9,6 @@ tags: [moc, compute]
| 문서 | 설명 |
|------|------|
| [[infra-hosts]] | 인프라 호스트 및 네트워크 (SSH 접속, Incus, Tailscale) |
| [[amd-vi-iommu]] | AMD-Vi (IOMMU) Completion-Wait timeout 부분 hang 메커니즘과 차단 (`iommu=pt`) |
| [[k3s-migration]] | K3s PostgreSQL 백엔드 이전 기록 |
| [[zlambda]] | zlambda Linode 도쿄 NixOS VM |

View File

@@ -0,0 +1,132 @@
---
title: AMD-Vi (IOMMU) Completion-Wait timeout — 부분 hang 메커니즘과 차단
updated: 2026-05-05
tags: [infra, kernel, iommu, amd, freeze, troubleshooting]
---
## 개요
AMD Ryzen 호스트에서 발생하는 IOMMU(AMD-Vi) Completion-Wait timeout으로 인한 호스트 부분 hang 패턴 정본. 처음 만난 사례는 [[2026-05-04-amd-iommu-freeze]] (incus-kr2, Ryzen 9 6900HX). AMD Ryzen 베어메탈을 신규 도입할 때마다 선제 차단(`iommu=pt`)할 것.
## IOMMU(AMD-Vi)가 하는 일
PCIe/USB 디바이스가 메모리에 DMA 할 때 **"디바이스가 보는 주소(IOVA) → 실제 물리 메모리(PA)"** 변환 수행.
- 보안: 디바이스가 임의 메모리 접근 못 하게 격리 (e.g. 악성 USB가 RAM 덤프 못 함)
- 가상화: VFIO passthrough, SR-IOV에 필수
- AMD에서는 `AMD-Vi`, Intel에서는 `Intel VT-d`라 부름. 동일 개념
## 정상 동작
```
1. OS가 페이지 매핑을 바꿀 때마다 IOMMU에 invalidation 명령 전송
→ IOMMU 내부 캐시(IOTLB)를 비우라고
2. 명령은 IOMMU의 Command Queue에 쌓임
3. 끝에 Completion-Wait 명령으로 "여기까지 다 처리됐는지 알려줘" sync
4. OS는 이 응답을 기다림 (1초 내)
```
## 펌웨어 버그 발현 시 흐름
1. 어떤 조건에서 펌웨어/HW가 Completion-Wait 응답을 못 보냄
2. Linux가 1초 후 타임아웃 → `dmesg``AMD-Vi: Completion-Wait loop timed out` 출력
3. **타임아웃이 나면 큐 상태가 inconsistent해져 다음 invalidation도 같은 큐에서 stuck**
4. 새 IO나 새 매핑이 필요한 모든 작업이 IOMMU 응답 대기로 hang
5. 누적될수록 hang하는 작업 범위가 넓어져 결국 호스트 사용자공간 대부분이 부분 hang
## 부분 hang의 특이 패턴 — "왜 일부만 죽는가"
| 영향 받는 작업 | 영향 안 받는 작업 |
|---|---|
| 새 fork (페이지 매핑) | 이미 메모리에 매핑된 프로세스 (예: nginx, node-exporter) |
| 디스크 쓰기 (NVMe DMA 셋업) | ICMP (커널 raw socket, 이미 셋업된 NIC ring buffer) |
| 새 컨테이너 시작 | LXC 컨테이너 내부에서 이미 떠 있는 서비스 |
| sshd login (utmp/journal 쓰기) | 이미 열려있는 SSH 세션 |
| containerd / incus 데몬의 신규 작업 | 라우팅·NAT처럼 커널이 자체 처리하는 트래픽 |
→ 외부에서 보면 "ICMP 응답 OK, nginx 응답 OK, 그런데 SSH banner 직후 끊기고 K3s NotReady"라는 미스터리한 부분 hang. 동시에 OOM/디스크/NIC가 모두 멀쩡 (메트릭상 정상). [[2026-05-04-amd-iommu-freeze]] 참조.
## 영향 받는 하드웨어 / 트리거 조건
- **AMD Ryzen 6000 시리즈 (Rembrandt, Zen 3+)** — 알려진 펌웨어 이슈, 다수 보고 (Linux 메일링리스트, AMD 포럼)
- **AMD Ryzen Mobile / 미니 PC** — BIOS AGESA 업데이트가 늦거나 안 되는 환경에서 더 자주 발현
- 일부 Intel 플랫폼(VT-d)에서도 비슷한 패턴 보고 있으나 본 정본은 AMD 한정
트리거되는 일반 조건:
- DMA 자주 쓰는 디바이스 (NVMe, USB 컨트롤러, 10G NIC) 다수 동시 동작
- VFIO/가상화 + LXC/Docker 같은 컨테이너 동시 동작
- 부팅 후 일정 시간 (사례에서는 24분) 후 첫 timeout, 이후 누적
## 진단 신호
```bash
# 1차 확인 — Completion-Wait timeout 발생 여부
sudo dmesg -T | grep -iE "AMD-Vi.*Completion-Wait|AMD-Vi.*timed out"
# 부분 hang 의심 시 부수 증거
ssh <host> 'echo ok' # banner 직후 끊기면 의심
kubectl get nodes # NotReady, container runtime is down
node_procs_blocked # 0이어도 안전 신호 아님 (IOMMU hang은 D-state 안 거침)
node_memory_* # 정상이어도 안전 신호 아님
```
**핵심 함정**: `node_procs_blocked = 0`, `MemoryPressure = False`, `DiskPressure = False` 다 정상이어도 hang 가능. IOMMU layer는 OS가 노출하는 압박 메트릭에 안 잡힘. **메트릭 정상 + 외부 ICMP 응답 + 새 SSH 거부 조합이면 IOMMU 의심.**
## 차단 옵션
### 1. `iommu=pt` (권장 — Passthrough 모드)
GRUB cmdline에 추가:
```bash
sudo cp /etc/default/grub /etc/default/grub.bak.$(date +%Y%m%d)-iommu
sudo sed -i -E 's/^(GRUB_CMDLINE_LINUX_DEFAULT="[^"]*)(")/\1 iommu=pt\2/' /etc/default/grub
sudo update-grub
sudo systemctl reboot
```
검증:
```bash
cat /proc/cmdline | grep iommu=pt
sudo dmesg | grep "iommu: Default domain type"
# 기대: "iommu: Default domain type: Passthrough (set via kernel command line)"
```
**왜 해결되는가**: `pt` 모드는 **호스트 자신의 DMA에 대해 IOMMU 변환을 1:1 mapping으로 고정** → invalidation 거의 안 씀 → Completion-Wait 자체가 발생하지 않음 → 펌웨어 버그 트리거 안 됨. VFIO/SR-IOV 가상화는 여전히 IOMMU 사용 가능 (격리 유지). 트레이드오프는 호스트 자체 DMA 격리가 약해지는 것 — 베어메탈 + 알려진 디바이스 환경에서는 보통 수용 가능한 비용.
### 2. `amd_iommu=off` (차선)
IOMMU 자체를 비활성. VFIO passthrough 못 함, SEV/Confidential Computing 못 함. 가상화 안 쓰는 호스트면 가능하나 기본 권장 X.
### 3. BIOS AGESA 업데이트 (장기 대책)
펌웨어 fix가 들어간 AGESA 마이크로코드로 업데이트. Mini PC 제조사가 BIOS를 늦게 내거나 안 내면 불가능. 가능할 때 적용.
### 4. 커널 업그레이드
Linux 6.13+에서 일부 우회 패치 머지된 사례 있음. 효과는 트리거 조건에 따라 다름. `iommu=pt`로 먼저 차단하고 부수적으로 검토.
## 운영 규칙 (kappa 인프라)
1. **AMD Ryzen 베어메탈 신규 도입 시 처음부터 GRUB cmdline에 `iommu=pt` 박을 것.** 사고 경험한 다음 적용은 늦음 — 첫 freeze까지 평균 2주 간격.
2. 호스트 문서(`infra/compute/hosts/<name>.md`)의 GRUB 섹션에 `iommu=pt` 표시.
3. 기존 호스트 점검: `ssh <host> 'cat /proc/cmdline'` 해서 `iommu=pt` 없으면 다음 정기 재부팅 시 추가.
4. 시간대 `Asia/Seoul` 강제. 잘못된 timezone(예: PDT)은 dmesg 분석 시 시간 변환 오류로 잘못된 결론 유도 ([[2026-05-04-amd-iommu-freeze]] 헤임달 1차 진단 오판 사례).
5. AMD Ryzen 호스트는 OOB 전원 제어(Tapo 또는 IPMI) 필수. 펌웨어 hang은 OS shutdown으로 못 풀고 강제 전원 차단만 가능.
## 현재 적용 호스트 상태
| 호스트 | CPU | iommu=pt | 비고 |
|---|---|---|---|
| [[incus-kr2]] | AMD Ryzen 9 6900HX | ✓ (2026-05-04) | 본 사건 진원지 |
| [[incus-kr1]] | unknown | — | 점검 필요 |
| [[incus-hp1]] | Intel Xeon E5-2670 | N/A | Intel, AMD-Vi 무관 |
| [[incus-hp2]] | Intel Xeon E5-2670 | N/A | Intel, AMD-Vi 무관 |
## 참조
- [[2026-05-04-amd-iommu-freeze]] — 진단 + 조치 사연
- [[infra-hosts]] — 인프라 호스트 정본
- Linux kernel: `drivers/iommu/amd/iommu.c``__domain_flush_pages`, `iommu_completion_wait`
- AMD I/O Virtualization Technology Specification (IOMMU)

View File

@@ -1,6 +1,6 @@
---
title: incus-kr2
updated: 2026-05-04
updated: 2026-05-05
tags: [infra, host, incus, k3s, seoul, amd, iommu]
type: host
host_kind: server
@@ -39,17 +39,9 @@ Incus + K3s control-plane 호스트 (서울존). Mini PC 폼팩터, AMD Ryzen 9
## 알려진 hang 패턴 — AMD-Vi (IOMMU) Completion-Wait Timeout
호스트 freeze 반복 발생한 근본 원인 (2026-05-04 확정, [[2026-05-04-amd-iommu-freeze]]).
호스트 freeze 반복 근본 원인. 메커니즘 정본은 [[amd-vi-iommu]], 사건 사연은 [[2026-05-04-amd-iommu-freeze]].
**증상**:
- ICMP/이미 매핑된 프로세스(node-exporter, LXC 컨테이너 nginx)는 응답 유지
- containerd, incus 데몬, sshd 새 세션 fork만 동시에 hang
- kubelet `container runtime is down`, `/var/log/pods readdirent: input/output error`
- procs_blocked 0, MemoryPressure False — 자원 고갈 아님
**원인**: AMD Ryzen 6900HX IOMMU(AMD-Vi) Completion-Wait queue stall. `dmesg``AMD-Vi: Completion-Wait loop timed out` 반복 후 누적되어 DMA 의존 디바이스(NVMe, USB 컨트롤러 등)가 stall.
**조치 (2026-05-04 적용)**: GRUB cmdline `iommu=pt` 추가 → IOMMU passthrough 모드. dmesg `iommu: Default domain type: Passthrough` 확인.
요약: AMD Ryzen 6900HX IOMMU의 Completion-Wait queue가 stall되면서 DMA 의존 디바이스(NVMe, USB 컨트롤러 등)가 멈춤 → containerd/incus/sshd login만 죽고 ICMP/이미 매핑된 프로세스(nginx, node-exporter)는 살아남는 부분 hang. 조치: GRUB cmdline `iommu=pt` 추가 (2026-05-04 적용, 17시간 timeout 0건 검증).
**과거 freeze 이력 비교**:
| 일자 | 원인 | 조치 |