
一、Namespace和Cgroup
1. Namespace命名空间
Linux内核实现Namespace的主要目的之一是实现轻量级虚拟化(容器)服务。再此之前,Linux中很多资源是全局管理。
命名空间建立系统的不同视图,对于每一个命名空间,从用户看起来,应该像一台单独的Linux计算机一样,有自己的init进程(PID为O),其他进程的PID依次递增,A和B空间都有PID为0的init进程。
子容器的进程映射到父容器的进程上,父容器可以知道每一个子容器的运行状态,而子容器与子容器之间是隔离的。通俗一点说,NameSpace让容器认为自己是独立系统。
想要实现一个资源隔离的容器,需要6项隔离,Linux内核提供了这6种Namespace隔离的系统调用,在同一个Namespace下的进程可以感知彼此的变化,但不了解外界的变化,因此,可以让容器中的进程以为自己在一个独立的系统环境中,达到独立和隔离的目的。Linux提供了多个API用来操作 Namespace,它们是 clone(),setns() 和 unshare()函数:
clone():创建新进程,flags参数可以用来创建新的namespace
setns():让进程加入存在的 namespace
unshare():将调用进程移动到新的 namespace中
Docker容器在实现上通过namespace技术实现进程隔离,通过cgroup技术实现容器进程可用资源的限制。Docker启动一个容器时,实际上是创建了带多个 namespace 参数的进程。
作用:资源隔离
原理:namespace 将内核的全局资源进行封装,使得每个 namespace 都有一份独立的资源。因此不同进程在各自 namespace 内对同一种资源的使用不会互相干扰。
[Step1] 查看进程所属的Namespace。从版本号为3.8的内核开始,“/proc/[pid]/ns”目录下会包含进程所属的 namesapce 信息,使用下面的命令可以查看当前进程所属的namespace信息。
// 1046为当前系统docker的进程ID
[root@redhat ~]# ls -l /proc/1046/ns 
2. Namespace隔离实例
[Step1] 基于kylinsp3镜像创建一个容器ky01,运行/bin/bash。通过ps命令可以看到“/bin/bash”是PID=1的进程,说明Docker将隔离于宿主机中的其他进程。
[root@redhat ~]# docker run -it --name ky01 kylinsp3:latest /bin/bash
[root@e75b6402786f /]# ps axf
[Step2] 查看容器进程在宿主机上的真实PID,实际上容器上运行的/bin/bash在宿主机上是7216进程。
[root@redhat ~]# docker inspect ky01 | grep Pid
[Step3]: 分别在宿主机和容器中查看该容器进程相关的namespace信息,可以发现二者都一致。
[root@redhat ~]# ll /proc/7216/ns/
[root@redhat ~]# docker exec ky01 ls -l /proc/1/ns
3. Cgroup
Cgroup:Linux Control Group。限制一个进程组对系统资源的使用上限,包括CPU、内存、Block I/O等。Cgroups还能设置进程优先级,对进程进行挂起和恢复等操作。通俗一点说,CGroup能够让容器只使用指定资源。
原理:将一组进程放进一个Cgroup中,通过给这个Cgroup分配指定的可用资源,达到控制这个一组进程可用资源的目录
实现:在Linux中,Cgroups以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。该路径下的所有资源种类均可被 cgroup 限制
二、CPU资源限制
1. 性能压测容器stress
[Step1] 下载容器镜像。
[root@redhat ~]# docker pull polinux/stress-ng
[root@redhat ~]# docker pull polinux/stress
2. CPU资源限制
[Step1] 能够通过相关参数对容器的可用CPU资源进行限制。
-c、--cpu-shares:权重值,表示该进程能使用的CPU资源权重
--cpus:限制使用的CPU数量
[Step2] 调整虚拟机的处理器和内核数量。

[Step3]: 创建两个终端,第一个终端用于创建stress01容器并在前台运行。第二个终端运行top命令,实时监控系统状态。
[root@redhat ~]# docker run --name stress01 -it -c 1024 polinux/stress-ng --cpu 1
[Step2]: 再新建一个终端,创建一个容器,CPU权重依然设置为1024。
[root@redhat ~]# docker run --name stress02 -it -c 1024 polinux/stress-ng --cpu 1[Step3] 运行top命令,实时监控系统状态,可以看到两个stress-ng-cpu进程个占用约50%。

3. 内存资源限制
默认情况先,宿主机不限制容器对内存资源的使用。可以通过相关参数可以容器的可用CPU资源进行限制:
--memory:设置内存资源的使用限额
--memory-swap:设置内存和SWAP资源的使用限额
[Step1]: 启动一个容器,限制其只能使用400M内存和100M交换分区
[root@redhat ~]# docker run -it -m 400M --memory-swap=500M polinux/stress-ng --vm 1 --vm-bytes 450M4. Block IO限制
Block IO指的是磁盘的读写,可以通过三种方式限制容器读写磁盘的带宽
设置相对权重
--blkio-weight
设置bps:每秒读写的数据量
--device-read-bps
--device-write-bps
设置iops:每秒IO次数
--device-read-iops
--device-write-iops
