docker安全--安全理解、容器资源限制、安全加固
文章目录一、docker安全理解命名空间隔离机制控制组资源控制的安全二、容器资源限制1.cpu限额2.内存限额3.Block IO限制(磁盘IO)三、安全加固一、docker安全理解Docker容器的安全性,很大程度上依赖于Linux系统自身,评估Docker的安全性时,主要考虑以下几个方面:Linux内核的命名空间机制提供的容器隔离安全Linux控制组机制对容器资源的控制能力安全。Linux内核
一、docker安全理解
Docker容器的安全性,很大程度上依赖于Linux系统自身,评估Docker的安全性时,主要考虑以下几个方面:
Linux内核的命名空间机制
提供的容器隔离安全
Linux控制组机制
对容器资源的控制能力安全。
Linux内核的能力机制
所带来的操作权限安全
Docker程序(特别是服务端)本身的抗攻击性。
其他安全增强机制对容器安全性的影响。
命名空间隔离机制
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。
容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,比如:时间
。
控制组资源控制的安全
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源
。
确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS)方面必不可少。
[root@server2 ns]# cd /sys/fs/cgroup/
[root@server2 cgroup]# cd cpu/docker/
[root@server2 docker]# ls
24153aebd9f6408cd54dd649e9fbc1991e54af3ce7bf38c9995e76887abd5fdc
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
[root@server2 docker]# cd 24153aebd9f6408cd54dd649e9fbc1991e54af3ce7bf38c9995e76887abd5fdc
[root@server2 24153aebd9f6408cd54dd649e9fbc1991e54af3ce7bf38c9995e76887abd5fdc]# cat tasks
3863
3919
[root@server2 24153aebd9f6408cd54dd649e9fbc1991e54af3ce7bf38c9995e76887abd5fdc]# cat cpu.shares
1024
[root@server2 24153aebd9f6408cd54dd649e9fbc1991e54af3ce7bf38c9995e76887abd5fdc]# cat cpu.cfs_period_us
100000
cgroup为默认的资源控制组:
二、容器资源限制
Linux Cgroups 的全称是
Linux Control Group
。是限制一个进程组能够使用的资源上限
,包括 CPU、内存、磁盘、网络带宽等等。对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。
Linux Cgroups 给用户暴露出来的操作接口是文件系统。它以文件和目录的方式组织在操作系统的/sys/fs/cgroup
路径下。执行此命令查看:mount -t cgroup
在 /sys/fs/cgroup 下面有很多诸如cpuset、cpu、 memory 这样的子目录
,也叫子系统。在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。
docker对资源的控制实际上是借助Linux内核
完成的
1.cpu限额
[root@server2 docker]# docker run --help|grep cpu %docker在启动时支持的cpu设置选项
--cpu-period int Limit CPU CFS (Completely Fair
--cpu-quota int Limit CPU CFS (Completely Fair
--cpu-rt-period int Limit CPU real-time period in
--cpu-rt-runtime int Limit CPU real-time runtime in
-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution
--cpuset-mems string MEMs in which to allow execution
[root@server2 docker]# docker run -it --rm --cpu-quota 20000 ubuntu %分配20%
root@5f0341552d2d:/# dd if=/dev/zero of=/dev/null & %进入容器内部使用dd命令测试cpu的负载情况
[1] 9
此时我们打开另一个终端连接server2,使用top命令监控cpu的负载情况
该主机有两个cpu,我们设置使用一个cpu,然后开启两个容器来测试cpu资源的争抢情况:
[root@server2 docker]# cd /sys/devices/system/cpu/
[root@server2 cpu]# ls
cpu0 isolated modalias offline possible present uevent
cpuidle kernel_max nohz_full online power smt vulnerabilities
cd cpu1/
echo 0 > online %让cpu1下线
[root@server2 cpu]# docker run -it --rm ubuntu
root@21b61f7b5866:/# dd if=/dev/zero of=/dev/null &
[1] 9
##ctrl+p+q %退出但不停止容器运行
root@21b61f7b5866:/# [root@server12 cpu]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
21b61f7b5866 ubuntu "/bin/bash" 33 seconds ago Up 31 seconds loving_chebyshev
[root@server2 cpu]# docker run -it --rm ubuntu
root@e84802289cf8:/# dd if=/dev/zero of=/dev/null &
[1] 9
此时top监控cpu负载发现两个容器各占50%
root@e84802289cf8:/# exit %退出正在运行的容器
[root@server12 cpu]# docker run --rm --cpu-shares 512 ubuntu %删除容器
[root@server12 cpu]# docker run -it --rm --cpu-shares 512 ubuntu %开启一个新的容器并设置cpu共享优先级是512,是默认1024的一半,因此第二个容器分配到的cpu资源也是第一个容器的二分之一
root@ea83d0afa54d:/# dd if=/dev/zero of=/dev/null & %做压力测试
[1] 9
2.内存限额
docker默认对容器内存的使用没有限制,
有多少用多少
,当然我们可以来根据自己的具体需要定义
我们先介绍一下linux内核自带的对用户使用内存的限制方法:
[root@server2 cpu]# cd /sys/fs/cgroup/memory/
[root@server2 memory]# mkdir x1
[root@server2 x1]# yum install -y libcgroup-tools.x86_64
[root@server2 x1]# ls
[root@server2 x1]# echo 209715200 > memory.memsw.limit_in_bytes %内存+swap一共给200M
[root@server2 x1]# cd /dev/shm
[root@server2 shm]# df
tmpfs 1023544 0 1023544 0% /dev/shm
[root@server2 shm]# free -m
total used free shared buff/cache available %avaolable=free+buff/cache
Mem: 1999 194 1164 16 640 1622
Swap: 2047 0 2047
[root@server2 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300 %创建300M大小内存空间,并指定内存控制器为memory:x1
Killed %300M超过内存限制,进程直接被kill
[root@server2 shm]# free -m
total used free shared buff/cache available
Mem: 1999 194 1164 16 640 1423 %available大小减小200M,因为内存最大限制为200M
Swap: 2047 0 2047
[root@server2 shm]# du -h bigfile %只给用200M,多了不让用
199M
[root@server2 shm]# rm -fr bigfile
针对用户设置:
[root@server2 ~]# useradd wxh
[root@server2 ~]# vim /etc/cgrules.conf
wxh memory x1/ %最后一行添加
[root@server2 ~]# systemctl start cgred.service %启动相关服务
[root@server2 ~]# su - wxh %切换用户
[wxh@server2 ~]$ dd if=/dev/zero of=bigfile bs=1M count=200
Killed %因为切换用户也会有内存消耗,因此虽然限制了200M,但创建200M大小内存空间时仍会失败
[wxh@server2 shm]$ free -m
total used free shared buff/cache available
Mem: 1999 200 953 214 845 1417
Swap: 2047 0 2047
[wxh@server2 shm]$ du -h bigfile
199M bigfile
[wxh@server2 shm]$ exit
logout
[root@server2 shm]# vim /etc/cgrules.conf %删除最后一行wxh,重启服务
[root@server2 shm]# systemctl restart cgred.service
[root@server2 shm]# su - wxh
Last login: Thu Jan 28 19:14:43 +08 2021 on pts/0
[wxh@server2 ~]$ cd /dev/shm/
[wxh@server2 shm]$ ls
bigfile
[wxh@server2 shm]$ dd if=/dev/zero of=bigfile bs=1M count=200 %此时不受内存限制
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.786068 s, 267 MB/s
容器资源控制示例:
[root@server2 shm]# docker run -d --name demo --memory 200M --memory-swap 200M nginx %--memory设置内存使用限额 --memory-swap设置swap交换分区限额
[root@server2 ~]# cd /sys/fs/cgroup/memory/docker/
[root@server2 docker]# ls
f305b8af8799d94ae14316fa847057bbcad163f022de1287e3121341c8f08f5e
[root@server2 docker]# cd f305b8af8799d94ae14316fa847057bbcad163f022de1287e3121341c8f08f5e
[root@server2 f305b8af8799d94ae14316fa847057bbcad163f022de1287e3121341c8f08f5e]# cat memory.limit_in_bytes
209715200 %由于启动容器时已经设置了内存限制,因此这里的参数也随之更改了
[root@server2 f305b8af8799d94ae14316fa847057bbcad163f022de1287e3121341c8f08f5e]# cat memory.memsw.limit_in_bytes
209715200
3.Block IO限制(磁盘IO)
[root@server2 shm]# docker run -it --device-write-bps /dev/vda:30MB ubuntu %指定往/dev/vda设备中的写入速度为30M每秒
root@1bde4226e5a8:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct %oflag=direct参数定义直接往硬盘中写入而不经过内存
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 3.31855 s, 31.6 MB/s
三、安全加固
系统中
有一些资源凭借namespace机制是无法隔离的
,因此我们就需要借助其它工具来实现这一目的
利用LXCFS增强docker容器隔离性和资源可见性:
yum install -y lxcfs-2.0.5-3.el7.centos.x86_64.rpm %安装相关rpm包
lxcfs /var/lib/lxcfs & %执行并打入后台
docker run -it -m 256m \ %运行相关容器,并把相关资源直接挂载到/proc/目录下来做资源的隔离,指定资源的大小为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 \
ubuntu
设置特权级运行的容器:--privileged=true
有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交换分区,挂载USB磁盘,修改MAC地址等。
[root@server2 ~]# docker run -it --rm --privileged=true busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ip addr add 172.17.0.10/24 dev eth0 %设置完--privileged=true参数后,我们可以进行添加ip,设置网卡down等操作
/ # ping 172.17.0.10
PING 172.17.0.10 (172.17.0.10): 56 data bytes
64 bytes from 172.17.0.10: seq=0 ttl=64 time=0.071 ms
64 bytes from 172.17.0.10: seq=1 ttl=64 time=0.052 ms
^C
--- 172.17.0.10 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.052/0.061/0.071 ms
/ # ip addr del 172.17.0.10/24 dev eth0
设置容器白名单:--cap-add
--privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限。
[root@server2 ~]# docker run -it --rm --cap-add=NET_ADMIN busybox %添加--cap-add=NET_ADMI参数,可以对网络进行更改
/ # ip link set down dev eth0
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
29: eth0@if30: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ip link set up dev eth0
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
29: eth0@if30: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
更多推荐
所有评论(0)