奇技指南
在开发一款软件时,为了延长软件的生命周期,须要一款配套软件来对发布的软件进行监控。随着容器技术的成熟,系统的定制和软件的打包变得愈来愈容易,同时,对容器进行监控成为了容器使用者所必备的技能。下来,做者将带领你们认识一下容器的资源管理工具Cgroups。
提及容器监控,首先会想到经过Cadvisor, Docker stats等多种方式获取容器的监控数据,并同时会想到容器经过Cgroups实现对容器中的资源进行限制。可是这些数据来自哪里,而且如何计算的?答案是Cgroups。最近在写docker容器监控组件,在深刻Cadvisor和Docker stats源码发现数据都来源于Cgroups。了解之余,并对Cgroups作下笔记。html
Cgroups 是 control groups 的缩写,是Linux内核提供的一种能够限制,记录,隔离进程组(process groups)所使用物理资源的机制。最初有google工程师提出,后来被整合进Linux的内核。所以,Cgroups为容器实现虚拟化提供了基本保证,是构建Docker,LXC等一系列虚拟化管理工具的基石。linux
Cgroups主要由task,cgroup,subsystem及hierarchy构成。下面分别介绍下各自的概念。docker
Subsystems, Hierarchies,Control Group和Tasks之间有许多的规则,下面介绍下:
一、同一个hierarchy可以附加一个或多个subsystem。
以下图,将cpu和memory subsystems(或者任意多个subsystems)附加到同一个hierarchy。shell
二、一个subsystem只能附加到一个hierarchy上。
以下图,cpu subsystem已经附加到了hierarchy A,而且memory subsystem已经附加到了hierarchy B。所以cpusubsystem不能在附加到hierarchy B。centos
三、系统每次新建一个hierarchy时,该系统上的全部task默认构成了这个新建的hierarchy的初始化cgroup,这个cgroup也称为root cgroup。对于你建立的每一个hierarchy,task只能存在于其中一个cgroup中,即一个task不能存在于同一个hierarchy的不一样cgroup中,可是一个task能够存在在不一样hierarchy中的多个cgroup中。若是操做时把一个task添加到同一个hierarchy中的另外一个cgroup中,则会从第一个cgroup中移除。
以下图,cpu和memory被附加到cpu_mem_cg的hierarchy。而net_cls被附加到net_cls hierarchy。而且httpd进程被同时加到了cpu_mem_cg hierarchy的cg1 cgroup中和net hierarchy的cg3 cgroup中。并经过两个hierarchy的subsystem分别对httpd进程进行cpu,memory及网络带宽的限制。微信
四、系统中的任何一个task(Linux中的进程)fork本身建立一个子task(子进程)时,子task会自动的继承父task cgroup的关系,在同一个cgroup中,可是子task能够根据须要移到其它不一样的cgroup中。父子task之间是相互独立不依赖的。
以下图,httpd进程在cpu_and_mem hierarchy的/cg1 cgroup中并把PID 4537写到该cgroup的tasks中。以后httpd(PID=4537)进程fork一个子进程httpd(PID=4840)与其父进程在同一个hierarchy的统一个cgroup中,可是因为父task和子task之间的关系独立不依赖的,因此子task能够移到其它的cgroup中。网络
咱们直接使用shell 命令直接操做hierarchy并设置cgroup参数。在centos6上也能够直接使用libcgroup提供的工具可简化对cgroup的使用。ide
使用shell命令建立hierarchy并附加subsystems到该hierarchy上。 做为root为hierarchy建立一个mount point。而且在mount point中包含cgrou的名字。工具
例如:测试
接下来使用mount命令去挂载hierarchy并附加一个或多个subsystem到该hierarchy上。
例如:
若是想在已有的hierarchy上attch或detach subsystem,可使用remount操做,例如咱们想detach掉memory subsystem。
能够直接用umount命令来unmount一个已有的Hierarchy:
例如:
直接使用shell命令mkdir建立一个子cgroup:
例如:
在group1中使用echo命令插入0-1到cpuset.cpus,来限制该cgroup中的tasks只能跑在0和1的cpu core上。以下:
只要将想要限制的进程PID,追加到想要的cgroup的tasks文件中就能够了。例如:将PID=1701的进程放到“/cgroup/cpu_and_mem/group1/”的cgroup中。
不管是使用docker run方式直接建立容器,仍是经过各种容器编排工具(如:Kubernetes)建立容器,对于容器的限制本质都是经过Cgroups。咱们分别使用这两种方式来建立容器并观察cgroups:
测试环境:
一、限制CPU share,建立两个容器,则会在运行该容器宿主的/sys/fs/cgroup/cpu/docker/ 下分别建立两个子cgroup,格式以下。
二、建立一个容器,并设置--cpu-shares参数为:1024*10。
查看该容器cgroup的cpu.shares文件内容以下。
三、建立一个容器,并设置--cpu-shares参数为: 1024*14。
查看该容器cgroup的cpu.shares文件内容以下。
四、两个容器使用cpu的stats,一个容器分到14核的相对cpu计算时间,另外一个容器分到10核的相对cpu计算时间:
一、建立一个容器,限制容器能使用的内存上限为1024M。
二、查看容器memory的stats,内存使用率100%。
三、当容器使用的内存量超过1024M,则容器会被kill -9掉。
使用kubernetes编排工具建立的容器,则与容器关联的cgroup均在运行该容器宿主机的/sys/fs/cgroup/cpu/kubepods/下,具体的格式以下所示:
使用Pod建立一个容器,对应的yaml文件内容以下:
在运行该容器的宿主机上查看该容器的cgroup信息,会观察到cpu.shares为1核,memory.limit_in_bytes为2G。
相关文章
https://access.redhat.com/doc...
https://www.kernel.org/doc/Do...
http://www.infoq.com/cn/artic...
关于360技术
360技术是360技术团队打造的技术分享公众号,天天推送技术干货内容
更多技术信息欢迎关注“360技术”微信公众号