Kubernetes采用CGroup实现容器的资源隔离。CGroup V2统一了访问资源的路径,支持Pod级别的资源监控、网络重定向,同时在跨多资源协调上具备更强的资源隔离能力。本文介绍如何使用ack-image-builder工具构建CGroup V2的自定义镜像,并在ACK控制台使用自定义镜像创建CGroup V2节点。
背景信息
CGroup
Kubernetes采用CGroup实现容器的资源隔离。CGroup分为V1和V2版本,V2版本提供了更一致的体验和更丰富的功能。主要特性如下。
统一了访问资源的路径,各种资源处于统一路径下。
新增PSI等功能特性。
支持CGroup级别的eBPF挂载,可以实现Pod级别的资源监控、网络重定向等。
在跨多资源协调上具备更强的资源隔离能力。
统一地管理各种类型的内存分配,例如网络内存、Kernel内存等。
支持异步资源变化的统计,例如通过Page Cache的Write-back统计实现异步IO的限制。
Kubernetes在1.18版本中支持CGroup V2,进入Alpha阶段,在1.22版本中进入Beta阶段,在1.25中进入GA。更多信息,请参见About cgroup v2。
ack-image-builder
ack-image-builder是阿里云推出的一款镜像构建工具,旨在通过简易的方式自动化构建镜像。利用ack-image-builder可以构建出CGroup V2的系统镜像,方便您在ACK集群中添加CGroup V2的节点。关于ack-image-builder,请参见ack-image-builder。
ack-image-builder基于开源工具HashiCorp Packer开发,HashiCorp Packer提供默认配置模板和校验脚本。关于HashiCorp Packer,请参见HashiCorp Packer。
使用限制
限制项 | 说明 |
操作系统 | 目前仅Alibaba Cloud Linux 3支持CGroup V2。所以仅支持使用Alibaba Cloud Linux 3作为基础镜像来构建支持CGroup V2的自定义镜像。 |
运行时 | 仅支持containerd运行时。 |
Kubernetes | 1.28及以上版本。 |
应用或组件 | 如果集群上运行的应用或者组件依赖于CGroup,请确保它们与CGroup V2兼容。
|
注意事项
如果使用Java的应用,建议采用JDK 11.0.16或者JDK 15之后的版本,以便与CGroup V2兼容。更多信息,请参见JDK-8230305。
前提条件
已前往配额平台申请使用自定义镜像。
操作步骤
使用ack-image-builder创建Kubernetes集群自定义节点镜像的步骤如下。
安装Packer。
执行如下命令,下载CGroup V2的配置模板。
git clone https://github.com/AliyunContainerService/ack-image-builder.git cd ack-image-builder
构建CGroup V2的节点自定义镜像。
执行如下命令,导入AccessKey信息用于创建构建镜像过程中的临时资源。
export ALICLOUD_ACCESS_KEY=XXXXXX export ALICLOUD_SECRET_KEY=XXXXXX
执行如下命令,制作自定义镜像。
packer build -var cgroup_mode=CGROUP_MODE_V2 examples/ack-aliyunlinux3.json
其中
cgroup_mode
的参数为镜像采用的CGroup模式,默认为CGROUP_MODE_V1
。此处指定为CGROUP_MODE_V2
,构建出的自定义镜像采用CGroup V2的CGroup模式。其中
scripts/set-cgroupv2.sh
为设置CGroup版本,m-xxxxxxxxxxxxxxxxx
为自定义镜像ID。
采用CGroup V2镜像创建集群。
下文以创建ACK集群Pro版为例。
登录集群节点,执行如下命令查看CGroup类型。验证集群中的节点是否采用了CGroup V2。
df -T /sys/fs/cgroup
预期结果:
Filesystem Type 1K-blocks Used Available Use% Mounted on cgroup2 cgroup2 0 0 0 - /sys/fs/cgroup
表示集群中的节点采用了CGroup V2。
CGroup V2常用使用场景
使用CGroup V2限制容器IO速度
"CGroup V1"对异步的"blockio"统计不准确,导致容器的IO的统计和限制通常大大小于实际应用IO的量。
而在"CGroup V2"中会同时将这部分异步的IO统计到正确容器中,所以我们可以采用"CGroup V2"来限制容器的IO。
限制方式:
通过将对应的磁盘的I/O限制写入到容器的"CGroupV2"的"io.max"限制文件中达到限制容器IO的效果。
详细配置内容参考链接。
示例:
在容器启动时,我们对容器的"CGroupV2"做IO的限制,随后启动"dd"命令来验证限制后整体io被控制在限制的带宽值:
apiVersion: v1
kind: Pod
metadata:
name: write-file-pod
spec:
restartPolicy: Never
containers:
- name: dd-container
image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3
command:
- bash
- -c
- "yum install -y sysstat; \
echo '253:0 wbps=10485760' > /sys/fs/cgroup$(cat /proc/1/cgroup | awk -F ':' '{print $3}')/io.max; \
dd if=/dev/zero of=/writefile bs=100M count=10 & iostat -dh 1 30;"
securityContext:
privileged: true
# 其中 "echo '253:0 wbps=10485760' > /sys/fs/cgroup/.../io.max"为io限制配置
# "253:0" 为磁盘的设备id,可以根据实际环境中写入的磁盘设备调整
# "wbps" 是磁盘写入带宽限制, 10485760=10MB/s
将如上Pod部署到集群中后,查看Pod日志可以看到磁盘的IO被限制到配置的10MB/s。
# kubectl logs write-file-pod -f
....
tps kB_read/s kB_wrtn/s kB_read kB_wrtn Device
91.00 0.0k 10.8M 0.0k 10.8M vda
tps kB_read/s kB_wrtn/s kB_read kB_wrtn Device
88.00 0.0k 9.6M 0.0k 9.6M vda