一、Hupe Page 定義
在 Linux 中,虛機內存是以頁為單位來管理的。頁的大小為 4KB。 1MB 的內存能劃分為 256 頁; 1GB 則等同于 256000 頁。
CPU 中有一個內置的內存管理單元,用于存儲這些頁的列表(頁表),每頁都有一個對應的入口。
TLB(Translation lookaside buffer)為頁表(存放虛擬地址的頁地址和物理地址的頁地址的映射關系)在CPU內部的高速緩存。TLB的命中率越高,頁表查詢性能就越好。
TLB的一行為一個頁的映射關系,也就是管理了一個頁大小的內存:TLB管理的內存大小 = TLB行數 x 內存的頁大小
同一個CPU的TLB行數固定,因此內存頁越大,管理的內存越大,相同業務場景下的TLB命中率就越高。
如果為服務器分配的內存遠大于現有內存管理單元能管理的量,則會造成內存的浪費。 CentOS 6 中為解決這個問題,使用了大頁面(Huge Page)的方式。
簡單來說,大頁面(Huge Page)即大小為 2MB 或者 1GB 的頁。 2MB 的頁適用于管理 GB 級單位的內存; 1GB 的頁適用于 TB 級單位的內存。
大頁面(Hupe Page)的配置
大頁面配置需要連續的內存空間,因此在開機時就分配是最可靠的方式。配置大頁面的參數有:
- hugepages :在內核中定義了開機啟動時就分配的永久大頁面的數量。默認為 0,即不分配。只有當系統有足夠的連續可用頁時,分配才會成功。由該參數保留的頁不能用于其他用途。
hugepagesz: 在內核中定義了開機啟動時分配的大頁面的大小。可選值為 2MB 和 1GB 。默認是 2MB 。
default_hugepagesz:在內核中定義了開機啟動時分配的大頁面的默認大小。
|
1、開機時就分配方式: # cat /etc/default/grub GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet mgag200.modeset=0 transparent_hugepage=never default_hugepagesz=2M hugepagesz=2M hugepages=1024" GRUB_DISABLE_RECOVERY="true"
# grub2-mkconfig -o /boot/grub2/grub.cfg # reboot
2、動態設置方式: # echo never > /sys/kernel/mm/transparent_hugepage/enabled # echo 1024 > /proc/sys/vm/nr_hugepages # systemctl restart kubelet
# 驗證是否生效,剛到HugePages_Total和HugePages_Free有值就生效了 # cat /proc/meminfo | grep -i huge AnonHugePages: 3534848 kB ShmemHugePages: 0 kB FileHugePages: 0 kB HugePages_Total: 1024 HugePages_Free: 1024 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 2097152 kB # cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages 512 # cat /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages 512 # cat /sys/devices/system/node/node1/hugepages/hugepages-1048576kB/nr_hugepages 0 # cat /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages 0 |
配置大頁面后,系統在開機啟動時會首選嘗試在內存中找到并預留連續的大小為 hugepages * hugepagesz 的內存空間。如果內存空間不滿足,則啟動會報錯 Kernel Panic, Out of Memory 等錯誤。
使用大頁面后,能減少系統管理和訪問頁的時間;內核中的 swap 守護進程也不會管理大頁面占用的這部分空間。合理設置大頁面能減少內存操作的負擔,減少訪問頁表造成性能瓶頸的可能性,從而提升系統性能。
注意:節點從普通內存分出一定大小來作為大頁內存使用,所以節點分配了大頁內存后,節點的普通內存總庫存大小要減去大頁內存的值,這個重啟kubelet后node的Allocatable.Memory會自動減掉,只需要在OPS重新同步內存庫存。
二、創建HugePage虛機
虛機要同時滿足以下條件:
resources.limits.memory的值必須等于resources.requests.memory。
resources.requests.memory的值不能超過節點的2MB 或者 1GB 的頁總大小(頁總大小=hugepages * hugepagesz)。
如果選的頁大小是2MB,resources.requests.memory的值必須可以整除2MB,如果選的頁大小是1GB,resources.requests.memory的值必須可以整除1GB。
|
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: labels: kubevirt.io/vm: huge-page-vm name: huge-page-vm # namespace: test spec: template: spec: domain: cpu: cores: 2 model: host-model resources: limits: cpu: "2" memory: 4Gi requests: cpu: 666m memory: 4Gi memory: # 設置hugepagesz是2Mi或1Gi hugepages: pageSize: "2Mi" |
virt-launcher的pod會占用多一點內存,所以huge-page虛機扣減庫存多加1G大小。
注意:mem_huge_page_repo表更新allocate_memory時,mem__huge_page_sale表的記錄插入時,allocate_request和allocate_limit的值應該比request和limit值大1G。
三、NUMA支持
NUMA簡單可以理解為CPU的內存親和性,在Linux內核2.5版本開始支持。不同NUMA內的CPU core訪問同一個位置的內存,性能不同。內存訪問延時從高到低為:跨CPU > 跨NUMA不跨CPU > NUMA內。
要開出NUMA的虛機,必須滿足以下條件:
- 虛機必須是獨占CPU的,虛機必須是Guaranteed級別。
- 節點必須配置了大頁內存。
- kubevirt 版本是0.43以上,feature-gate必須打開NUMA特性。
|
apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachine metadata: labels: kubevirt.io/vm: numa-vm name: numa-vm # namespace: test spec: template: spec: domain: cpu: dedicatedCpuPlacement: true isolateEmulatorThread: true numa: guestMappingPassthrough: { } resources: limits: cpu: 2 memory: 4Gi requests: cpu: 2 memory: 4Gi memory: # 設置hugepagesz是2Mi或1Gi hugepages: pageSize: "2Mi" |
kubevrit文檔不建議domain.cpu和resources.cpu同時設置,我們統一使用resources設置cpu和內存即可。