容器限速和流量采集01-Namespace和Cgroup
1 应用场景在提供容器化PAAS服务的场景下,跟公有云场景下对于VM的需求类似,我们需要能够限制容器 对于网络、磁盘、CPU以及内存的使用,避免某个容器对资源的占用过高导致影响其他容器使用的情况。目前直接使用 docker 原生的 cgroup 对磁盘、CPU以及内存资源使用进行限制基本够用。但是对于网络的使用限制,需要自己来实现。容器化PAAS服务需要对宿主机上跑的各个业务容器做宽带限速和宽带流
1 应用场景
在提供容器化PAAS服务的场景下,跟公有云场景下对于VM的需求类似,我们需要能够限制容器 对于网络、磁盘、CPU以及内存的使用,避免某个容器对资源的占用过高导致影响其他容器使用的情况。目前直接使用 docker 原生的 cgroup 对磁盘、CPU以及内存资源使用进行限制基本够用。但是对于网络的使用限制,需要自己来实现。容器化PAAS服务需要对宿主机上跑的各个业务容器做宽带限速和宽带流量进行计费。宿主机的网络有单网口和多网口接入两种类型,宿主机上配置的容器的network也需要支持 host和bridge两种模式。
2 docker 容器的隔离性
2.1 linux namespace
Docker 容器使用 linux namespace 来隔离其运行环境,使得容器中的进程看起来就像在一个独立环境中运行一样。linux namespace目的是将某个特定的全局系统资源(global system resource)通过抽象方法使得namespace 中的进程看起来拥有它们自己的隔离的全局系统资源实例。Linux 内核中实现了六种 namespace。
namespace | description |
---|---|
Mount | namespace中看到不同的文件系统 |
UTS | namespace有自己的hostname 和 domainame |
IPC | 只有在同一个 IPC namespace 的进程之间才能互相通信 |
PID | 每个 PID namespace 中的进程可以有其独立的 PID |
Network | 独立的网络设备,IP 地址,IP 路由表 |
User | 独立的user 和 group id |
2.2 linux cgroup(controll groups)
namespace提供的是虚拟环境到宿主机的一个映射,但是并没有限制对宿主机资源的使用,要限制宿主机网络、磁盘、CPU以及内存的使用,需要使用 linux cgroup 来实现。
linux cgroup 目前有 v1,v2两个版本,cgroup driver 主要有 cgroupfs、systemd 两种,也就是有使用 systemd 的 linux 系统,cgroup 的配置已经集成到 systemd。systemd是Kubernetes自带的cgroup driver,而docker的cgroup driver默认是cgroupfs。同时运行有两个cgroup控制管理器,当资源有压力的情况时,有可能出现不稳定的情况。
以 cgroupfs cgroupv1版本为例,/sys/fs/cgroup 目录中有若干个子目录,对应受 cgroups 控制的资源,
cgroup | description |
---|---|
blkio | 对块设备输入输出限制 |
cpu,cpuacct | 对CPU的使用限制 |
cpuset | 多核系统中可以指定使用哪些cpu核 |
devices | 各种访问设备限制 |
freezer | 挂起或恢复任务 |
hugetlb | 对HugeTLB系统大文件系统进行限制 |
memory | 内存使用限制 |
net_cls,net_prio | 网络使用限制以及网络优先级配置 |
2.3 使用 cgroup 对某个 linux 进程进行资源限制配置
上面 docker 对于 CPU 资源使用限制的配置是基于 linux cgroup 来实现的,我们也可以使用 cgroup 来对某个进程做资源限制配置。还是以显示 CPU 使用为例。
2.3.1 不限制 CPU 使用的情况下运行一个测试程序
写一个简单的C测试程序
int main(void)
{
int i = 0;
while(1) {i++;}
return 0;
}
编译这个测试程序并运行
gcc cgroupcpu.c -o cgroupcpu
./cgroupcpu
在不做限制的情况下,cgroupcpu 单核cpu 利用率基本上维持在 100%。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
146841 root 20 0 4212 352 276 R 100.0 0.0 0:09.82 cgroupcpu
2.3.2 使用 cgroup 对进程的 CPU 使用做限制
➜ ~ cd /sys/fs/cgroup/cpu
➜ mkdir cgroupcpu # 新建一个目录用来存储cpu使用限制策略
➜ cd cgroupcpu
➜ cat cpu.cfs_quota_us # cpu.cfs_quota_us文件用来存储cpu使用配额,-1 表示当前没有cpu使用限制
-1
➜ echo 10000 > cpu.cfs_quota_us # 10000表示限制单核cpu利用率为 10%
➜ echo 146841 > tasks # 要将当前要限制的进程 pid 配置到 tasks文件里面,说明是对哪个进程做使用限制,tasks里面可以配置多个进程
使用 cgroup 对进程的 CPU 使用做限制的效果
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
146841 root 20 0 4212 348 276 R 9.9 0.0 2:19.51 cgroupcpu
2.4 docker 资源限制配额配置
docker 配置限制磁盘、CPU以及内存使用的方法比较简单,只需要在 docker run 中配置对应参数即可,以限制 CPU 使用为例,docker run 增加 --cpuset-cpus 参数可以用来限制容器能够使用宿主机的那些 CPU 核。
--cpu-period int Limit CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota
--cpu-rt-period int Limit CPU real-time period in microseconds
--cpu-rt-runtime int Limit CPU real-time runtime in microseconds
-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
2.4.1 docker 不限制cpu使用
docker run -it --name tt \
-v /root/temp:/soft \
centos:7 /soft/cgroupcpu
可以观察到 cgroupcpu 这个进程占用了一个 cpu 核 100% 的利用率
2.4.2 docker 不限制cpu使用 --cpu-quota 限制 cpu 利用率
docker run -it --name ss \
-v /root/temp:/soft \
--cpu-quota=10000 \
centos:7 /soft/cgroupcpu
这个时候查看 cgroupcpu 利用率在 10% 左右
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
267225 root 20 0 4212 348 276 R 9.9 0.0 0:04.71 cgroupcpu
然后在 cgroup cpu 部分的配置里面可以看到对应的配置。如果 cgroup 是 systemd,这个容器对应 cpu cgroup 配置目录是 /sys/fs/cgroup/cpu/system.slice/docker-[containerid].scope,如果 cgroup driver 是 cgroupfs,该容器对应的 cpu cgroup 配置目录是 /sys/fs/cgroup/cpu/docker/[containerid]
➜ pwd
/sys/fs/cgroup/cpu/system.slice/docker-477d1b9306a3881b7ba804d0ad5b3d29436a0358aa587e322ceca35d7c0ef43b.scope # 该容器 cpu cgroup 配置目录
➜ ll
total 0
-rw-r--r-- 1 root root 0 Dec 31 14:22 cgroup.clone_children
--w--w--w- 1 root root 0 Dec 31 14:22 cgroup.event_control
-rw-r--r-- 1 root root 0 Dec 31 14:22 cgroup.procs
-r--r--r-- 1 root root 0 Dec 31 14:22 cpuacct.stat
-rw-r--r-- 1 root root 0 Dec 31 14:22 cpuacct.usage
-r--r--r-- 1 root root 0 Dec 31 14:22 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Dec 31 14:22 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Dec 31 14:22 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Dec 31 14:22 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Dec 31 14:22 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Dec 31 14:22 cpu.shares
-r--r--r-- 1 root root 0 Dec 31 14:22 cpu.stat
-rw-r--r-- 1 root root 0 Dec 31 14:22 notify_on_release
-rw-r--r-- 1 root root 0 Dec 31 14:22 tasks
➜ cat cpu.cfs_quota_us # docker run --cpu-quota=10000 对一个的配置
10000
➜ cat tasks # 这里面存放了该容器运行进程的 pid
267225
参考资料
更多推荐
所有评论(0)