proc文件系统隔离(lxcfs)

场景描述

容器虚拟化带来轻量高效,快速部署的同时,也因其隔离性不够彻底,给用户带来一定程度的使用不便。由于Linux内核namespace本身还不够完善,因此容器在隔离性方面也存在一些缺陷。例如,在容器内部proc文件系统中可以看到宿主机上的proc信息(如meminfo, cpuinfo,stat, uptime等)。利用lxcfs工具可以将容器内的看到宿主机/proc文件系统的内容,替换成本容器实例的相关/proc内容,以便容器内业务获取正确的资源数值。

接口说明

系统容器对外提供两个工具包:一个是lxcfs软件,另外一个是配合lxcfs一起使用的isulad-lxcfs-toolkit工具。其中lxcfs作为宿主机daemon进程常驻,isulad-lxcfs-toolkit通过hook机制将宿主机的lxcfs文件系统绑定挂载到容器。

isulad-lxcfs-toolkit命令行格式如下:

  1. isulad-lxcfs-toolkit [OPTIONS] COMMAND [COMMAND_OPTIONS]

命令

功能说明

参数

remount

将lxcfs重新mount到容器中

—all:对所有的容器执行remout lxcfs操作

—container-id:remount lxcfs到特定的容器ID

umount

将lxcfs从容器中umount掉

—all:对所有的容器执行umout lxcfs操作

—container-id:对特定容器执行umount lxcfs操作

check-lxcfs

检查lxcfs服务是否运行

prestart

在lxcfs服务启动前将/var/lib/lxcfs目录mount到容器中

约束限制

  • 当前只支持proc文件系统下的cpuinfo, meminfo, stat, diskstats, partitions,swaps和uptime文件,其他的文件和其他内核API文件系统(比如sysfs)未做隔离 。
  • 安装rpm包后会在/var/lib/isulad/hooks/hookspec.json生成样例json文件,用户如果需要增加日志功能,需要在定制时加入—log配置。
  • diskstats只能显示支持cfq调度的磁盘信息,无法显示分区信息。容器内设备会被显示为/dev目录下的名字。若不存在则为空。此外,容器根目录所在设备会被显示为sda。
  • 挂载lxcfs时必须使用slave参数。若使用shared参数,可能会导致容器内挂载点泄露到主机,影响主机运行 。
  • lxcfs支持服务优雅降级使用,若lxcfs服务crash或者不可用,容器内查看到的cpuinfo, meminfo, stat, diskstats, partitions, swaps和uptime均为host信息,容器其它业务功能不受影响。
  • lxcfs底层依赖fuse内核模块以及libfuse库,因此需要内核支持fuse。
  • lxcfs当前仅支持容器内运行64位的app,如果容器内运行32位的app可能会导致app读取到的cpuinfo信息不符合预期。
  • lxcfs只是对容器cgroup进行资源视图模拟,对于容器内的系统调用(例如sysconf)获取到的仍然是主机的信息,lxcfs无法做到内核隔离。
  • lxcfs使用隔离后的cpuinfo显示的cpu信息具有如下特征:
    • processor:从0开始依次递增。
    • physical id:从0开始依次递增。
    • sibliing:固定为1。
    • core id:固定为0。
    • cpu cores:固定为1。

使用示例

  1. 首先需要安装lxcfs和isulad-lxcfs-toolkit这两个包,并启动lxcfs服务。

    1. [root@localhost ~]# yum install lxcfs isulad-lxcfs-toolkit
    2. [root@localhost ~]# systemctl start lxcfs
  2. 容器启动完成之后查看容器内是否存在lxcfs挂载点。

    1. [root@localhost ~]# isula run -tid -v /var/lib/lxc:/var/lib/lxc --hook-spec /var/lib/isulad/hooks/hookspec.json --system-container --external-rootfs /home/root-fs none init
    2. a8acea9fea1337d9fd8270f41c1a3de5bceb77966e03751346576716eefa9782
    3. [root@localhost ~]# isula exec a8 mount | grep lxcfs
    4. lxcfs on /var/lib/lxc/lxcfs type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    5. lxcfs on /proc/cpuinfo type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    6. lxcfs on /proc/diskstats type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    7. lxcfs on /proc/meminfo type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    8. lxcfs on /proc/partitions type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    9. lxcfs on /proc/stat type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    10. lxcfs on /proc/swaps type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
    11. lxcfs on /proc/uptime type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
  3. 执行update命令更新容器的cpu和mem资源配置,然后查看容器资源。根据如下回显可知,容器资源视图显示的是容器真实资源数据而不是宿主机的数据。

    1. [root@localhost ~]# isula update --cpuset-cpus 0-1 --memory 1G a8
    2. a8
    3. [root@localhost ~]# isula exec a8 cat /proc/cpuinfo
    4. processor : 0
    5. BogoMIPS : 100.00
    6. cpu MHz : 2400.000
    7. Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
    8. CPU implementer : 0x41
    9. CPU architecture: 8
    10. CPU variant : 0x0
    11. CPU part : 0xd08
    12. CPU revision : 2
    13. processor : 1
    14. BogoMIPS : 100.00
    15. cpu MHz : 2400.000
    16. Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
    17. CPU implementer : 0x41
    18. CPU architecture: 8
    19. CPU variant : 0x0
    20. CPU part : 0xd08
    21. CPU revision : 2
    22. [root@localhost ~]# isula exec a8 free -m
    23. total used free shared buff/cache available
    24. Mem: 1024 17 997 7 8 1006
    25. Swap: 4095 0 4095