Docker安全
- 1 Docker安全
- 2 容器资源控制
- 2.1 CPU限额
- 2.2 内存限制
- 2.2.1 操作系统层面内存的限制
- 2.2.2 cgconfig不同用户的限制
- 2.2.3 容器中内存的限制
- 2.3 Block IO限制
- 3 docker安全加固
1 Docker安全
(1) 命名空间隔离的安全
- 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间,命名空间提供了最基础也最直接的隔离。
- 与虚拟机方式相比,通过Linux
namespace来实现的隔离不是那么彻底;容器只是运行在宿主机上的一种特殊的进程,多个容器之间使用的就还是同一个宿主机的操作系统内核;在
Linux 内核中,有很多资源和对象是不能被 Namespace化的,比如:时间。
(2)控制组资源控制的安全
- 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
- Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。
运行容器:docker run -d --name demo nginx
- 显示 Docker 系统信息:
docker info
- 查询系统中已经mount 的cgroup的文件系统:
mount -t cgroup
- 运行容器时会在/sys/fs/cgroup/生成限制容器进程组能够使用的资源上限:
cd /sys/fs/cgroup/
tasks ##容器进程号
cpu.shares:1024
cpu.cfs_period_us:100000
cpu.cfs_quota_us:-1
2 容器资源控制
Cgroups全称Control Groups,是Linux内核提供的物理资源隔离机制,通过这种机制,可以实现对Linux进程或者进程组的资源限制、隔离和统计功能。实现 cgroups 的主要目的是为不同用户层面的资源管理提供一个统一化的接口。从单个任务的资源控制到操作系统层面的虚拟化,cgroups 提供了四大功能:
- 资源限制:cgroups 可以对任务是要的资源总额进行限制。比如设定任务运行时使用的内存上限,一旦超出就提示。
- 优先级分配:通过分配的 CPU 时间片数量和磁盘 IO 带宽,实际上就等同于控制了任务运行的优先级。
- 资源统计:cgoups 可以统计系统的资源使用量,比如 CPU 使用时长、内存用量等。这个功能非常适合当前云端产品按使用量计费的方式。
- 任务控制:cgroups 可以对任务执行挂起、恢复等操作。
Linux Cgroups 给用户暴露出来的操作接口是文件系统。它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下,路径下有诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。
控制组下面的资源文件的值,可以在用户执行 docker run 时的参数指定。
2.1 CPU限额
(1) 运行容器:docker run -it --rm busybox
- 吞吐量测试
dd if=/dev/zero of=/dev/null &
- 此时只有一个容器,独占cpu资源
(2) 运行容器(cpu限额):docker run -it --rm --cpu-quota 20000 busybox
- cpu_period 和 cpu_quota 这两个参数需要组合使用,用来限制进程在长度为cpu_period(默认100000)的一段时间内,只能被分配到总量为 cpu_quota 的 CPU 时间为20000
- 吞吐量测试
dd if=/dev/zero of=/dev/null &
- 查看容器的进程号:
cd /sys/fs/cgroup
- 查看此时容器占用cpu的资源大约为总的20%
(3) 多个进程占用的cpu资源
- 由于虚拟机是两个cpu,为了实验效果明显,关闭cpu1:
cd /sys/devices/system/cpu/cpu1/
- 查看cpu的详细信息:
lscpu
- 运行两个容器
docker run -it --rm busybox
dd if=/dev/zero of=/dev/null & ##ctrl+p+q退出容器
docker run -it --rm busybox
dd if=/dev/zero of=/dev/null & ##ctrl+p+q退出容器
- 由于未设置cpu的优先级,此时两个容器的占用cpu资源的优先级相同
- 关闭运行的第二个容器,此时cpu资源由第一个容器占用
- 运行容器时划分cpu的比例(默认1024):
docker run -it --rm --cpu-shares 512 busybox
dd if=/dev/zero of=/dev/null & ##ctrl+p+q退出容器
- 查看容器占用cpu资源的情况,18140进程划分的cpu资源是1024,18595进程划分的cpu资源是512,所有18140进程占用的资源是18595进程占用cpu资源的2倍
2.2 内存限制
2.2.1 操作系统层面内存的限制
进入cgroup的memory子目录:cd /sys/fs/cgroup/memory
mkdir dir
cd dir/ ##(从父集继承的文件)
echo 104857600 > memory.memsw.limit_in_bytes ##100*1024*1024(100M)
cat memory.memsw.limit_in_bytes ##内存和swap分区限额为100M
- cgexec命令可以直接在命令行控制资源组 :
必须在/dev/shm内存空间下写入
cgexec -g memory:dir dd if=/dev/zero of=bigfile bs=1M count=200
- 因为划分的内存和swap限额为100M,现在划分200超过了限额,命名行会输出killed提示,bigfile的文件不会超过100M
2.2.2 cgconfig不同用户的限制
(1) 新建用户:useradd user1
(2) 编辑/etc/cgrules.conf规则文件:vim /etc/cgrules.conf
- cgrules.conf规则文件需要填写用户 限制类型 限制策略
(3) 重启服务:systemctl start cgred.service
(重新读取 /etc/cgrules.conf )
(4) 测试
su - user1 ##切换用户
cd /dev/shm ##必须在/dev/shm内存空间下写入
dd if=/dev/zero of=bigfile bs=1M count=100 ##写入100M的内存,被限制
du -h bigfile ##最大不会超过100M
2.2.3 容器中内存的限制
容器可用内存包括两个部分:物理内存和swap交换分区
(1) 运行容器:
docker run -it --rm --memory 100M --memory-swap 100M busybox
## -memory设置内存使用限额
## --memory-swap设置swap交换分区限额
(2) 进入cgroup的memory目录:cd /sys/fs/cgroup/memory/
- memory.memsw.limit_in_bytes :内存和swap分区限额为100M
2.3 Block IO限制
(1) 运行容器:docker run -it --device-write-bps /dev/vda:30M ubuntu
限制写设备/dev/vda的bps为30M
dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
## 目前的block IO限制只对direct IO有效。(不使用文件缓存)
(2) 进入cgroup的blkio目录:cd /sys/fs/cgroup/blkio
cd docker/
cat blkio.throttle.write_bps_device ##写设备的bps限制31457280/(1024*1024)=30M
3 docker安全加固
(1) 利用LXCFS增强docker容器隔离性和资源可见性
[root@server2 lxcfs]# docker run -it -m 100m \
> -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
root@16ca4a215221:/# free -m
total used free shared buff/cache available
Mem: 100 0 99 31 0 99
Swap: 100 0 100
(2) 设置特权级运行的容器:--privileged=true
有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交换分区,挂载USB磁盘,修改MAC地址等。
- 运行容器:
docker run -it --rm busybox
- 禁用eth0:
ip link set down dev eth0
,在root用户下,也没执行禁用的命令
- 查看正在运行的容器:
docker ps
- 查看容器的信息:
docker inspect a89a3e58baf2
- 在运行容器的时候设置特权:docker run -it --rm --privileged=true busybox
- 查看容器的信息
docker ps
docker inspect c7c7d83b070e
(3) 设置容器白名单:–cap-add
privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用–cap-add添加必要的权限。
- 在运行容器的时候指定修改网络接口数据:
--cap-add=NET_ADMIN
,可以执行修改网络接口数据的命令
docker run -it --rm --cap-add=NET_ADMIN busybox
- 查看容器的信息
docker ps
docker inspect 165eac6741ea