目录
一、cgroup简介
二、 容器资源控制
1、内存限制
?2、cpu限额
?3、Block IO限制
?三、docker 安全加固
在使用 docker 运行容器时,默认的情况下,docker没有对容器进行硬件资源的限制,当一台主机上运行几百个容器,这些容器虽然互相隔离,但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制,那么容器之间会互相影响,小的来说会导致容器资源使用不公平;大的来说,可能会导致主机和集群资源耗尽,服务完全不可用。
docker 作为容器的管理者,自然提供了控制容器资源的功能。正如使用内核的 namespace 来做容器之间的隔离,docker 也是通过内核的 cgroups 来做容器的资源限制;包括CPU、内存、磁盘三大方面,基本覆盖了常见的资源配额和使用量控制
一、cgroup简介
?? Linux Cgroups 的全称是 Linux Control Group。 是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。 对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。 Linux Cgroups 给用户暴露出来的操作接口是文件系统。 它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。 执行此命令查看:mount -t cgroup???
?? 在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。 在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。 控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。
docker ps docker run -d --name demo nginx ##运行一个容器 docker ps docker inspect demo ##查看demo信息 docker inspect demo | grep Pid ##可以看到pid为3904,是一个进程 cd /proc/3904/ ls cd ns ?ls ##可以看到有6种ns ll -d /var/lib/docker/? #docker所有信息都在这个目录中,继承超级用户权限 rpm -qa | grep docker ##有无根模式
?
二、 容器资源控制
1、内存限制
docker run --help | grep memory docker ps docker rm -f demo docker run --rm -it --memory 200M busybox ##运行容器限制使用内存200M free -m? ##容器内和宿主机 的内存信息共享 ll -d /proc/meminfo ##内存信息存储目录
docker ps docker inspect 8eaf11fb38be ##可以看到设置的内存200M docker ps docker rm -f? brave_driscoll?
docker run -d --name demo -m 200M nginx docker ps mount -t cgroup ##可以看到以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下 cd /sys/fs/cgroup/ ?ls ?cd memory/ ls cd docker/ ls ##可以看到运行的容器 cd ee9e314442a1946014927017f4f34bfd956d8e780bb531c494607b8df49dddb3 ?ls cat memory.limit_in_bytes##查看内存控制的资源限制,200M说明已经受限
docker run -d --name demo2 nginx ##再开一个容器不做内存限制 cd - #切换到之前的目录 cd .. ls ##可以看到demo2容器id cd 3955d8631839ffc805157981b147aab75fd4008e68974d438c1483be9b769743 ls cat memory.limit_in_bytes ##查看内存限制,没有限制 cd .. pwd 所有的docker 容器都在这个docker 目录中,这个目录里面的信息都是继承父级memory子系统的 ?ls cd .. ls cat memory.limit_in_bytes mkdir x1##创建x1控制器 cd x1/ ls 里面内容继承父级子系统的 cat? memory.limit_in_bytes echo 209715200 > memory.limit_in_bytes 给予200M内存使用量 cat? memory.limit_in_bytes
cd df #可以看到tmpfs挂接的是物理机的1/2的内存 cd /dev/shm/ ls free -m ##查看内存 dd if=/dev/zero of=bigfile bs=1M count=100 ##在此目录下写数据耗费的是内存 free -m ##空闲少了100M内存 ls rm -f bigfile free -m #删除刚建立的文件,物理内存还原 vmstat ##此命令也可以查看内存使用量 free -m
dd if=/dev/zero of=bigfile bs=1M count=300 free -m ##可以看到少了300M cd /sys/fs/cgroup/memory/x1/ ls cat memory.limit_in_bytes #可以看到设置的内存限制为200M id ##因为使用的是超级用户,不受限制 cd - ?ls rm -f bigfile free -m cd - ls cat tasks ##要使之生效,必须将其加入到进程任务中 yum search cgroup yum? install -y libcgroup-tools.x86_64 cd - ls cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300 ###内存子系统x1控制器 控制物理内存不能超过200
free -m #可以看到物理内存少了200M,但是swap分区也使用了100M rm -f bigfile free -m cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300 ?free -m ##swap交换分区是物理内存不够用时备用的
rm -f bigfile cd - ls ?docker run --help | grep memory cat? memory.memsw.limit_in_bytes#内存和swap总共限制资源 cat memory.limit_in_bytes echo 209715200 > memory.memsw.limit_in_bytes ##给予200M ?cat? memory.memsw.limit_in_bytes cd - cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300 ##命令被kill,swap不可用 free -m du -h bigfile ##文件大小为200M
docker ps docker inspect demo | grep Pid ##过滤出demo的pid cd /sys/fs/cgroup/memory/ 进入memory控制器 ls cd docker/ ?ls 可以看到运行容器ID cd ee9e314442a1946014927017f4f34bfd956d8e780bb531c494607b8df49dddb3 进入demo ls cat tasks ##容器内所有的进程都可以看到 cd .. ls cd 3955d8631839ffc805157981b147aab75fd4008e68974d438c1483be9b769743 进入demo2 ls cat tasks #容器的进程还有容器内nginx其他进程,都是自动添加 docker inspect demo2 | grep Pid cd docker run --help | grep cpu ##针对cpu 的限制 docker run --help | grep devi ##还有设备io的
? 2、cpu限额
Linux 通过 CFS(Completely Fair Scheduler,完全公平调度器)来调度各个进程对 CPU 的使用。CFS 默认的调度周期是 100ms。
我们可以设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少 CPU 时间。使用--cpu-period即可设置调度周期,使用--cpu-quota即可设置在每个周期内容器能使用的 CPU 时间。两者一般配合使用。
?cd /sys/fs/cgroup/ ls cd cpu ?ls mkdir x2 cd x2/? ##继承父级子系统的文件 ls cat cpu.cfs_quota_us #-1 表示没有任何限制 cat cpu.cfs_period_us echo 20000 >? cpu.cfs_quota_us ##表示20%的cpu运行时间每100ms cat cpu.cfs_quota_us dd if=/dev/zero of=/dev/null & ##此动作会直接占据cpu top ##top命令查看cpu占用 cd /sys/devices/system/ ?ls cd cpu/ ?ls ##cpu0不可以被关闭 cd cpu1/ ?ls cat online echo 0 > online 设置关闭cpu1 ?cat online top ##按“1”可以看到只有cpu0运行,cpu1被关闭 echo 1 > online ##重启开启cpu1 top
?cd /sys/fs/cgroup/ ?ls cd cpu/ ##进入cpu进程 cd x2/ ls echo 6205 > tasks #把dd进程id直接放入task 中 cat tasks top #查看到%cpu为20% kill 6205 #不需要时可以kill top
cd docker ps docker rm -f demo docker rm -f demo2 docker run -d? --cpu-period=100000 --cpu-quota=20000 --name demo nginx##运行容器将 CFS 调度的周期设为 100000,将容器在每个周期内的 CPU 配额设置为 20000,表示该容器每 100ms 可以得到 20% 的 CPU 运行时间 docker ps cd /sys/fs/cgroup/ ls cd cpu cd docker/ ls ?cd def37a843dfc59e92d781f7e7e7ec0ee6831202d6cb3154175d93e15159f83d8 ls ?cat cpu.cfs_quota_us 自动设置CPU 配额为 20000
3、Block IO限制
docker run -it --device-write-bps /dev/vda:30MB centos:7 ##--device-write-bps限制写设备的bps速率为30MB/s
--/# dd if=/dev/zero of=/bigfile bs=1M count=200 oflag=direct?#目前的block IO限制只对direct IO有效。(不使用文件缓存)
可以看到速率为31.6MB/s
docker run -it centos:7 ##不加速率限制运行,可以看到速率达到863MB/s docker container prune docker ps -a docker rm -f demo
三、docker 安全加固
?
在容器内查看内存时显示的是宿主机的内存信息,为了安全起见有时候需要做限制
docker run --rm -it --memory 200M busybox
/ # free -m #给了200M但是swap出现的还是2G
*proc是没有做隔离的,所以容器和宿主机看到的是一样的【直接访问的是根下的proc】
cd /proc/ ?ls cd ?ls yum install -y?? lxcfs-2.0.5-3.el7.centos.x86_64.rpm ?lxcfs /var/lib/lxcfs & ##运行软件打入后台 ?ps ax ?cd? /var/lib/lxcfs/? 默认的数据目录:/var/lib/lxcfs/ ls??? #会生成相应的cgroup和proc
cd cgroup/ ls cd .. cd proc/ ?ls? #可以看到每一个文件都分别代表宿主机的6样信息
把lxcfs-2.0.5-3.el7.centos.x86_64.rpm从真机中传到docker1
利用LXCFS增强docker容器隔离性和资源可见性?
?
docker run? -it -m 256m?????? -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw?????? -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw?????? -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw?????? -v /var/lib/lxcfs/proc/stat:/proc/stat:rw?????? -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw?????? -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw centos:7? ##此时运行容器,运行时将lxcfs数据目录下的内容挂载到容器内
--/# free -m ? #可以看到swap分区有200M
docker container prune docker run --rm -it busybox
--/ # ip addr
--/ # ip link set down dev eth0 ?#执行命令没有操作权限,不允许
--/ # id ?#可以看到是超级用户默认在运行容器时容器内的用户并不是真正的root用户
设置特权级运行的容器:--privileged=true 有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交换分区,挂载USB磁盘,修改MAC地址等?
docker run --rm -it --privileged=true busybox##可以执行ip link set
这个权限比较大,接近于宿主机的root用户,为了防止用户权限的滥用,需要增加权限,只提供给容器必须的权限。此时Docker提供了权限白名单的机制,使用–cap-add添加必要的权限。 docker run --rm -it --cap-add=NET_ADMIN busybox ##容器具有网络管理的权限
-/ # fdisk -l ?#看不到磁盘分区
docker run --rm -it --privileged=true busybox ##可以查看磁盘
?
?
|