本文介绍了如何配置大页和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 ,因为透明大页存在一些问题:
- 在 RAC 环境下 透明大页( TransparentHugePages )会导致异常节点重启,和性能问题;
- 在单机环境中,透明大页( 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 重启节点
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尚未管理系统已生效的大页资源
需重启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-2Mi
和 hugepages-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
|
说明:
例如,在默认页面大小为 4KiB 的系统上,你可以指定限制 hugepages-2Mi: 80Mi
。 如果容器尝试分配 40 个 2MiB 大小的巨页(总共 80 MiB ),则分配请求会失败。
说明:
不能过量使用 hugepages- *
资源。 这与 memory
和 cpu
资源不同。
6 业务测试
使用大页内存的pod测试,k8s集群节点已有大页资源
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
|
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
|
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