在HOST上面,一个LXC container包含一个config文件和一个rootfs目录。

早期我们在交叉编译系统上编译出container的rootfs之后,直接在编译系统上将其用tar压缩打包。然后下载到目标系统上解压到container的根文件系统“rootfs”里面。但是这样的话有几个问题:
1. image过于庞大,导致下载到目标系统时间较长。
2. 在目标系统上安装时解压时间过长,且会占用大量flash空间。
3. 当container运行起来后,动态生成的文件跟原有的文件混在一起,不方便管理。例如如果要将container恢复到安装时的状态,这时就无从知道删除哪些文件了。
4. 卸载container时需要删除整个rootfs,耗时较长。
5. 无法防止运行过程中对原始文件系统的修改。

基于以上的缺陷,我们做了以下改良:
1. 在编译系统上压缩打包时,我们将rootfs打包成squashfs文件系统并压缩,这种方式压缩比更高,这样可以减少最后生成的image的大小。

$ sudo -n -- mksquashfs $rootfs_dir $squashfs_image_path -noappend -comp xz

这样就生成了“rootfs_base.img”,然后再跟其他配置文件和脚本文件一起压缩打包生成最后的image
2.在目标系统上,直接将"rootfs_base.img" 挂载到文件系统目录上,这样就减少了解压的过程,注意在mount时,我们以readonly的方式mount,这样就防止原始的文件系统被篡改。

mount -nt squashfs -o ro $LXC_DIR/rootfs_base.img $LXC_DIR/lowerdir || error_exit "Cannot mount rootfs base image"

3.我们将目标系统上的rootfs设计成overlay文件系统,将原始的rootfs_base部分放在lower layer,然后将系统运行时产生的文件系统的变动放在upper layer。这样就可以将原始文件和运行时文件进行了隔离。
4.为了限制运行时文件系统大小,我们在安装container时,创建了一个固定大小的类型为ex2的image "rootfs_overlay.img",然后将这个image挂载在一个loop文件系统上:

$ rm -f $LXC_DIR/rootfs_overlay.img

$ dd if=/dev/zero of=$LXC_DIR/rootfs_overlay.img bs=1K count=$size
$ mkfs.ext2 -E root_owner="$uid:$gid" $LXC_DIR/rootfs_overlay.img
$ mount -nt ext4 -o loop,nouser_xattr,noacl,nodelalloc,nobarrier,noblock_validity,noatime,sync $LXC_DIR/rootfs_overlay.img $LXC_DIR/overlay || error_exit "Cannot mount overlay rootfs image"

这样,对$LXC_DIR/overlay的写入就受到"rootfs_overlay.img"的大小的限制了。
5.最后我们最终的runtime rootfs是如下组成:


$ mkdir -p $LXC_DIR/overlay/upperdir $LXC_DIR/overlay/workdir 
$ mount -nt overlay overlay -o "noatime,lowerdir=$LXC_DIR/lowerdir,upperdir=$LXC_DIR/overlay/upperdir,workdir=$LXC_DIR/overlay/workdir" "$LXC_ROOTFS_PATH"

6.在stop container的时候,只需要umount相关的文件系统。

$ umount --lazy "$LXC_DIR/overlay"
$ umount --lazy "$LXC_DIR/lowerdir"
$ umount --lazy "$LXC_DIR/basedir"

在uninstall container的时候,只需要删除相应的image和目录即可。如果需要恢复原始状态,只需要清空upper layer的部分。

如果是特权“priv”模式:

mount -nt squashfs -o ro $LXC_DIR/rootfs_base.img $LXC_DIR/lowerdir || error_exit "Cannot mount rootfs base image"
mount -nt ext4 -o loop,nouser_xattr,noacl,nodelalloc,nobarrier,noblock_validity,noatime,sync $LXC_DIR/rootfs_overlay.img $LXC_DIR/overlay || error_exit "Cannot mount overlay rootfs image"
mkdir -p $LXC_DIR/overlay/upperdir $LXC_DIR/overlay/workdir
mount -nt overlay overlay -o "noatime,lowerdir=$LXC_DIR/lowerdir,upperdir=$LXC_DIR/overlay/upperdir,workdir=$LXC_DIR/overlay/workdir" "$LXC_ROOTFS_PATH"

如果是unpriv模式:

mount -nt squashfs -o ro $LXC_DIR/{{ base_image }} $LXC_DIR/basedir || error_exit "Cannot mount rootfs base image"
bindfs -r --uid-offset=$LXC_UID --gid-offset=$LXC_GID $LXC_DIR/basedir $LXC_DIR/lowerdir || error_exit "Cannot mount base rootfs with UID offset"
mkdir -p $LXC_DIR/overlay/upperdir $LXC_DIR/overlay/workdir
mount -nt overlay overlay -o "noatime,lowerdir=$LXC_DIR/lowerdir,upperdir=$LXC_DIR/overlay/upperdir,workdir=$LXC_DIR/overlay/workdir" "$LXC_ROOTFS_PATH"

LXC容器文件系统设计优化的更多相关文章

  1. LXC容器

    1.    LXC简述 Linux container是一种资源隔离机制而非虚拟化技术.VMM(VMM Virtual Machine Monitor)或者叫Hypervisor是标准的虚拟化技术,这 ...

  2. Hadoop HDFS分布式文件系统设计要点与架构

      Hadoop HDFS分布式文件系统设计要点与架构     Hadoop简介:一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群 ...

  3. lxc 容器基础配置篇

    一, 首先配置lxc需要的网卡断 吧eth0复制一份变为br0 配置br0 配置eth0 重启网卡   /etc/init.d/network restart 安装lxc软件 需要epel源--- y ...

  4. 生成Alpine LXC容器的根文件系统

    一个Alpine LXC容器的文件系统内容包括以下内容 根文件系统 应用程序,库文件以及配置文件 根文件系统主要包含alpine linux最小系统所需要的组件.下面主要讲一下制作根文件系统的方法. ...

  5. Java读取Level-1行情dbf文件极致优化(3)

    最近架构一个项目,实现行情的接入和分发,需要达到极致的低时延特性,这对于证券系统是非常重要的.接入的行情源是可以配置,既可以是Level-1,也可以是Level-2或其他第三方的源.虽然Level-1 ...

  6. Java读取Level-1行情dbf文件极致优化(2)

    最近架构一个项目,实现行情的接入和分发,需要达到极致的低时延特性,这对于证券系统是非常重要的.接入的行情源是可以配置,既可以是Level-1,也可以是Level-2或其他第三方的源.虽然Level-1 ...

  7. Linux文件系统性能优化 (转)

    http://blog.chinaunix.net/uid-7530389-id-2050116.html 由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍 ...

  8. 如何在Ubuntu上创建及管理LXC容器?

    将LXC安装到Ubuntu上 $ sudo apt-get install lxc 安装完毕之后,运行lxc-checkconifg工具,检查当前Linux内核支持LXC的情况.要是一切都已被启用,内 ...

  9. Django中静态文件引用优化

    静态文件引用优化 在html文件中是用django的静态文件路径时,一般会这么写: <script type="text/javascript" src="/sta ...

随机推荐

  1. pycharm的使用(day03复习整理)

    pycharm的使用 file --> settings --> editor -->general --> change font size .... file --> ...

  2. Java基础(十二)lambda表达式

    1.引入lambda表达式的重要性 lambda表达式是一个可传递的代码块,可以在以后执行一次或多次. 在前面的回调部分,有一个例子是,ActionListener类实现了TimePrinter接口并 ...

  3. Handler的postDelayed(Runnable, long)

    handler.postDelayed(myRunnable,1000)是为了轮播图片,每隔1000ms后执行一次run方法,实现轮播实例如下: public void MesageColse(){ ...

  4. 6.1Hadoop属性Configuration配置API

    6.1  Hadoop属性配置API Hadoop需要添加一些自定义的属性值,可以通过Configuration类的实例来加载xml配置文件中的属性值. (1)   xml配置文件的格式 <?x ...

  5. day 2 DP专场

    上午讲了一上午背包,从01背包到完全背包到多重背包,感觉也没说什么,旁边的大佬一直在飞鸽里说让老师讲快点,然而最后也没人敢跟老师说.... 例题真的各个都是神仙题, 挂饰 好像就是一上午最简单的... ...

  6. Hybrid App: 了解JavaScript如何与Native实现混合开发

    一.简介 Hybrid Development混合开发是目前移动端开发异常火热的新兴技术,它能够实现跨平台开发,极大地节约了人力和资源成本.跨平台开发催生了很多新的开源框架,就目前而言,在混合开发中比 ...

  7. 开发板,pc,虚拟机三者如何互相ping通

    1 安装虚拟机时,主机和虚拟机必须是桥接网卡,保证了ip 同一:192,168,1,xx 2 打开虚拟机之前,先把pc机的无线网卡禁用掉只能使用本地连接,pc通过网线连接上网,打开虚拟机,命令行输入: ...

  8. egret Tiledmap编写障碍物的思路

    egret Tiledmap编写障碍物的思路 获取控制对象下一刻移动的坐标,将其转换成瓦片坐标,如果getTileGIDAt(根据瓦片坐标获取瓦片id)的值不为0,说明对象将要移动的位置有障碍物,不做 ...

  9. mysql优化必知(mysql的语句执行顺序)

    MySQL的语句执行顺序 MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操作,最后执行的是LIMIT操作.其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入 ...

  10. 03-MyBatis拦截器机制

    目录 MyBatis拦截器介绍 拦截器的使用 拦截器介绍及配置 源码分析 总结 本文转载自MyBatis拦截器原理探究 MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽 ...