1、docker安全简介
[root@server1 ~]# docker inspect -f '{{.State.Pid}}' demo 查看容器pid
4458
[root@server1 ~]# cd /proc/4458 进入进程目录
[root@server1 4458]# ls 容器信息
attr cwd map_files oom_adj schedstat task
autogroup environ maps oom_score sessionid timers
auxv exe mem oom_score_adj setgroups uid_map
cgroup fd mountinfo pagemap smaps wchan
clear_refs fdinfo mounts patch_state stack
cmdline gid_map mountstats personality stat
comm io net projid_map statm
coredump_filter limits ns root status
cpuset loginuid numa_maps sched syscall
[root@server1 4458]# cd ns/
[root@server1 ns]# ls
ipc mnt net pid user uts 提供了容器6种安全隔离
2、容器资源控制
[root@server1 ~]# mount -t cgroup 查看cgroup 文件系统被挂载到那些位置,发现被挂载到/sys/fs/cgroup
2、1内存限制
[root@server1 ~]# cd /sys/fs/
[root@server1 fs]# ls
bpf cgroup pstore xfs
[root@server1 fs]# cd cgroup/
[root@server1 cgroup]# ls 里面有cpu、memroy 、cpuset等等这些子目录
blkio cpu,cpuacct freezer net_cls perf_event
cpu cpuset hugetlb net_cls,net_prio pids
cpuacct devices memory net_prio systemd
[root@server1 cgroup]# cd memory/ 进入内存目录
[root@server1 memory]# cat memory.limit_in_bytes 查看内存限制
9223372036854771712 没有限制
[root@server1 memory]# docker rm -f demo 先删除之前的容器demo
demo
[root@server1 memory]# docker run -d --name demo --memory 200M nginx 指定demo容器内存为200M
[root@server1 cgroup]# cd /sys/fs/cgroup/memory/ 进入内存子系统目录
[root@server1 memory]# cd docker/ 进入daocker目录 ,所有容器控制都在docker目录里
[root@server1 docker]# cd 4312c8b6210c22ebaa09fa9969450700b35fe8bc92866382261e72682e215b60/ 进入以容id命名的目录
[root@server1 4312c8b6210c22ebaa09fa9969450700b35fe8bc92866382261e72682e215b60]# ls 以下才是容器真正生效的参数,
cgroup.clone_children memory.memsw.failcnt
cgroup.event_control memory.memsw.limit_in_bytes
cgroup.procs memory.memsw.max_usage_in_bytes
memory.failcnt memory.memsw.usage_in_bytes
memory.force_empty memory.move_charge_at_immigrate
memory.kmem.failcnt memory.numa_stat
memory.kmem.limit_in_bytes memory.oom_control
memory.kmem.max_usage_in_bytes memory.pressure_level
memory.kmem.slabinfo memory.soft_limit_in_bytes
memory.kmem.tcp.failcnt memory.stat
memory.kmem.tcp.limit_in_bytes memory.swappiness
memory.kmem.tcp.max_usage_in_bytes memory.usage_in_bytes
memory.kmem.tcp.usage_in_bytes memory.use_hierarchy
memory.kmem.usage_in_bytes notify_on_release
memory.limit_in_bytes tasks
memory.max_usage_in_bytes
[root@server1 4312c8b6210c22ebaa09fa9969450700b35fe8bc92866382261e72682e215b60]# cat memory.limit_in_bytes 查看内存容器限制
209715200 为200M,以上其他参数如果不指定,会从父级继承
[root@server1 docker]# docker rm -f demo 删除容器
demo
[root@server1 docker]# yum install libcgroup-tools.x86_64 -y
[root@server1 memory]# mkdir x1 在memory里创建x1目录
[root@server1 memory]# cd x1/
[root@server1 x1]# ls x1目录会继承父级参数
cgroup.clone_children memory.memsw.failcnt
cgroup.event_control memory.memsw.limit_in_bytes
cgroup.procs memory.memsw.max_usage_in_bytes
memory.failcnt memory.memsw.usage_in_bytes
memory.force_empty memory.move_charge_at_immigrate
memory.kmem.failcnt memory.numa_stat
memory.kmem.limit_in_bytes memory.oom_control
memory.kmem.max_usage_in_bytes memory.pressure_level
[root@server1 x1]# echo 209715200 > memory.limit_in_bytes 设置内存限制为200M
[root@server1 x1]# cat memory.limit_in_bytes
209715200
如何在物理内存里写东西??
[root@server1 x1]# df
[root@server1 x1]# cd /dev/shm/ 因此向此目录写东西就是往物理内存里写东西
[root@server1 shm]# free -m
total used free shared buff/cache available
Mem: 1998 161 1366 48 470 1628 可用内存为1628
Swap: 2047 0 2047
[root@server1 shm]# dd if=/dev/zero of=bigfile bs=1M count=100 生成一个100M的bigfile文件
[root@server1 shm]# free -m
total used free shared buff/cache available
Mem: 1998 161 1266 148 570 1528 可用空间少了100M
Swap: 2047 0 2047
[root@server1 shm]# dd if=/dev/zero of=bigfile bs=1M count=300 生成一个300M的bigfile文件,对内存没有限制
300+0 records in
300+0 records out
314572800 bytes (315 MB) copied, 0.108231 s, 2.9 GB/s
如何将设置的内存限制生效??
[root@server1 shm]# rm -f bigfile 删除文件
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300 -g指定memory子系统的x1控制器,来限制内存
300+0 records in
300+0 records out
314572800 bytes (315 MB) copied, 0.269023 s, 1.2 GB/s
[root@server1 shm]# free -m
total used free shared buff/cache available
Mem: 1998 165 1167 243 666 1429 现在发现只减少了200M,200M为限制的物理内存
Swap: 2047 105 1942 还有100M在swap,swap分区作用:当物理内存被耗尽的时侯,可以提供应急相应手段,避免操作系统卡死
上述方法还是没有有效的限制内存,超过200M还是可以写入,我们需要的效果是超过200M就无法写入,该如何时现??
[root@server1 shm]# rm -f bigfile 删除文件
[root@server1 cgroup]# cd /sys/fs/cgroup/memory/
[root@server1 memory]# cd x1/
[root@server1 x1]# echo 209715200 > memory.memsw.limit_in_bytes 表示物理内存+swap总共200M
[root@server1 x1]# cd /dev/shm/
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
Killed
[root@server1 shm]# free -m
total used free shared buff/cache available
Mem: 1998 161 1167 247 670 1429 内存只占用了200
Swap: 2047 0 2047 swap为0,没有占用
[root@server1 shm]# cd /sys/fs/cgroup/memory/x1/
[root@server1 x1]# cat tasks 如果有进程应用子系统,要把进程pid放到此目录即可
[root@server1 ~]# docker run -it --memory 200M --memory-swap=200M busybox 内存限制,docker和cgroup结合,只需要
/ # free -m
total used free shared buff/cache available
Mem: 1999 220 1125 0 653 1389
Swap: 2048 1 2047 系统上限已经设置了,但是系统隔离比较差
按ctrl+pq 退出
[root@server1 ~]# cd /sys/fs/cgroup/memory/
[root@server1 memory]# cd docker/
[root@server1 docker]# ls
c6a5d7aa4f43852fc42718f5dfb14f72adb54bb0824f00d8d4acabd1397c2351 容器id
cgroup.clone_children
cgroup.event_control
[root@server1 docker]# cd c6a5d7aa4f43852fc42718f5dfb14f72adb54bb0824f00d8d4acabd1397c2351/
[root@server1 c6a5d7aa4f43852fc42718f5dfb14f72adb54bb0824f00d8d4acabd1397c2351]# cat memory.limit_in_bytes
209715200 内存上线已经设置为200M
[root@server1 c6a5d7aa4f43852fc42718f5dfb14f72adb54bb0824f00d8d4acabd1397c2351]# cat memory.memsw.limit_in_bytes
209715200 内存上线已经设置为200M
如何控制普通用户内存的使用?
[root@server1 ~]# useradd wxh 创建一个普通用户
[root@server1 ~]# vim /etc/cgrules.conf 此文件是持久化配置子文件系统的,上述创建的x1重启就会消失
wxh memory x1/ 添加规则
普通用户 memory子系统 控制
[root@server1 ~]# systemctl start cgred.service 需要开启cgred服务进程
[root@server1 ~]# cd /dev/shm/
[root@server1 shm]# rm -f bigfile 删除此文件,这个文件也是通过差异控制器写进去的也算内存
[wxh@server1 ~]$ cd /sys/fs/cgroup/memory/x1/
[wxh@server1 x1]$ cat tasks
5823 这就是用户的进程
5862
[wxh@server1 x1]$ cd /dev/shm/
[wxh@server1 shm]$ dd if=/dev/zero of=bigfile bs=1M count=300 大与200M,写不进去
Killed
2、2 cpu限额
[root@server1 ~]# cd /sys/fs/cgroup/
[root@server1 cgroup]# cd cpu 进入cpu子系统
[root@server1 cpu]# mkdir x2 创建x2 ,里面参数都是继承了父级参数
cgroup.clone_children cpuacct.usage_percpu cpu.shares
cgroup.event_control cpu.cfs_period_us cpu.stat
cgroup.procs cpu.cfs_quota_us notify_on_release
cpuacct.stat cpu.rt_period_us tasks
cpuacct.usage cpu.rt_runtime_us
[root@server1 x2]# cat cpu.cfs_period_us 此参数表示时间分片
100000
[root@server1 x2]# cat cpu.cfs_quota_us此参数表示配额
-1 -1表示不做限制
[root@server1 x2]# lscpu
[root@server1 x2]# cd /sys/devices/
[root@server1 devices]# ls
breakpoint LNXSYSTM:00 pci0000:00 pnp0 system uprobe
kprobe msr platform software tracepoint virtual
[root@server1 devices]# cd system/
[root@server1 system]# ls
clockevents clocksource container cpu edac machinecheck memory node
[root@server1 system]# cd cpu/
[root@server1 cpu]# ls
cpu0 isolated nohz_full possible smt
cpu1 kernel_max offline power uevent
cpuidle modalias online present vulnerabilities
[root@server1 cpu]# cd cpu1/ cpu0不能被关闭,只能关闭除了cpu0之外的
[root@server1 cpu1]# ls
cache crash_notes_size firmware_node online subsystem uevent
crash_notes driver node0 power topology
[root@server1 cpu1]# cat online
1
[root@server1 cpu1]# echo 0 > online 导入0就是关闭
[root@server1 x2]# echo 20000 > cpu.cfs_quota_us 变更为20000配额,说明只能用时间分片总量100000的20%
[root@server1 x2]# cgexec -g cpu:x2 dd if=/dev/zero of=/dev/null & -g指定子系统cpu下的x2控制
去0设备去取,存到空设备里,这样不消耗内存,只耗cpu
27 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 md
[root@server1 x2]# top 可以发现cpu的
[root@server1 x2]# echo -1 > cpu.cfs_quota_us 将cpu配额改称-1不限制
[root@server1 x2]# dd if=/dev/zero of=/dev/null & 不限制cpu,可以发现cpu使用率100%用完
[root@server1 x2]# cat cpu.shares 可以发现,cpu优先级都为1024
1024
[root@server1 x2]# echo 100 > cpu.shares 现在将优先级改成100
[root@server1 x2]# cgexec -g cpu:x2 dd if=/dev/zero of=/dev/null &
此时两个进程争抢一个cpu资源,其中一个dd的cpu优先级设置的为100,只是1024的1/10
[root@server1 x2]# fg
cgexec -g cpu:x2 dd if=/dev/zero of=/dev/null 结束此进程
^C117824728+0 records in
117824728+0 records out
60326260736 bytes (60 GB) copied, 883.761 s, 68.3 MB/s
[root@server1 x2]# dd if=/dev/zero of=/dev/null & 不设置控制器,正常使用dd命令
可以发现优先级一样,公平调度
docker 和 cgroup 的结合使用:
[root@server1 x2]# docker run -d --memory 200M --memory-swap=200M --name demo --cpu-quota=20000 nginx 运行容器并设置cpu配额为20000,内存为200M
[root@server1 cpu]# cd /sys/fs/cgroup/cpu/docker 进入cpu子系统的docker目录
[root@server1 docker]# ls
[root@server1 cf251c5da70c7837e8f55251a1a1de0f4a914139b15894df4909a178cd88a987]# cat cpu.cfs_quota_us
20000 cpu 配额设置成功
[root@server1 ~]# cd /sys/fs/cgroup/memory/docker/ 进入内存子系统docker目录
[root@server1 docker]# ls
[root@server1 docker]# cd cf251c5da70c7837e8f55251a1a1de0f4a914139b15894df4909a178cd88a987
[root@server1 cf251c5da70c7837e8f55251a1a1de0f4a914139b15894df4909a178cd88a987]# cat memory.limit_in_bytes
209715200 内存限额为200M,也设置成功
在容器内测试:
[root@server1 ~]# docker exec -it demo bash 进入容器
root@cf251c5da70c:/# dd if=/dev/zero of=/dev/null
[root@server1 ~]# top ,可以发现cpu占用率为20%
2、3 磁盘io的限制(控制磁盘的读写速度)
[root@server1 ~]# cd /sys/fs/cgroup/
[root@server1 cgroup]# cd blkio/
[root@server1 blkio]# fdisk -l 查看当前虚拟机此盘名称,此盘为vda
[root@server1 blkio]# dd if=/dev/zero of=/tmp/bigfile bs=1M count=100 没有限制时截取文件速度是2.9 GB/s
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0355846 s, 2.9 GB/s
[root@server1 blkio]# docker run --help| grep device 过滤一下与设备相关的参数
--blkio-weight-device list Block IO weight (relative device
--device list Add a host device to the container
--device-cgroup-rule list Add a rule to the cgroup allowed
devices list
--device-read-bps list Limit read rate (bytes per second)
from a device (default [])
--device-read-iops list Limit read rate (IO per second)
from a device (default [])
--device-write-bps list Limit write rate (bytes per
second) to a device (default [])
--device-write-iops list Limit write rate (IO per second)
to a device (default [])
--gpus gpu-request GPU devices to add to the
[root@server1 blkio]# docker run -it --rm --device-write-bps /dev/vda:10MB rhel7 bash -device-write-bps表示控制写入速度,每秒10M
bash-4.2# dd if=/dev/zero of=/bigfile bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 9.94984 s, 10.5 MB/s 可以发现每秒控制在10M,控制成功
3、docker安全加固—利用lxfs增强容器隔离性和资源可见性
[root@foundation50 lxcfs]# scp lxcfs-2.0.5-3.el7.centos.x86_64.rpm server1:
[root@server1 ~]# yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm -y 安装软件包
[root@server1 ~]# lxcfs /var/lib/lxcfs & 运行lxcfs,生成所需要的数据
[1] 4837
[root@server1 ~]# hierarchies:
0: fd: 5: devices
1: fd: 6: memory
2: fd: 7: blkio
3: fd: 8: hugetlb
4: fd: 9: net_prio,net_cls
5: fd: 10: perf_event
6: fd: 11: pids
7: fd: 12: cpuacct,cpu
8: fd: 13: freezer
9: fd: 14: cpuset
10: fd: 15: name=systemd
[root@server1 ~]# cd /var/lib/lxcfs/ lxcfs就是早期linux容器技术
[root@server1 lxcfs]# ls
cgroup proc
[root@server1 lxcfs]# cd proc/
[root@server1 proc]# ls
cpuinfo diskstats meminfo stat swaps uptime 此6个文件就是容器的信息文件 将此六个文件挂载到容器proc目录里
[root@server1 proc]# docker pull ubuntu 拉取ubuntu镜像,因为busybox没有free命令,看不到实验效果
[root@server1 proc]# docker run -it -m 200m \ -m 200M 设置内存为200M
> -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \ 将此6个文件挂载到容器/proc目录
> -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@382e5cfabea1:/# free -m
total used free shared buff/cache available 只显示200M,达到隔离效果
Mem: 200 0 199 16 0 199
Swap: 200 0 200
4、设置特权级运行的容器:–privileged=true
有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交换分区,挂载USB磁盘,修改MAC地址等。
[root@server1 proc]# docker run -it --rm --privileged=true busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel) 虽然看上去是超户,但其实不是
/ # ip link set down eth0 停掉eth0接口
ip: SIOCSIFFLAGS: Operation not permitted 没有权限
[root@server1 proc]# docker run -it --rm --privileged=true busybox --privileged=true表示权限全开,此时才是真正的超户
[root@server1 proc]# docker run -it --rm --privileged=true busybox
/ # ip link set down eth0 此时停掉eth0接口
/ # ip addr 可以发现接口已经停止了没有ip了
4、1 设置容器白名单:–cap-add
注意:–privileged=true此权限太大,因为容器和宿主机是共享的,为了防止通过容器去修改宿主机 此时Docker 提供了权限白名单的机制,使用–cap-add添加必要的权限。 内核能力机制提供了许多权限控制
[root@server1 proc]# docker run -it --rm --cap-add=NET_ADMIN busybox --cap-add表示添加白名单,NET_ADMIN表示执行网络相关操作的能力
[root@server1 proc]# docker run -it --rm --cap-add=NET_ADMIN busybox
/ # ip addr 查询ip,可以
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
23: eth0@if24: <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
/ # fdisk -l 查询此盘,就没有权限,只针对网络
|