一、cgroup资源配置方法
1.cgroup概念
cgroup(control group控制族群)
(1)什么是cgroup
和namespace类似,也是将进程进程分组,但是目的与namespace不一样,namespace是为了隔离进程组之前的资源,而cgroup是为了对一组进程进行统一的资源监控和限制。
(2)为什么要使用cgroup
在Linux里,对进程进程分组,比如Session group、process group等,后来需要追踪一组进程的内存和IO使用情况,出现了cgroup,用来统一对进程进行分组,并在分组的基础上对进程进程监控和资源控制管理等。
(3)cgroup的作用
cgroup(control group控制族群)是一个内核特性,用于限制、统计、隔离一组进程的资源(CPU、内存、磁盘、网络等),首字母不要大写。Docker通过cgroup来控制容器使用的资源配额,包括CPU、内存、磁盘三大方面,基本覆盖了常见的资源配额和使用量控制。
cgroup 主要功能包括:
- 资源限制:限制一组进程的可用资源阈值。
- 资源监控:监控 cgroup 级别的资源使用状态。
- 进程控制:控制(挂起 or 恢复)cgroup 中的所有进程。
- 优先级控制:控制不同 cgroup 的优先级,当资源不足时,优先满足优先级高的 cgroup。
控制族群就是按照一组某种标准划分的进程。Cgroup中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也可以从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用cgroups以控制族群为单位分配资源,同时受到cgroups以控制族群为单位设定限制。
注意:
- 单数形式(cgroup)指所有特性,也可以作为“cgroup controllers”的修饰。
- 复数形式(cgroups)指多个 cgroup。
(4)docker利用cgroup隔离其命名空间
cgroup是一种资源控制手段,也是容器隔离的6个名称空间的一种实现手段
Docker 是一款常用的容器化管理工具,其中的命名空间是其重要特性之一。Docker 命名空间可以分为六种类型,每种类型都有其独特的作用和用途。下面一一介绍这六种命名空间:
1. Mount (mnt)
这种命名空间隔离的是挂载点。通过这个空间,我们可以在容器中挂载文件系统,而不会影响到主机系统的挂载点,实现了文件系统的隔离。
2. Process ID (pid)
这种命名空间隔离了进程 ID。使用这种空间可以将容器内部的进程 ID 隔离开来,从而避免与宿主机的进程 ID 冲突。
3. Network (net)
这种命名空间隔离的是网络配置。通过这个空间,我们可以自定义容器的网络配置,而不会影响到宿主机或其他容器的网络配置,实现了网络的隔离。
4. Interprocess Communication (ipc)
这种命名空间隔离的是进程间通信。使用这个空间,可以将容器内部的进程间通信隔离,避免与宿主机或其他容器的进程间通信冲突。
5. User ID (user)
这种命名空间隔离的是用户 ID。使用这种命名空间可以让容器内部的用户 ID 和宿主机上的用户 ID 隔离开来,从而避免权限问题。
6. UTS Namespace (uts)
这种命名空间隔离的是主机的主机名和域名。使用这种空间可以让容器内部有独立的主机名和域名,而不会影响到宿主机的主机名和域名。
当我们需要在 Docker 中进行资源隔离和管理时,这些命名空间 是非常有用的。通过这些命名空间,可以更好地隔离各个容器之间的资源,从而使容器的资源利用更加高效,保持容器的互相独立性。
每个容器相当于一个进程
进程相当于资源
(5)docker中的cgroup驱动器
对于cgroup的操作驱动,大多数linux发行版上,操作系统默认的驱动都为systemd。
docker支持的cgroup驱动器有两个:cgroupfs和systemcd
- cgroupfs是文件驱动修改,内核功能没有提供任何的系统调用接口,而是对 linux vfs 的一个实现,因此可以用类似文件系统的方式进行操作。
- systemd封装了 cgroups 的软件也能让你通过它们定义的接口控制 cgroups 的内容,因此是通过接口调用驱动修改。
docker默认的cgroup的驱动为cgroupfs,可通过启动参数native.cgroupdriver=systemd进行修改
Kubernetes的默认驱动和docker的驱动是一致的。
因为多数linux发行版的cgroup的驱动为systemd,所以当再选择cgroupfs作为驱动时,会致使操作系统中存在两个cgroup驱动,会带来不稳定的影响。所以在系统已经使用systemd的基础上,配置不推荐使用cgroupfs,直接使用systemd即可。
二、使用 Stress 工具测试 CPU 和内存
1.用 Stress 工具测试 CPU 和内存
[root@localhost ~]# docker pull centos:7
[root@localhost ~]# cd /root/stress/
[root@localhost ~]# vim /root/stress/Dockerfile
FROM centos:7
MAINTAINER 5CC
RUN yum -y install wget
RUN wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum -y install stress
[root@localhost ~]# cd /root/stress
[root@localhost stress]# docker build -t centos:stress .
[root@localhost stress]# docker run -tid --name cpu100 --cpu-shares 100 centos:stress stress -c 10
[root@localhost ~]# docker exec -it cpu100 bash
备注:
stress是一个压力测试工具,用于测试cpu和内存的负载
cpu.shares。这个值是 CPU cgroup 对于控制组之间的 CPU 分配比例,它的缺省值是 1024。
-c:运行10个stress进程
使用cpu share命令设置容器使用cpu的优先级
[root@localhost ~]# docker run -tid --name cpu512 --cpu-shares 512 centos:stress stress -c 10
[root@localhost ~]# docker exec -it cpu512 bash
进入容器用top命令查看资源利用情况
设置cpu资源翻倍
[root@localhost~]#docker run -tid --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10
[root@localhost ~]# docker exec -it cpu1024 bash
进入容器用top命令查看资源利用情况
三个容器的对比(查看其中stress的进程数量)
备注:
测试完后删掉这三个容器
docker rm cpu100 -f
docker rm cpu512 -f
docker rm cpu1024 -f
2.CPU周期限制
[root@localhost ~]# docker run -tid --name mem --cpu-period 100000 --cpu-quota 200000 centos:stress
[root@localhost ~]# docker exec -it mem bash
[root@738f9fc62048 /]# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us
[root@738f9fc62048 /]# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
备注:
- --cpu-period 是用来指定容器对 CPU 的使用要在多长时间内做一次重新分配。
- --cpu-quota 是用来指定在这个周期内,最多可以有多少时间用来跑这个容器。
- cpu-period 和 cpu-quota 的单位为微秒(μs)
3.CPU Core 控制
[root@localhost ~]# docker run -tid --name cpu1 --cpuset-cpus 0-2 centos:stress
注意:docker主机需要更多的cpu内核,否则包含3个内核的容器无法创建,增加内核后重启一下docker主机
0-2表示0、1、2三个内核
[root@localhost ~]# docker exec -it cpu1 bash
[root@5204fe18208e /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus
4.CPU 配额控制参数的混合使用
[root@localhost ~]# docker run -tid --name cpu3 --cpuset-cpus 3 --cpu-shares 512 centos:stress stress -c 1
[root@localhost ~]# docker exec -it cpu3 bash
进入容器用top命令查看资源利用情况
注意:
docker主机的cpu内核数量要大于等于满足配额数量
[root@localhost ~]# docker run -tid --name cpu4 --cpuset-cpus 3 --cpu-shares 1024 centos:stress stress -c 1
[root@localhost ~]# docker exec -it cpu4 bash
进入容器用top命令查看资源利用情况
对比两次的显示结果,重点查看%CPU这一列的值,应该为2:1的比例
stress -c 1 命令,将会给系统一个随机负载,产生 1 个进程
5.内存限额
允许该容器最多使用 200M 的内存和 300M 的 swap
[root@localhost ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
备注:
--vm 1:启动 1 个内存工作线程
--vm-bytes 280M:每个线程分配 280M 内存
- 分配 280M 内存。
- 释放 280M 内存。
- 再分配 280M 内存。
- 再释放 280M 内存。
- 一直循环......
让工作线程分配的内存超过 300M,分配的内存超过限额,stress 线程报错,容器退出:
[root@localhost ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
6.Block IO 的限制
默认情况下,所有容器能平等地读写磁盘,可以通过设置--blkio-weight 参数来改变容器block IO 的优先级。
--blkio-weight 与 --cpu-shares 类似,设置的是相对权重值,默认为 500。取值范围10--1000
在下面的例子中,容器 A 读写磁盘的带宽是容器 B 的两倍。
[root@localhost ~]# docker run -it --name container_A --blkio-weight 600 centos:stress
[root@5e7093d94869 /]# cat /sys/fs/cgroup/blkio/blkio.weight
[root@localhost ~]# docker run -it --name container_B --blkio-weight 300 centos:stress
[root@39947b6517d4 /]# cat /sys/fs/cgroup/blkio/blkio.weight
cat /sys/fs/cgroup/blkio/blkio.bfq.weight
注意:
kernel 5.10 或更高的版本不在适用
要使 –blkio-weight 生效,需要保证 IO 的调度算法为 CFQ。可以使用下面的方式查看:
root@localhost:~# cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
7.bps 和 iops 的限制
限制容器写 /dev/sda 的速率为 5 MB/s
[root@localhost ~]# docker run -it --device-write-bps /dev/sda:5MB centos:stress
[root@e3eb0e9ad6fc /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct
不限速
[root@localhost ~]# docker run -it centos:stress
[root@cb6691338f52 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct