目录

k8s管理大页HugePages配置说明

本文介绍了如何配置大页和k8s使用大页

1 关于大页Huge Pages

在 Linux 中大页分为两种: Huge pages ( 标准大页 ) 和 Transparent Huge pages( 透明大页 ) 。

内存是以块即页的方式进行管理的,当前大部分系统默认的页大小为 4096 bytes 即 4K。1MB 内存等于 256 页; 1GB 内存等于 256000 页。

CPU 拥有内置的内存管理单元,包含这些页面的列表,每个页面通过页表条目引用。当内存越来越大的时候, CPU 需要管理这些内存页的成本也就越高,这样会对操作系统的性能产生影响。

2 Huge Pages

Huge pages 是从 Linux Kernel 2.6 后被引入的,目的是通过使用大页内存来取代传统的 4kb 内存页面, 以适应越来越大的系统内存,让操作系统可以支持现代硬件架构的大页面容量功能。

Huge pages 有两种格式大小:2MB 和1GB ,2MB 页块大小适合用于 GB 大小的内存, 1GB 页块大小适合用于 TB 级别的内存; 2MB 是默认的页大小。

Transparent Huge Pages 从RHEL 6 .SUSE Server 11,Oracle Linux(UEK2) 开始引入的一个功能。

而这两种大页, 根本的区别:Huge Page 是预分配的,Transparent Huge Pages 是动态分配的。

在两者一起使用的情况下,可能会导致性能问题和系统重启。Oracle 服务器建议禁用Transparent Huge Pages. 而在Oracle Linux 6.5 中,已经删除Transparent HugePages.

Oracle 官方虽然推荐我们使用 Huge pages ,但是却建议我们关闭 Transparent Huge pages ,因为透明大页存在一些问题:

  1. 在 RAC 环境下 透明大页( TransparentHugePages )会导致异常节点重启,和性能问题;
  2. 在单机环境中,透明大页( TransparentHugePages ) 也会导致一些异常的性能问题;

注:Transparent Huge Pages在32位的RHEL 6中是不支持的。

3 查看Huge Pages

  • 查询标准大页的大小

    之前说过,huge page 的大小是提前设置好的。那么设置的大页大小是多少呢。可以通过/proc/meminfo来看。

    1
    2
    3
    4
    5
    6
    7
    8
    
    grep Huge /proc/meminfo
      
    AnonHugePages:     18432 kB
    HugePages_Total:       0
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB
    

    AnonHugePages: 匿名 HugePages 数量。Oracle Linux 6.5 中已删除此计数器。与透明 HugePages 有关。

    HugePages_Total: 分配的页面数目,和Hugepagesize相乘后得到所分配的内存大小

    HugePages_Free: 从来没有被使用过的Hugepages数目。即使oracle sga已经分配了这部分内存,但是如果没有实际写入,那么看到的还是Free的。这是很容易误解的地方(池中尚未分配的 HugePages 数量。)

    HugePages_Rsvd: 已经被分配预留但是还没有使用的page数目。在Oracle刚刚启动时,大部分内存应该都是Reserved并且Free的,随着ORACLE SGA的使用,Reserved和Free都会不断的降低

    HugePages_Surp: “surplus”的缩写形式,表示池中大于/proc/sys/vm/nr_hugepages 中值的 HugePages 数量。剩余 HugePages 的最大数量由 /proc/sys/vm/nr_overcommit_hugepages 控制。此值为0的情况很常见

    Hugepagesize: 页面大小

    HugePages_Free – HugePages_Rsvd 这部分是没有被使用到的内存,如果没有其他的oracle instance,这部分内存也许永远都不会被使用到,也就是被浪费了。

    HugePages_Total-HugePages_Free+HugePages_Rsvd 就是目前实例需要的页面数量.

  • 查看是否启用huge_page

    可以通过两个文件中的参数来确定,系统是否启用了大页。

    1
    2
    3
    4
    
    $ cat /proc/sys/vm/nr_hugepages
    0
    $ grep -i HugePages_Total /proc/meminfo
    HugePages_Total:       0
    

    如果两个的结果都是0 ,说明系统中已禁用大页,而且不存在内存大页

4 系统配置Huge Pages

开启该功能需要进行额外设置

4.1 备份文件

4.1.1 备份配置文件

1
cp /etc/default/grub /etc/default/grub.`date +%F`.bak

4.1.2 备份grub配置文件

1
2
3
cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.`date +%F`.bak

# cp /boot/efi/EFI/centos/grub.cfg /boot/efi/EFI/centos/grub.cfg.`date +%F`.bak

4.2 编辑/etc/default/grub 文件

在 GRUB_CMDLINE_LINUX 那一行后面追加下面内容,例如:

1
2
# vi /etc/default/grub
GRUB_CMDLINE_LINUX="transparent_hugepage=never default_hugepagesz=2M hugepagesz=1G hugepages=1 hugepagesz=2M hugepages=512"

说明:如果禁用透明大页,则需设置transparent_hugepage=never

各类型大页数量,可根据实际环境配置。

配置后节点文件实例,其中hugepages相关的内容是新增的,其它配置不改动

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@host-136 home]# 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=0M-4G:128M,4G-8G:256M,8G-:512M transparent_hugepage=never default_hugepagesz=2M hugepagesz=1G hugepages=1 hugepagesz=2M hugepages=512  nomodeset"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_DISABLE_OS_PROBER=true
[root@host-136 home]#

4.3 重新生成grub配置文件

不同系统配置一下的grub配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
On BIOS-based machines, issue the following  command   as root:
# grub2-mkconfig -o /boot/grub2/grub.cfg
On UEFI-based machines, issue the following  command   as root:
# grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
## centos
# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

ctyunos 系统
# grub2-mkconfig -o /boot/grub2/grub.cfg

再使用 grub2-mkconfig 生成grub.cfg配置文件。

1
2
3
4
5
6
# 注意不同系统下的配置文件路径

# grub2-mkconfig -o /boot/grub2/grub.cfg

# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

配置实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@claster4-master1 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.10.0-136.12.0.86.ctl3.x86_64
Found initrd image: /boot/initramfs-5.10.0-136.12.0.86.ctl3.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-60f6c5d40de24acabdcc67f51be8f5f8
Found initrd image: /boot/initramfs-0-rescue-60f6c5d40de24acabdcc67f51be8f5f8.img
Adding boot menu entry for UEFI Firmware Settings ...
done
[root@claster4-master1 ~]#

4.4 重启节点

1
2
# reboot now
init 6

4.5 检查大页配置信息

查看Hugepagesize、 HugePages_Total等参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@host-136 ~]# grep Huge /proc/meminfo
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
FileHugePages:         0 kB
HugePages_Total:     512
HugePages_Free:      512
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:         2097152 kB
[root@host-136 ~]#

检查大页数量配置,512个2M大页和1个1G大页

1
2
3
4
5
6
7
8
9
[root@host-136 ~]# cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
512
[root@host-136 ~]#
[root@host-136 ~]#
[root@host-136 ~]#
[root@host-136 ~]# cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
1
[root@host-136 ~]#

4.6 重启kubelet,让k8s生效大页内存资源

此时k8s尚未管理系统已生效的大页资源

/posts/2024/03/k8s%E7%AE%A1%E7%90%86%E5%A4%A7%E9%A1%B5hugepages%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E/136-hp-gaiqian.png

需重启kubelet以生效

1
systemctl restart kubelet

查看配置大页内存的节点信息,能够看到2M和1G大页内存已在k8s集群节点中生效,如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Capacity:
  chinatelecom/vcuda-core:    0
  chinatelecom/vcuda-memory:  0
  cpu:                        112
  ephemeral-storage:          51166812Ki
  hugepages-1Gi:              1Gi
  hugepages-2Mi:              1Gi
  memory:                     395095064Ki
  pods:                       110
  tencent.com/vcuda-core:     0
  tencent.com/vcuda-memory:   0
Allocatable:
  chinatelecom/vcuda-core:    0
  chinatelecom/vcuda-memory:  0
  cpu:                        111600m
  ephemeral-storage:          51166812Ki
  hugepages-1Gi:              1Gi
  hugepages-2Mi:              1Gi
  memory:                     381676706310
  pods:                       110
  tencent.com/vcuda-core:     0
  tencent.com/vcuda-memory:   0

注意以下信息变化:

1
2
3
4
5
6
# k8s生效前
  hugepages-1Gi:              0
  hugepages-2Mi:              0
# k8s生效后
  hugepages-1Gi:              1Gi
  hugepages-2Mi:              1Gi

5 K8S API

用户可以通过在容器级别的资源需求中使用资源名称 hugepages-<size> 来使用巨页,其中的 size 是特定节点上支持的以整数值表示的最小二进制单位。 例如,如果一个节点支持 2048KiB 和 1048576KiB 页面大小,它将公开可调度的资源 hugepages-2Mihugepages-1Gi。与 CPU 或内存不同,巨页不支持过量使用(overcommit)。 注意,在请求巨页资源时,还必须请求内存或 CPU 资源。

同一 Pod 的 spec 中可能会消耗不同尺寸的巨页。在这种情况下,它必须对所有挂载卷使用 medium: HugePages-<hugepagesize> 标识。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-example
spec:
  containers:
  - name: example
    image: fedora:latest
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages-2Mi
      name: hugepage-2mi
    - mountPath: /hugepages-1Gi
      name: hugepage-1gi
    resources:
      limits:
        hugepages-2Mi: 100Mi
        hugepages-1Gi: 2Gi
        memory: 100Mi
      requests:
        memory: 100Mi
  volumes:
  - name: hugepage-2mi
    emptyDir:
      #  必须为HugePages-xxx格式
      medium: HugePages-2Mi
  - name: hugepage-1gi
    emptyDir:
      #  必须为HugePages-xxx格式
      medium: HugePages-1Gi

Pod 只有在请求同一大小的巨页时才使用 medium:HugePages

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-example
spec:
  containers:
  - name: example
    image: fedora:latest
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 100Mi
        memory: 100Mi
      requests:
        memory: 100Mi
  volumes:
  - name: hugepage
    emptyDir:
      #  可以为HugePages格式
      medium: HugePages

说明:

  • 与CPU或内存不同,巨大页面不支持过度承诺。请注意,在请求hugepage资源时,必须同时请求内存或CPU资源。

  • 巨页的资源请求值必须等于其限制值。该条件在指定了资源限制,而没有指定请求的情况下默认成立。

例如,在默认页面大小为 4KiB 的系统上,你可以指定限制 hugepages-2Mi: 80Mi。 如果容器尝试分配 40 个 2MiB 大小的巨页(总共 80 MiB ),则分配请求会失败。

说明:

不能过量使用 hugepages- * 资源。 这与 memorycpu 资源不同。

6 业务测试

使用大页内存的pod测试,k8s集群节点已有大页资源

/posts/2024/03/k8s%E7%AE%A1%E7%90%86%E5%A4%A7%E9%A1%B5hugepages%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E/136-hp-gaihou.png

6.1 2M类型大页资源

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-2mi-example
spec:
  containers:
  - name: example
    image: dockerhub.kubekey.local/kubesphereio/busybox:1.31.1
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 10Mi
        memory: 100Mi
      requests:
        memory: 100Mi
  volumes:
  - name: hugepage
    emptyDir:
      #  可以为HugePages格式
      medium: HugePages

6.2 1G大页资源

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-1gi-example
spec:
  containers:
  - name: example
    image: dockerhub.kubekey.local/kubesphereio/busybox:1.31.1
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-1Gi: 1Gi
        memory: 100Mi
      requests:
        memory: 100Mi
  volumes:
  - name: hugepage
    emptyDir:
      #  可以为HugePages格式
      medium: HugePages

/posts/2024/03/k8s%E7%AE%A1%E7%90%86%E5%A4%A7%E9%A1%B5hugepages%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E/136-hp-gaihou2.png

6.3 混合类型大页

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-example
spec:
  containers:
  - name: example
    image: fedora:latest
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages-2Mi
      name: hugepage-2mi
    - mountPath: /hugepages-1Gi
      name: hugepage-1gi
    resources:
      limits:
        hugepages-2Mi: 100Mi
        hugepages-1Gi: 2Gi
        memory: 100Mi
      requests:
        memory: 100Mi
  volumes:
  - name: hugepage-2mi
    emptyDir:
      medium: HugePages-2Mi
  - name: hugepage-1gi
    emptyDir:
      medium: HugePages-1Gi

查看配置大页节点的大页内存使用情况,如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                   Requests     Limits
  --------                   --------     ------
  cpu                        1472m (1%)   4500m (4%)
  memory                     1519Mi (0%)  3218Mi (0%)
  ephemeral-storage          0 (0%)       0 (0%)
  hugepages-1Gi              1Gi (100%)   1Gi (100%)
  hugepages-2Mi              210Mi (20%)  210Mi (20%)
  chinatelecom/vcuda-core    0            0
  chinatelecom/vcuda-memory  0            0
  tencent.com/vcuda-core     0            0
  tencent.com/vcuda-memory   0            0

1
2
3
4
[root@cluster2-master1 ~]# kubectl get pod
huge-pages-2mi-example           1/1     Running   0              102m
huge-pages-mix-1gi-2mi-example   1/1     Running   0              34m

/posts/2024/03/k8s%E7%AE%A1%E7%90%86%E5%A4%A7%E9%A1%B5hugepages%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E/136-hp-gaihou3.png

6.4 大页资源超用

pod作业已使用完1G大页内存,pod作业继续请求1G大页资源,测试如下:

1
2
3
4
5
6
[root@cluster2-master1 hugepage]# kubectl get po |grep huge
huge-pages-1gi-example           0/1     Pending   0              3m31s
huge-pages-2mi-example           1/1     Running   0              106m
huge-pages-mix-1gi-2mi-example   1/1     Running   0              38m
[root@cluster2-master1 hugepage]#

查看排队等待pod信息,发现调度失败,原因为:节点的hugepages-1Gi资源都不满足作业pod请求

1
2
3
4
5
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  40s (x4 over 4m3s)  default-scheduler  0/7 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 6 Insufficient hugepages-1Gi.

6.5 大页资源使用+cpu

仅设置cpu,无memory,可以运行成功

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-2mi-example
spec:
  containers:
  - name: example
    image: dockerhub.kubekey.local/kubesphereio/busybox:1.31.1
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 10Mi
        #memory: 100Mi
        cpu: 1
      requests:
        #memory: 100Mi
        cpu: 1
  volumes:
  - name: hugepage
    emptyDir:
      #  可以为HugePages格式
      medium: HugePages

6.6 大页资源使用错误

没有设置cpu和memory,接口报错,运行失败

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: v1
kind: Pod
metadata:
  name: huge-pages-2mi-example
spec:
  containers:
  - name: example
    image: dockerhub.kubekey.local/kubesphereio/busybox:1.31.1
    command:
    - sleep
    - inf
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 10Mi
        # 错误:没有设置cpu和memory
        #memory: 100Mi
      requests:
        # 错误:没有设置cpu和memory
        #memory: 100Mi
  volumes:
  - name: hugepage
    emptyDir:
      #  可以为HugePages格式
      medium: HugePages

错误显示

1
2
3
4
5
6
[root@cluster2-master1 hugepage]#
[root@cluster2-master1 hugepage]# kubectl create -f error-2m.yaml
The Pod "huge-pages-2mi-example" is invalid: spec.containers[0].resources: Forbidden: HugePages require cpu or memory
[root@cluster2-master1 hugepage]#
[root@cluster2-master1 hugepage]#

7 附录参考

Linux HugePage

https://www.cnblogs.com/halberd-lee/p/12802918.html

k8s管理巨页(HugePage)

https://kubernetes.io/zh-cn/docs/tasks/manage-hugepages/scheduling-hugepages/

Linux 大页内存 Huge Pages 虚拟内存

https://www.cnblogs.com/studywithallofyou/p/17435497.html

HugeTLB Pages

https://www.kernel.org/doc/html/latest/admin-guide/mm/hugetlbpage.html

欧拉系统的内存大页配置

https://docs.openeuler.org/zh/docs/22.03_LTS_SP3/docs/StratoVirt/%E8%99%9A%E6%8B%9F%E6%9C%BA%E9%85%8D%E7%BD%AE.html