Docker-资源隔离、资源控制
1、资源隔离
1.1、需求
在一个操作系统中,启动了多个应用容器,那么这些应用容器如何来保障互相的操作不受影响?
-- 资源隔离
1.2、简介
Linux内核实现namespace的主要目的,就是为了实现轻量级虚拟化技术服务。在同一个namespace下的进程合一感知彼此的变化,而对外界的进程一无所知。
Docker通过linux的 pid、net、ipc、mnt、uts、user这六类的namespace将容器的进程、网络、消息、文件系统、UTS和操作系统资源隔离开。
从而让容器中的进程产生错觉,仿佛自己置身一个独立的系统环境中,以达到隔离的目的。
1.3、namespace
1.3.1、分类
namespace 系统调用参数 隔离内容
UTS CLONE_NEWUTS 主机名或域名
IPC CLONE_NEWIPC 信号量、消息队列和共享内存
PID CLONE_NEWPID 进程编号
Network CLONE_NEWNET 网络设备、网络战、端口等
Mount CLONE_NEWNS 挂载点(文件系统)
User CLONE_NEWUSER 用户组和用户组
Time CLONE_NEWTIME 启动和单调时钟
1.3.2、通过命令查询ns
]# ps -aux | grep docker | grep -v grep root 32141 0.0 1.9 1096140 72988 ? Ssl 15:16 0:03 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
]# ll /proc/32141/ns/ lrwxrwxrwx. 1 root root 0 5月 18 18:51 ipc -> ipc:[4026531839] lrwxrwxrwx. 1 root root 0 5月 18 18:51 mnt -> mnt:[4026531840] lrwxrwxrwx. 1 root root 0 5月 18 18:51 net -> net:[4026531956] lrwxrwxrwx. 1 root root 0 5月 18 18:51 pid -> pid:[4026531836] lrwxrwxrwx. 1 root root 0 5月 18 18:51 user -> user:[4026531837] lrwxrwxrwx. 1 root root 0 5月 18 18:51 uts -> uts:[4026531838]
1.4、环境准备
1.4.1、启动2个nginx容器【nginx80,nginx81】
docker run -d --rm --name nginx80 nginx
docker run -d --rm --name nginx81 nginx
1.4.2、查询基本信息
docker inspect nginx80
docker inspect nginx81
1.5、隔离级别-实战
1.5.1、文件系统隔离
# nginx80 ]# docker exec -it nginx80 cat /proc/self/mountinfo | head -5 185 122 0:51 / / rw,relatime master:68 - overlay overlay rw,seclabel,lowerdir=/var/lib/docker/overlay2/l/2IYIZJRREC556PKKX43OBOFM5W:/var/lib/docker/overlay2/l/2UFXEGQEPFQFJD7FSGBOJZOEFF:/var/lib/docker/overlay2/l/54URWT4BBGRSLW4CMO6EDCWNP5:
/var/lib/docker/overlay2/l/HJCFS3MVHVODBCH3ITLJJAMKX4:/var/lib/docker/overlay2/l/BOZLGSVQXEAZ7YORN76HBA7GJH:/var/lib/docker/overlay2/l/3BVRX2BKGYF5V56C4PCECSOSFS:/var/lib/docker/overlay2/l/6LEGS22UCMTWB5QBNC5TO3GIV3,upperdir=/var/lib/docker/
overlay2/be42eef2b650ab981e4bd9141ddaeaff0aae3fe7317d6b4cb0f8edaae06caf9d/diff,workdir=/var/lib/docker/overlay2/be42eef2b650ab981e4bd9141ddaeaff0aae3fe7317d6b4cb0f8edaae06caf9d/work 186 185 0:53 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw 187 185 0:54 / /dev rw,nosuid - tmpfs tmpfs rw,seclabel,size=65536k,mode=755 188 187 0:55 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=666 189 185 0:56 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro,seclabel # nginx81 ]# docker exec -it nginx81 cat /proc/self/mountinfo | head -5 238 174 0:63 / / rw,relatime master:71 - overlay overlay rw,seclabel,lowerdir=/var/lib/docker/overlay2/l/PI3ZEHEP46H5BW6II33FK3SFLS:/var/lib/docker/overlay2/l/2UFXEGQEPFQFJD7FSGBOJZOEFF:/var/lib/docker/overlay2/l/54URWT4BBGRSLW4CMO6EDCWNP5:
/var/lib/docker/overlay2/l/HJCFS3MVHVODBCH3ITLJJAMKX4:/var/lib/docker/overlay2/l/BOZLGSVQXEAZ7YORN76HBA7GJH:/var/lib/docker/overlay2/l/3BVRX2BKGYF5V56C4PCECSOSFS:/var/lib/docker/overlay2/l/6LEGS22UCMTWB5QBNC5TO3GIV3,upperdir=/var/lib/docker/
overlay2/abf9cd19e452f4922e0258b4bef1b35b8601aedae3dde5dde161e4287b4eaa7f/diff,workdir=/var/lib/docker/overlay2/abf9cd19e452f4922e0258b4bef1b35b8601aedae3dde5dde161e4287b4eaa7f/work 239 238 0:65 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw 240 238 0:66 / /dev rw,nosuid - tmpfs tmpfs rw,seclabel,size=65536k,mode=755 241 240 0:67 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=666 242 238 0:68 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro,seclabel # 发现到workdir是不一样的
1.5.2、UTC资源隔离
]# cat /var/lib/docker/containers/ea887c4677393fde4dcd98709f21769e551e312d51014faf1d91029a1db221b9/hostname ea887c467739
]# cat /var/lib/docker/containers/ea887c4677393fde4dcd98709f21769e551e312d51014faf1d91029a1db221b9/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.4 ea887c467739
1.5.3、IPC资源隔离
# 宿主机的IPCS ]# ipcmk -Q 消息队列 id:0 ]# ipcs --------- 消息队列 ----------- 键 msqid 拥有者 权限 已用字节数 消息 0x48951c54 0 root 644 0 0 ------------ 共享内存段 -------------- 键 shmid 拥有者 权限 字节 nattch 状态 --------- 信号量数组 ----------- 键 semid 拥有者 权限 nsems # 容器的IPCS ]# docker exec -it nginx80 /bin/bash root@2bcea13a72c7:/# ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status ------ Semaphore Arrays -------- key semid owner perms nsems ipcmk -Q # 建立一个消息队列 ipcs # 查看消息情况
1.5.4、PID资源隔离
# 宿主机的PID ]# docker inspect --format '{{.State.Pid}}' nginx80 51094 ]# pstree -g 51094 nginx(51094)───nginx(51094) # 容器内的PID ]# docker exec -it nginx80 /bin/bash root@2bcea13a72c7:/# pstree -g nginx(1)---nginx(1)
1.5.5、net资源隔离
]# ls /var/lib/docker/network/files/local-kv.db /var/lib/docker/network/files/local-kv.db ]# docker exec -it nginx80 ifconfig | grep inet inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255 inet 127.0.0.1 netmask 255.0.0.0 ]# docker exec -it nginx81 ifconfig | grep inet inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255 inet 127.0.0.1 netmask 255.0.0.0
1.5.6、User资源隔离
]# docker exec -it nginx80 id uid=0(root) gid=0(root) groups=0(root)
]# docker exec -it nginx81 id uid=0(root) gid=0(root) groups=0(root)
2、资源控制
2.1、基础知识
2.1.1、简介
对于容器的资源限制,LXC给出的方法是Cgroup,Cgroup 全称Control group,Docker把它继承过来了。
CGroup其实就是通过创建一个虚拟的文件系统交给容器使用,同时还能对容器的容量做出限制。
通过CGroup可以实现的功能:资源限制、优先级分配、资源统计、任务控制
2.1.2、默认情况下,资源限制的功能已经开启
]# grep -i cgroup /boot/config-3.10.0-1160.el7.x86_64 CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_SCHED=y CONFIG_BLK_CGROUP=y # CONFIG_DEBUG_BLK_CGROUP is not set CONFIG_NETFILTER_XT_MATCH_CGROUP=m CONFIG_NET_CLS_CGROUP=y CONFIG_NETPRIO_CGROUP=y
2.1.3、系统cgroup的体现
]# ll /sys/fs/cgroup/ drwxr-xr-x. 5 root root 0 5月 15 03:41 blkio lrwxrwxrwx. 1 root root 11 5月 15 03:41 cpu -> cpu,cpuacct lrwxrwxrwx. 1 root root 11 5月 15 03:41 cpuacct -> cpu,cpuacct drwxr-xr-x. 5 root root 0 5月 15 03:41 cpu,cpuacct drwxr-xr-x. 3 root root 0 5月 15 03:41 cpuset drwxr-xr-x. 5 root root 0 5月 15 03:41 devices drwxr-xr-x. 3 root root 0 5月 15 03:41 freezer drwxr-xr-x. 3 root root 0 5月 15 03:41 hugetlb drwxr-xr-x. 5 root root 0 5月 15 03:41 memory lrwxrwxrwx. 1 root root 16 5月 15 03:41 net_cls -> net_cls,net_prio drwxr-xr-x. 3 root root 0 5月 15 03:41 net_cls,net_prio lrwxrwxrwx. 1 root root 16 5月 15 03:41 net_prio -> net_cls,net_prio drwxr-xr-x. 3 root root 0 5月 15 03:41 perf_event drwxr-xr-x. 5 root root 0 5月 15 03:41 pids drwxr-xr-x. 5 root root 0 5月 15 03:41 systemd
2.1.4、以CPU限制为例
]# tree /sys/fs/cgroup/cpu/docker /sys/fs/cgroup/cpu/docker ├── 2bcea13a72c7ab25d8ce8067c1f4a97e9532b09380318d57ea7f1b9f6a79ed23 │ ├── cgroup.clone_children │ ├── cgroup.event_control │ ├── cgroup.procs │ ├── cpuacct.stat │ ├── cpuacct.usage │ ├── cpuacct.usage_percpu │ ├── cpu.cfs_period_us │ ├── cpu.cfs_quota_us │ ├── cpu.rt_period_us │ ├── cpu.rt_runtime_us │ ├── cpu.shares │ ├── cpu.stat │ ├── notify_on_release │ └── tasks ├── 61a640daad394d4c1d6e44bd184fd44fdbdd955175cb7da4931a4868cd3cd155 │ ├── cgroup.clone_children │ ├── cgroup.event_control │ ├── cgroup.procs │ ├── cpuacct.stat │ ├── cpuacct.usage │ ├── cpuacct.usage_percpu │ ├── cpu.cfs_period_us │ ├── cpu.cfs_quota_us │ ├── cpu.rt_period_us │ ├── cpu.rt_runtime_us │ ├── cpu.shares │ ├── cpu.stat │ ├── notify_on_release │ └── tasks
2.2、资源限制的命令和工具介绍
2.2.1、简介
默认情况下,容器没有资源的 "使用限制" -- 可以使用尽可能多的主机资源。 Docker提供了控制容器使用资源的方法,可以限制当前容器可以使用的内存数量和cpu资源。我们可以通过docker run的参数来进行简单的控制
2.2.2、资源限制的命令
]# docker run --help | grep -iE 'cpu|oom|memory'
--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)
--kernel-memory bytes Kernel memory limit
-m, --memory bytes Memory limit
--memory-reservation bytes Memory soft limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)
--oom-kill-disable Disable OOM Killer
--oom-score-adj int Tune host's OOM preferences (-1000 to 1000)
2.2.3、docker-stress-ng压测工具的介绍
网上有一个非常好的容器压力测试工具,docker-stress-ng 我们可以基于该镜像来进行各种容量的限制测试 # 查看帮忙信息 ]# docker run -it --rm lorel/docker-stress-ng:latest | grep -iE 'cpu|mem' --affinity N start N workers that rapidly change CPU affinity -C N, --cache N start N CPU cache thrashing workers --cache-flush flush cache after every memory write (x86 only) -c N, --cpu N start N workers spinning on sqrt(rand()) --cpu-ops N stop when N cpu bogo operations completed -l P, --cpu-load P load CPU by P %%, 0=sleep, 100=full load (see -c) --cpu-method m specify stress cpu method m, default is all --memcpy N start N workers performing memory copies --memcpy-ops N stop when N memcpy bogo operations completed --vm-hang N sleep N seconds before freeing memory --vm-keep redirty memory instead of reallocating --vm-locked lock the pages of the mapped region into memory
2.3、内存资源限制-实战
2.3.1、开启两个work的容器,每个work默认占256m,当前容器占 512m【--vm】
]# docker run --name mem_stress -it --rm lorel/docker-stress-ng:latest --vm 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm ]# docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 280cbd4988f8 mem_stress 99.41% 514.2MiB / 3.612GiB 13.90% 656B / 0B 0B / 0B 5
2.3.2、调整最大的容器内存量为 100m【-m】
# 关闭容器后,调整最大的容器内存量为 100m ]# docker run --name mem_stress -it --rm -m 100m lorel/docker-stress-ng:latest --vm 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm ]# docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS db65e6d9b724 mem_stress 95.49% 99.94MiB / 100MiB 99.94% 656B / 0B 3.6MB / 12.6GB 5
2.4、CPU资源限制-实战
2.4.1、查看当前的cpu信息
]# lscpu | grep CPU CPU op-mode(s): 32-bit, 64-bit CPU(s): 1 On-line CPU(s) list: 0 CPU 系列: 23 CPU MHz: 2894.563 NUMA 节点0 CPU: 0
2.4.2、开启使用两个cpu的容器【--cpu】
]# docker run --name cpu_stress -it --rm lorel/docker-stress-ng:latest --cpu 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 cpu # 查看状态 ]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 7f58ff01d9ef cpu_stress 100.06% 6.016MiB / 3.612GiB 0.16% 656B / 0B 0B / 0B 3
2.4.3、调整cpu的使用数量为1,压测的CPU为2【--cpus】
# 限制只能使用一半的CPU ]# docker run --name cpu_stress -it --rm --cpus 0.5 lorel/docker-stress-ng:latest --cpu 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 cpu # 查看状态 ]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 514173c9426a cpu_stress 50.29% 6.016MiB / 3.612GiB 0.16% 586B / 0B 0B / 0B 3
2.4.5、定制cpu绑定操作【--cpuset-cpus】
]# docker run -it --rm --name cpu_stress --cpus 0.5 --cpuset-cpus 0 lorel/docker-stress-ng:latest --cpu 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 cpu ]# docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 9cef3ce365c9 cpu_stress 49.97% 6.023MiB / 3.612GiB 0.16% 656B / 0B 0B / 0B 3