目录

一、cgroup简介

二、 容器资源控制

1、内存限制

2、cpu限额

3、Block IO限制

三、docker 安全加固


docker容器镜像加密 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 ##有无根模式

docker容器镜像加密 docker容器如何加密_docker_02

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_03

docker容器镜像加密 docker容器如何加密_docker_04

docker容器镜像加密 docker容器如何加密_nginx_05

 

二、 容器资源控制

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容器镜像加密 docker容器如何加密_docker_06

docker容器镜像加密 docker容器如何加密_安全_07

docker容器镜像加密 docker容器如何加密_运维_08

docker容器镜像加密 docker容器如何加密_nginx_09

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容器镜像加密 docker容器如何加密_docker_10

docker容器镜像加密 docker容器如何加密_docker_11

docker容器镜像加密 docker容器如何加密_docker_12

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

docker容器镜像加密 docker容器如何加密_docker_13

docker容器镜像加密 docker容器如何加密_安全_14

docker容器镜像加密 docker容器如何加密_安全_15

docker容器镜像加密 docker容器如何加密_运维_16

docker容器镜像加密 docker容器如何加密_运维_17

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

docker容器镜像加密 docker容器如何加密_运维_18

docker容器镜像加密 docker容器如何加密_运维_19

docker容器镜像加密 docker容器如何加密_安全_20

docker容器镜像加密 docker容器如何加密_nginx_21

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交换分区是物理内存不够用时备用的

docker容器镜像加密 docker容器如何加密_docker_22

docker容器镜像加密 docker容器如何加密_docker_23

docker容器镜像加密 docker容器如何加密_nginx_24

docker容器镜像加密 docker容器如何加密_nginx_25

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容器镜像加密 docker容器如何加密_docker_26

docker容器镜像加密 docker容器如何加密_运维_27

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_28

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的

docker容器镜像加密 docker容器如何加密_nginx_29

docker容器镜像加密 docker容器如何加密_安全_30

docker容器镜像加密 docker容器如何加密_安全_31

docker容器镜像加密 docker容器如何加密_安全_32

docker容器镜像加密 docker容器如何加密_nginx_33

  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

docker容器镜像加密 docker容器如何加密_运维_34

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_35

docker容器镜像加密 docker容器如何加密_安全_36

docker容器镜像加密 docker容器如何加密_docker_37

docker容器镜像加密 docker容器如何加密_安全_38

docker容器镜像加密 docker容器如何加密_docker_39

 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

docker容器镜像加密 docker容器如何加密_运维_40

docker容器镜像加密 docker容器如何加密_nginx_41

docker容器镜像加密 docker容器如何加密_nginx_42

docker容器镜像加密 docker容器如何加密_docker_43

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

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_44

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容器如何加密_运维_45

docker容器镜像加密 docker容器如何加密_docker_46

docker容器镜像加密 docker容器如何加密_docker_47

三、docker 安全加固

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_48

docker容器镜像加密 docker容器如何加密_docker_49

 

在容器内查看内存时显示的是宿主机的内存信息,为了安全起见有时候需要做限制

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和proccd cgroup/
 ls
 cd ..
 cd proc/
  ls  #可以看到每一个文件都分别代表宿主机的6样信息

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_50

把lxcfs-2.0.5-3.el7.centos.x86_64.rpm从真机中传到docker1

docker容器镜像加密 docker容器如何加密_运维_51

利用LXCFS增强docker容器隔离性和资源可见性 

docker容器镜像加密 docker容器如何加密_安全_52

docker容器镜像加密 docker容器如何加密_安全_53

docker容器镜像加密 docker容器如何加密_运维_54

docker容器镜像加密 docker容器如何加密_docker_55

 

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 ##可以查看磁盘

docker容器镜像加密 docker容器如何加密_运维_56

docker容器镜像加密 docker容器如何加密_docker_57

docker容器镜像加密 docker容器如何加密_docker容器镜像加密_58

docker容器镜像加密 docker容器如何加密_安全_59

docker容器镜像加密 docker容器如何加密_nginx_60

docker容器镜像加密 docker容器如何加密_运维_61

docker容器镜像加密 docker容器如何加密_nginx_62