제 홈랩 미니 PC 5대는 성능보다 조용함이 먼저입니다. 거실에서 팬 소리가 들리면 안 되니까, 부팅할 때 cron으로 CPU 전력 제한(RAPL PL1)을 28W에 묶어두고 씁니다. 그런데 그중 한 대(pve3)만 유독 느리고, 유독 뜨겁고, 가끔 멈추기까지 했습니다.
“28W로 묶었으니 조용한 대신 좀 느린 거겠지” 하고 넘겼던 게 실수였습니다. 같은 CPU를 쓰는 노드들과 나란히 놓고 재보니 이건 설정 문제가 아니라 고장이었습니다. 이번 글은 그걸 숫자로 찾아내고, 고칠 때까지 버틴 기록입니다.
(지난 글에서 Immich GPU 부하 때의 pve3 온도를 잠깐 다뤘는데, 이번엔 CPU 쪽 전체 과정입니다. 같은 노드의 메모리, VFIO 이야기도 그 글에 보탰습니다.)
🧭 환경
- 미니 PC 5대(pve1~5), CPU는 전부 Intel Core Ultra 5 235H (Arrow Lake-H, 기본 전력 28W, 최대 4.8GHz)
- Proxmox + Ceph OSD/MDS + 노드마다 Kubernetes 워커 VM
- 원칙: 전력 제한은 쓰로틀링을 없앨 때만 내린다. 올리는 건 직접 소리를 들어보면서 내가 한다.
📊 1단계: 같은 CPU끼리 나란히 놓고 보기
세 노드를 같은 28W 제한에서 동시에 쟀습니다.
| pve1 | pve2 | pve3 | |
|---|---|---|---|
| 패키지 온도 | 65°C | 71°C | 91°C |
| core 쓰로틀 누적 | 15,291 | 0 | 408,250 |
| 패키지 쓰로틀 | 801회 / 1.8초 | 0 | 35,698회 / 395초 |
| 현재 패키지 전력 | 28.00W (제한에 닿음) | 25.91W | 21.09W |
pve3는 전력을 덜 쓰면서 더 뜨겁습니다. 4.8GHz CPU가 1.2~1.4GHz로 돌고 있었고요. 전력 제한이 막고 있는 거라면 전력이 28W에 붙어 있어야 합니다. 그런데 21W에서 멈춰 있다는 건 열이 전력보다 먼저 성능을 막고 있다는 뜻입니다. 이 시점에서 “설정을 더 낮춰야 하나”가 아니라 “열이 안 빠지는구나”로 질문이 바뀌었습니다.
🌡️ 2단계: 105°C라고 써 있지만 실제로는 85°C
sensors는 CPU 한계를 105°C로 보여줍니다. 그런데 85°C 근처부터 쓰로틀이 걸리고 있었습니다. MSR을 직접 읽어보니 이유가 있었습니다.
MSR 0x1A2 (TEMPERATURE_TARGET) = 0x94690000
→ TjMax 105°C, TCC offset 20, 잠김(lock)
→ 실제 쓰로틀 시작점 = 105 - 20 = 85°CBIOS가 TCC offset 20을 걸고 잠가둔 겁니다. 그래서 목표 온도를 이렇게 잡았습니다. 24시간 도는 미니 PC 기준으로 장시간 부하 78°C 이하, 즉 실제 쓰로틀 시작점에서 7°C 여유입니다. 그리고 MSR 0x64F(perf limit reasons)로 지금 걸린 제한이 전력(PL1) 때문인지 열(THERMAL, RATL) 때문인지 구분했습니다. pve3는 평소에도 RATL(평균 온도 제한)이 켜져 있었습니다.
🧪 3단계: PL1과 PL2를 따로 재는 시험 만들기
풀로드만 걸면 장기 제한(PL1)만 드러나고, 단기 제한(PL2)의 효과는 안 보입니다. 그래서 부하를 세 종류로 나눈 스크립트를 만들었습니다.
| 모드 | 부하 | 보는 것 |
|---|---|---|
| steady | 전 스레드 풀로드 10분 | PL1의 안정 온도 |
| burst | 15초 부하 / 15초 휴식 반복 | PL2가 만드는 순간 온도 |
| natural | 부하 없이 실제 운영 부하만 | 설정의 실제 효과 |
운영 중인 클러스터라 안전장치를 넣었습니다.
- 한 번에 한 노드만, Ceph 상태를 확인하고 시작
- 끝나든 중단되든 원래 전력 제한을 자동 복구
- CPU 92°C가 3초 이어지거나 NVMe가 70°C에 닿으면 즉시 중단
pltest.sh <natural|steady|burst> PL1 PL2 초💀 4단계: 열어보니 팬이 안 돌고 있었다
5대 전부 PL1을 바꿔가며 돌려봤습니다. pve4는 20W에서 쓰로틀이 0, pve1은 가끔 버스트 스파이크 정도였는데 pve3만 처참했습니다.
| pve3 (실부하) | 최고 온도 | 10분당 쓰로틀 (core / pkg) |
|---|---|---|
| 28W | 105°C | 7,633 / 652 |
| 16W | 81°C | 61 / 6 |
일단 PL1을 16W로 내려 서비스를 지키고, 서멀 재도포를 하려고 분해했습니다. 그런데 CPU 팬이 아예 안 돌고 있었습니다. ㅠㅠ 팬이 죽은 채로 방열판 자연 대류만으로 버티고 있었던 겁니다. 케이스를 열어둔 상태로 팬이 올 때까지 16W로 지냈습니다.
🎚️ 5단계: 팬 위치를 손본 뒤 다시 찾은 값
임시로 팬을 다시 달고 위치를 조정한 뒤 같은 시험을 다시 돌렸습니다. PL1은 10분 풀로드 결과입니다.
| PL1 | 10분 뒤 온도 | 클럭 |
|---|---|---|
| 22W | 75.0°C | 769 MHz |
| 23W | 77.5°C | 908 MHz |
| 25W | 81.0°C | 1,175 MHz |
| 28W | 6분 만에 85°C, 계속 상승 | 1,530 MHz |
PL2는 PL1 23W에 두고 burst로 쟀습니다.
| PL2 | 결과 |
|---|---|
| 30W | 이유 모를 85~88°C 튐 2회 |
| 35W | 두 번 다 깨끗 (최고 81~84°C, 85°C 이상 0초) |
| 40W | 100°C, core 쓰로틀 38회 |
30W가 35W보다 나빴던 건 끝까지 설명을 못 했습니다. 두 번 반복해서 같은 결과라 35W로 정했습니다.
⚡ 6단계: 1초짜리 103°C는 PL2가 아니라 최대 클럭 탓
23W/35W로 맞춘 뒤에도 평소 부하에서 1초짜리 90~103°C 스파이크가 가끔 찍혔습니다. PL2를 낮춰도 안 없어졌습니다. 범인은 단일 코어가 최대 클럭(4.8GHz)으로 부스트할 때 생기는 핫스팟이었습니다. 전체 전력은 작아도 코어 하나에 열이 몰리는 거죠.
P코어 두 개에 고정한 부하를 반복하면서 최대 클럭만 바꿔봤습니다.
| 최대 클럭 | 최고 온도 |
|---|---|
| 상한 없음 (4.8GHz) | 88~92°C |
| 4.0GHz | 90°C (효과 없음) |
| 3.5GHz | 85°C |
| 3.0GHz | 81°C |
3.0GHz로 잘랐습니다. 대가는 짧은 단일 스레드 작업이 최대 37% 느려지는 겁니다. 반대로 23W로 장시간 돌릴 땐 어차피 0.9GHz 근처라 상한이 영향을 주지 않습니다.
# /etc/cron.d/reboot 에 PL1, PL2 와 같은 줄로
for p in /sys/devices/system/cpu/cpufreq/policy*; echo 3000000 > $p/scaling_max_freq; end이 설정으로 pve3는 CPU, GPU, 실제 Immich 부하 모두에서 78°C 이하, 쓰로틀 0회를 지켰습니다. 10분당 7,633회였던 게 0회가 됐고, 풀로드 클럭은 416~497MHz에서 908MHz로 두 배가 됐습니다.
🌀 마지막: Noctua 팬으로 바꾸고 원래 값으로
새 팬(Noctua)이 와서 교체한 뒤 원래 설계 전력인 28W로 다시 쟀습니다.
| 팬 위치 조정 상태 | Noctua 교체 후 | |
|---|---|---|
| 28W 풀로드 | 6분 만에 85°C, 계속 상승 | 10분 내내 72.7°C로 평탄 |
| 클럭 | 1,530 MHz (곧 쓰로틀) | 1,549 MHz |
| 쓰로틀 | 발생 | 0회 |
같은 28W에서 온도가 약 12°C 내려갔습니다. 그래서 지금은 원래대로 PL1 28W / PL2 55W, 클럭 상한 해제 상태입니다. 23W/35W/3.0GHz는 팬이 없던 시절을 버티게 해준 임시 설정이었던 셈이죠. 28W 위로 올리는 시험은 하지 않았습니다. 지금도 충분히 조용하고, 그 정도면 됐습니다. ㅎㅎ
🐶 덤: 멈춘 채로 아무도 깨워주지 않을 때를 위해
팬 문제와 같은 시기에 pve3가 로그 한 줄 없이 36분 동안 멈춘 일이 있었습니다. 보통은 HA가 켜둔 softdog 워치독이 재부팅을 해줘야 하는데, 커널 타이머까지 같이 죽어서 softdog도 못 움직였습니다. 결국 집에 가서 전원을 뽑았습니다.
다행히 이 보드에는 칩셋 하드웨어 워치독(iTCO_wdt)이 있었습니다. Proxmox가 기본으로 블랙리스트에 넣어둬서 안 쓰이고 있었을 뿐이죠.
# /etc/default/pve-ha-manager
WATCHDOG_MODULE=iTCO_wdt
# /etc/sysctl.d/kernel_panic.conf
kernel.softlockup_panic = 1
kernel.hardlockup_panic = 1이제 같은 식으로 멈추면 하드웨어가 알아서 리셋합니다. 재부팅 후 wdctl로 Identity가 iTCO_wdt인지 확인하면 됩니다.
📝 정리
- 같은 하드웨어끼리 나란히 재보면 설정 문제와 고장이 갈립니다. 전력은 덜 쓰는데 더 뜨거우면 열이 안 빠지는 겁니다.
- 도구가 보여주는 한계(105°C)를 믿지 말고 MSR을 읽습니다. 실제 쓰로틀 시작점은 85°C였습니다.
- PL1은 풀로드로, PL2는 부하와 휴식을 반복하는 burst로 따로 잽니다.
- 1초짜리 고온 스파이크는 PL2가 아니라 단일 코어 부스트 클럭이 변수입니다. 최대 클럭 상한이 효과적입니다.
- 쿨링이 정상이면 원래 설계 전력으로 돌아갑니다. 낮춘 설정은 버티기용일 뿐입니다.
- 조용함이 목표여도 쓰로틀링은 조용함이 아니라 고장의 신호일 수 있습니다.

답글 남기기