使用lxcfs容器为其他docker容器提供proc隔离能力

背景

容器可以通过cgoup和namespace对容器使用的资源进行一定程度的隔离,可以对pid,net,mount fs,cpu和内存进行隔离。但是一般意义上,容器内部看到的/proc/文件系统下的信息全部是宿主机上的信息。在容器内部可以看到容器可以使用的内存、cpu和宿主机完全一致,这对于java容器会引入很严重的问题。因为在常规PaaS系统上,为了保证每个容器不会过度消耗宿主机内存资源,在容器启动时都会带上--memory-limit参数,这个参数限制了容器里所有进程能够使用的内存和,如果容器内部使用的内存超限,在默认配置下会触发os的oom-killer将容器内部进程杀死。Java运行的Jvm,它起来后会申请大量的内存用于Jvm管理的内存。而申请的基础就是Jvm所在机器上/proc/meminfo看到的内存大小信息。所以在PaaS系统上,老式Jvm常常会导致自己被Os的oom-killer杀死。
解决办法有两种:

  • 升级Jvm:采用能够意识到容器的jum版本

1.Jvm9上,使用parameters -xx:unlockExperimentalVMOptions and -xx:+UseCGoupMemoryLimitForHeap
2.升级到Jvm10,Jvm10是能够意识到容器的jvm
3.使用(特殊的openjdk容器镜像){https://hub.docker.com/r/fabric8/java-jboss-openjdk8-jdk}镜像,此镜像容器使用50%容器内存限制给jvm使用

  • 采用lxcfs方式对容器的/proc系统进行修改——这既是本文介绍的方法

lxcfs介绍

lxcfs是一种基于fuse实现的用户态文件系统,最刚开在ubuntu上使用,现在可以使用在centos,federa上。它使用c开发,依赖于fuse包。
为容器提供如下目录:

  • /proc/cpuinfo
  • /proc/meminfo
  • /proc/diskstats
  • /proc/swaps
  • /proc/uptime

当容器里进程访问到这些目录后,lxcfs将转换到进程所在的cgroup(也就是进程所在容器的宿主机cgoup里)读取memlimit,swaplimit ,cpuset,disk和uptime。由此提供容器独特视角的/proc/xx信息。
下图为lxcfs的架构


lxcfs架构

主机lxcfs为docker容器提供proc隔离

lxcfs安装(编译)

网上常见的lxcfs都是采用下载lxcfs-2.0.x rpm方式安装。其实lxcfs工程只依赖于fuse包,如果需要从github代码编译还需要安装:automake,autoconf包,当然gcc这些必须的。可以直接从github下载最新的lxcfs代码进行编译即可。
笔者使用的centos7.4系统,安装了fuse-devel、fuse-libs和fuse包。
Step1: 在代码根目录执行

bootstrap.sh
./configure
make

执行完毕之后在代码根目录出现了一个lxcfs的elf文件,要运行它需要将.libs/liblxcfs.so拷贝到指定目录上去
通过下面命令运行lxcfs

Mkdir /home/zxy/lxcfs-workdir
./lxcfs /home/zxy/lxcfs-workdir

运行起来以后,可以到/home/zxy/lxcfs-workdir下看到两个目录:
cgroup和proc目录
此时证明lxcfs已经成功了。
首先需要内核支持fuse,可以到/boot/下查看config文件中fuse是否配置为Y或者M

容器启动时刻可以通过下面命令为每个容器保证一个独立的/proc

docker  run --rm -name zxy-lxcfs-targe -m 64m --cpuset-cpus 1 -v /home/zxy/lxcfs-workdir/meminfo:/proc/meminfo \
-v /home/zxy/lxcfs-workdir/swaps:/proc/swaps \
-v /home/zxy/lxcfs-workdir/cpuinfo:/proc/cpuinfo \
-v /home/zxy/lxcfs-workdir/diskinfo:/proc/diskinfo \
-v /home/zxy/lxcfs-workdir/uptime:/proc/uptime -it centos:latest /bin/bash

容器启动后使用free命令可以看到容器存储只有64M,通过cat /proc/cpuinfo看到只有一个cpu,通过uptime看到启动时间为刚启动。

lxcfs容器为docker容器提供proc隔离

首先第一步需要主机上编译完成lxcfs。
lxcfs容器生成方法很简单,既可以采用docker build从centos镜像创建一个lxcfs;也可以采用docker cp方法将lxcfs和liblxcfs.so拷贝到centos容器内部,将fuse动态库也用同样的方式拷贝到centos容器内部,然后docker commit 将修改过centos容器提交为一个镜像。笔者采用后者方式生产一个lxcfs镜像。
通过下面命令启动此镜像

Docker run --privileged=true --pie=host -v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /home/zxy/lxcfs-workdir:/var/lib/lxcfs:rshared --it centos-lxcfs /home/lxcfs /var/lib/lxcfs

此容器运行后,可以在宿主机上检查/home/zxy/lxcfs-workdir有无cgroup和proc目录证明lxcfs有无正常启动。
如果正常可以上上一小节中介绍的方法,启动其他docker容器,此时其他docker容器内部看到的/proc/就变为
lxcfs修改后的了。

你可能感兴趣的:(使用lxcfs容器为其他docker容器提供proc隔离能力)