3.0.2. 隔离与限制

2019-04-20  本文已影响0人  RockyLuo_290f

一个运行着CentOS的KVM虚拟机启动后,不做优化的情况下,虚拟机自己就需要占用100~200MB内存。
应用运行在虚拟机里面,对宿主机操作系统的调用就不可避免要经过虚拟化软件的拦截和处理,本身又是一层性能损耗,

容器化后的用户应用,依然还是一个宿主机上的普通进程,使得虚拟化带来的性能虽好几乎可以忽略。

敏捷和高性能 是容器相较于虚拟机的最大优势,也是它在PaaS这种更细粒度的资源管理平台上大行其道的重要原因。
其弊端的主要问题是 隔离得不彻底。

首先既然容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。

例如在Windows宿主机上运行Linux容器,或者在低版本Linux机上运行高版本的Linux容器都是行不通的

其次在linux内核中,有很多资源和对象是不能被namespace化的,如时间time

如果你的容器中的程序修改了系统时间,整个宿主机的时间都会被随之修改。
应此在容器里部署应用的时候,用户必须考虑到什么可以改,什么不能改

由于共享宿主机内核,容器给应用暴露出来的攻击面是相当大的,越狱难度也比虚拟机低得多

尽管我们可以使用Seccomp等技术,对容器内部发起的所有系统调用进行过滤和甄别来进行安全加固,但这种方法因为多了一层对系统调用的过滤,一定会拖累容器的性能

容器的限制:

在容器内的第一号进程,在容器的干扰下只能看到容器里的情况,但在宿主机上,它同其他进程依然是平等的竞争关系,
这就意味这个进程虽然被隔离起来,但它所能够使用到的资源确实可以随时被宿主机上的其他进程占用,当然,他自己将所有资源吃光也是不合理的。

Linux Cgroups就是Linux内核中用来为进程设置资源限制的一个重要功能, 全称为 Linux Control Group。最主要的左右就是限制一个进程组能够使用的资源上限,包括CPU,内存,磁盘,网络带宽等等。此外Cgroup还能够对进程进行优先级设置,审计,以及将进程挂起和恢复等操作

在Linux中,Cgroups给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下
可以用mount指令展示出来

$ mount -t cgroup 
cpuset on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cpu on /sys/fs/cgroup/cpu type cgroup (rw,nosuid,nodev,noexec,relatime,cpu)
cpuacct on /sys/fs/cgroup/cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct)
blkio on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
memory on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)

其输出结果为一系列的文件系统目录,(如果没有,需要挂载Cgroups)
在子系统对应的资源种类下,可以看到该类资源具体可以被限制的方法,比如对CPU子系统来说,我们可以看到如下几个配置文件

$ ls /sys/fs/cgroup/cpu
cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us  cpu.shares notify_on_release
cgroup.procs      cpu.cfs_quota_us  cpu.rt_runtime_us cpu.stat  tasks

例如参数cfs_period, cfs_quota就可以控制。cfs_period的一段时间内,只能被分配到总量为cfs_quota的cpu时间
一个死循环的进程 while true, 编号为226. 普通情况下会将cpu资源占满

通过设置cfs_period为100000(100ms), cfs_quota 写入20000(20ms)

接着把限制进程的PID写入container组里的tasks文件,上面的设置就会对该进程生效了,cpu的使用率就从100%立刻降到20%

其他设置限制能力的option
blkio 设置I/O限制
cpuset,为进程分配单独CPU核和对应的内存节点
memory,为进程设定内存使用的限制

一个容器的本质是一个单进程模型,这就意味着,在一个容器中,无法同时运行两个不同的应用。除非用公共程序当两个不同应用的父进程,一般用systemd或者supervisord这样的代替,作为容器的启动进程。

容器本身的设计,希望容器和应用能够同生命周期。

上一篇 下一篇

猜你喜欢

热点阅读