阿里云 2C2G 的小鸡为什么只有 1.6G内存?
最近在折腾自己的阿里云 2G 小鸡。
一开始只是觉得机器越来越紧张,free -h 看了一眼,发现有点不对劲:
free -h输出大概是这样:
total used free shared buff/cache available
Mem: 1.6Gi 1.4Gi 67Mi 5.6Mi 385Mi 275Mi
Swap: 4.0Gi 0B 4.0Gi这就很奇怪了。
服务器明明是 2G 内存规格,为什么系统里 Mem 的 total 只有 1.6Gi?
一开始我还以为是云厂商的 GB / GiB 口径差异。毕竟 2GB 按十进制换算成 GiB,本来就不是完整的 2GiB。
但这差得还是有点多。
Note
GB 和 GiB 确实不是一回事。2GB 约等于 1.86GiB,但这里系统只显示 1.6GiB,说明还有别的内存被保留了。
先确认系统实际识别到多少内存
先看 /proc/meminfo:
grep MemTotal /proc/meminfo输出:
MemTotal: 1716544 kB换算一下:
1716544 / 1024 / 1024 ≈ 1.64 GiB也就是说,Linux 最终可用的总内存确实只有大约 1.64GiB。
但这还不能说明云厂商真的少给了内存。还需要看看虚拟硬件层到底声明了多少。
继续看 dmidecode:
dmidecode -t memory关键输出如下:
Physical Memory Array
Maximum Capacity: 2 GB
Number Of Devices: 1
Memory Device
Size: 2 GB
Manufacturer: Alibaba Cloud这里可以看到,虚拟硬件层声明的内存设备确实是 2 GB。
所以现在情况变成了:
dmidecode: 2 GB
/proc/meminfo: 1.64 GiB这说明实例规格大概率没错,但 Linux 启动后有一部分内存被预留掉了。
查启动参数
继续看内核启动参数:
cat /proc/cmdline里面有这样一段:
crashkernel=0M-1G:0M,1G-4G:192M,4G-16G:256M,16G-64G:384M,64G-:512M crash_kexec_post_notifiers=1看到 crashkernel 基本就有方向了。
Note
这是给 kdump / crash dump 用的预留内存。简单说,就是系统提前留出一块内存,万一内核崩溃,可以用另一套 crash kernel 把现场 dump 下来,方便后续分析。这在生产环境排查内核崩溃时有用,但对一台 2G 小服务器来说,默认预留 192M 就有点奢侈了。
为什么 2G 最后只剩 1.6G?
大致可以这样理解:
阿里云实例规格:2GB
Linux 启动时识别 System RAM:约 1948MB
crashkernel 预留:192MB
其他 BIOS / ACPI / PCI / 内核 reserved:若干
最终 /proc/meminfo 中 MemTotal:约 1.64GiB少掉的内存主要分成几类:
- GB 和 GiB 的单位差异;
- 虚拟机启动时的 BIOS / ACPI / PCI MMIO 等保留区域;
- 内核自身占用;
crashkernel给 kdump 预留的192MB。
其中最明显、也最容易释放的,就是 crashkernel 这部分。
Note
kdump 不是没用,而是它更适合需要分析内核崩溃的场景。对个人小服务器来说,释放这部分内存通常更实际。
修改 GRUB,关闭 crashkernel
我这台机器是 Debian,配置文件在:
nano /etc/default/grub原本的 GRUB_CMDLINE_LINUX 里包含:
crashkernel=0M-1G:0M,1G-4G:192M,4G-16G:256M,16G-64G:384M,64G-:512M crash_kexec_post_notifiers=1把这两段删掉。
保存后更新 grub:
update-grub确认没有报错,再重启:
rebootWarning
修改 GRUB 前最好确认。如果启动参数写错导致机器起不来,还能从VNC救回来。