我的 Homelab 跑在一台迷你主机上:AMD Ryzen 5 5600H(6 核 12 线程,笔记本 U),上面装的是 Proxmox VE,里面只开了一台 K3s 虚拟机。最近摸机箱的时候明显感觉烫手,一查 CPU 温度常驻 72°C,决定好好优化一下。

现状诊断#

先 SSH 上去摸底。我的 Proxmox 宿主机在 Ansible inventory 里已经配好了,直接用 ad-hoc 命令采集信息:

ansible proxmox -m shell -a 'lscpu | grep "Model name"; sensors; free -h; qm list'

诊断结果比我预想得更激进一些:

项目 现状 问题
CPU Governor powersave 已经是省电模式,没问题
Turbo Boost 开启 CPU 频率飙到 3GHz+,主要热源
内存 13GB 物理 / VM 分配 15GB 严重超售,swap 占了 3.9GB
KSM (ksmd) 默认 20ms 扫描间隔,占 5% CPU 因为内存超售疯狂做内存去重
ASPM default PCIe 链路没有启用最省电模式
lm-sensors 未安装 之前甚至没法看温度

三个主要热源很清晰:Turbo Boost 没关VM 内存超售导致 swap 和 KSM 双重 CPU 开销powertop 没做自动调优

优化方案#

1. 减少 VM 内存分配(效果最大)#

对我这台机器来说,这是效果最明显的一步。宿主机只有 13GB 物理内存,VM 却分了 15GB,导致:

  • 3.9GB 数据被挤到 swap,磁盘 I/O 增加
  • KSM 以 20ms 间隔疯狂扫描内存页做去重,吃掉 5% CPU
  • 整体负载 1.71(12 线程的机器不该有这种空载负载)

解决方法:把 VM 内存从 15GB 降到 10GB,给宿主机留 3GB 余量。

Proxmox 不支持在线缩内存(balloon 值为 0),所以需要关机改配置:

# 关机(ACPI shutdown 如果超时就 force stop)
qm shutdown 100
# 如果等不到就强制关
qm stop 100

# 改内存
qm set 100 --memory 10240

# 启动
qm start 100

如果 VM 是用 Terraform 管理的,记得同步更新 terraform.tfvars

vm_memory = 10240    # 10GB (host has 13GB, avoid swap/KSM overhead)

注意:不要用 terraform apply 来改内存,Terraform 会销毁重建 VM,数据会丢。用 qm set 原地改更安全。

2. 禁用 Turbo Boost#

AMD Ryzen 5 5600H 的 Turbo 最高能到 4.28GHz,但我这个 Homelab 场景未必需要这种瞬时爆发。关掉以后 CPU 频率上限降到基频,通常很快就能看到温度变化。

立即生效:

echo 0 > /sys/devices/system/cpu/cpufreq/boost

持久化(创建 systemd service):

# /etc/systemd/system/disable-turbo-boost.service
[Unit]
Description=Disable CPU Turbo Boost
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo 0 > /sys/devices/system/cpu/cpufreq/boost'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
systemctl enable disable-turbo-boost

3. powertop 自动调优#

powertop 能自动把 USB 自动挂起、SATA 链路省电、音频节能等一堆细项全部打开:

# 先看效果
powertop --auto-tune

# 满意了就持久化
cat > /etc/systemd/system/powertop-autotune.service << 'EOF'
[Unit]
Description=PowerTOP auto-tune
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/powertop --auto-tune
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now powertop-autotune

4. 降低 KSM 扫描频率#

即使减了 VM 内存,Proxmox 默认还是会跑 KSM。把扫描间隔从 20ms 调到 200ms,CPU 开销通常也会明显下降:

echo 200 > /sys/kernel/mm/ksm/sleep_millisecs

同样用 systemd service 持久化:

# /etc/systemd/system/ksm-tuning.service
[Unit]
Description=Tune KSM sleep interval
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo 200 > /sys/kernel/mm/ksm/sleep_millisecs'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

5. PCIe ASPM 省电(可选)#

/etc/default/grub 里加入内核参数:

GRUB_CMDLINE_LINUX_DEFAULT="quiet pcie_aspm=powersupersave"

然后 update-grub && reboot

实测:我的 AMD 平台 BIOS 锁定了 ASPM 策略,内核参数传入了但 sysfs 里仍然显示 [default]。如果你的机器也这样,说明要去 BIOS 里改,或者直接跳过这步。

Ansible Playbook 一键搞定#

上面这些手动操作太零散了,我写了一个 Ansible playbook 把所有优化一步到位:

---
- name: Power & thermal optimization
  hosts: proxmox
  tasks:
    - name: Install lm-sensors
      apt:
        name: lm-sensors
        state: present
        update_cache: true

    - name: Read current temperatures
      command: sensors
      register: sensors_before
      changed_when: false

    - name: Show baseline temperatures
      debug:
        var: sensors_before.stdout_lines

    - name: Disable AMD Turbo Boost
      shell: echo 0 > /sys/devices/system/cpu/cpufreq/boost

    - name: Persist turbo boost disable
      copy:
        dest: /etc/systemd/system/disable-turbo-boost.service
        content: |
          [Unit]
          Description=Disable CPU Turbo Boost
          After=multi-user.target
          [Service]
          Type=oneshot
          ExecStart=/bin/sh -c 'echo 0 > /sys/devices/system/cpu/cpufreq/boost'
          RemainAfterExit=yes
          [Install]
          WantedBy=multi-user.target          

    - name: Enable disable-turbo-boost service
      systemd:
        name: disable-turbo-boost
        enabled: true
        daemon_reload: true

    - name: Create powertop auto-tune service
      copy:
        dest: /etc/systemd/system/powertop-autotune.service
        content: |
          [Unit]
          Description=PowerTOP auto-tune
          After=multi-user.target
          [Service]
          Type=oneshot
          ExecStart=/usr/sbin/powertop --auto-tune
          RemainAfterExit=yes
          [Install]
          WantedBy=multi-user.target          

    - name: Enable and start powertop auto-tune
      systemd:
        name: powertop-autotune
        enabled: true
        state: started
        daemon_reload: true

    - name: Slow down KSM scanning
      shell: echo 200 > /sys/kernel/mm/ksm/sleep_millisecs

    - name: Persist KSM tuning
      copy:
        dest: /etc/systemd/system/ksm-tuning.service
        content: |
          [Unit]
          Description=Tune KSM sleep interval
          After=multi-user.target
          [Service]
          Type=oneshot
          ExecStart=/bin/sh -c 'echo 200 > /sys/kernel/mm/ksm/sleep_millisecs'
          RemainAfterExit=yes
          [Install]
          WantedBy=multi-user.target          

    - name: Enable KSM tuning service
      systemd:
        name: ksm-tuning
        enabled: true
        daemon_reload: true

    - name: Set ASPM to powersupersave in GRUB
      lineinfile:
        path: /etc/default/grub
        regexp: '^GRUB_CMDLINE_LINUX_DEFAULT='
        line: 'GRUB_CMDLINE_LINUX_DEFAULT="quiet pcie_aspm=powersupersave"'
        backup: true
      register: grub_updated

    - name: Update GRUB
      command: update-grub
      when: grub_updated.changed

    - name: Read temperatures after optimization
      command: sensors
      register: sensors_after
      changed_when: false

    - name: Show results
      debug:
        var: sensors_after.stdout_lines

跑一下:

ansible-playbook playbooks/power-optimize.yaml

踩坑提醒:sysfs 文件(/sys/devices/...)不能用 Ansible 的 copy 模块写入,会报 Permission denied,因为 copy 会先写临时文件再 rename,但 sysfs 不支持这种操作。必须用 shell 模块直接 echo 写入。

效果#

优化前后对比(负载稳定后测量):

指标 优化前 优化后 改善
CPU 温度 (Tctl) 71.9°C 62°C -10°C
GPU 温度 (edge) 65.0°C 61°C -4°C
NVMe 温度 46.9°C 42.9°C -4°C
系统负载 1.71 0.43 -75%
可用内存 837MB 3.2GB +4x
Swap 使用 3.9GB 0B -100%

最大的收益来自两个地方:

  1. VM 内存从 15GB 降到 10GB — 消除了 swap 和 KSM 的双重 CPU 开销,负载直接砍了 75%
  2. 禁用 Turbo Boost — CPU 频率上限降下来,温度立即下降 5-6°C

截至目前,K3s 集群在 10GB 内存下运行正常,跑了十几个服务也没遇到 OOM。回头看,之前 15GB 更像是拍脑袋给的保守值。

总结#

这次 Homelab 散热优化中,我最后采用的处理顺序如下:

  1. 先查内存是否超售 — 这是比较容易被忽视但影响很大的一步。VM 分配超过物理内存 → swap → KSM → CPU 白干活 → 发热
  2. 关 Turbo Boost — 服务器场景不需要睿频,关了直接降 5°C+
  3. powertop –auto-tune — 一键开启几十项细碎的省电选项
  4. KSM 扫描频率 — 如果还在跑 KSM,把间隔调大
  5. ASPM — 看 BIOS 是否支持,不支持就跳过

全部操作用 Ansible 管理,可重复执行,重启后自动生效。