://lwn.net/Articles/723561/

近年来内核对容器的支持越来越全面,催生了一批容器化的系统。有趣的是内核关于容器是什么样的并没有明确定义,它只是提供了一些用户态可以使用的机制。David Howells最近着力于改变这种情况,他提交了一组patchset把container定义成一个内核对象。然而社区不是很接受这样的修改。

容器是一种轻量化的虚拟化技术,为容器内的进程制造拥有整个系统的假象。通过区分namespace,为每个namespace分别提供网络、文件系统和cgroup等来隔离容器,控制资源使用。辅以安全模块或者seccomp来对容器更多限制。结果以可以接受的复杂程度提供了大量灵活的机制,这是非常Linux的方式。但是容器源于的缺失使得内核端的事情变得有些复杂。 [编辑] 增加容器object

Howell的patch引入了一套系统调用,用于维护容器。

int container_create(const char *name, unsigned int flags);

这个系统调用用于创建一个容器,容器名称由第一个参数指定。flags参数指定namespace相关,例如指定CONTAINER_NEW_USER_NS创建的容器会使用心得namespace。返回值是用于引用创建容器的文件描述符。还有其他flags用于控制文件描述符关闭是否需要销毁容器这样的事情。

容器创建之后没有任何进程运行;如果用新挂载的namespace创建,容器里也不会有文件系统。fsopen()和fsmount()系统调用可以用来把文件系统添加到容器内部。“at”版本的文件系统调用(openat(),例如)可以接受容器的文件描述符。也可以用这样的方式让容器使用socket:

  int container_socket(int container_fd, int domain, int type, int protocol);

  可以让容器使用netlink socket更方便。

  让进程在容器里面运行的系统调用是:

     pid_t fork_into_container(int container_fd);

 Howell认为还有其他可以加到这个机制的方法,例如suspend和restart容器的系统调用、容器cgroup管理的方法。只是Howell的修改前景并不明朗。
 [编辑] 容器object抽象的不好?

 很多人对这样的修改并不买账。

 Jessica Frazelle认为Howell提出的容器object抽象的不够好,有其他很多创建容器的方法。还提到Open Containers Initiative中的很多runtime规范。

 James Bottomley更直接的认为这种修复的方向不对。他认为现在容器好就好在大家不必就容器是什么样的达成一致。可以根据需要创建一个用户态namespace没有mount namespace,或者一个体系结构模拟容器只有一个mount namespace。 Kubernetes系统里面对容器的使用允许namespace在“pods”之间共享,这个跟当前的容器object的定义也是冲突的。

 Eric Biederman的反对更强烈。namespace这样的修改会导致容器的所用conner cases完全暴露给用户态,开发者需要解决的问题更复杂,产生更多bug。


 [编辑] Upcalls

 退一步来看,这套patchset的出发点也不是让用户态管理容器更加方便,而是希望使内核“upcall”在容器环境里面更好的运转。

 通常来说,内核是系统的最底层。然而也不全是这样,例如`call_usermodehelper()`调用创建一个用户态进程来完成某些工作——换句话说“向上调用”到用户态。用到这样的“upcall”的有:

    * core-dump代码需要用户态进程来处理dump出的数据。
       * NFSv4 client调用程序做DNS解析。
          * 模块loader需要helper进程做模块的demand-loading
	     * 内核秘钥管理代码也需要用户态helper

	     这些upcall现在通常用到容器,然而内核没有容器的明确定义,并不能确定到底在那个容器里执行upcall,这样upcall可能会引起问题。

	     定义容器的确是解决这个问题的一个方法。但是Howell的解法引入了另外两个问题:(1)容器对象是解决问题的最好方法吗?(2)即便容器object有意义,需要暴露给用户态吗?

	     Colin Walters提出的另外一个解决方法是完全取缔“upcall”,用类似设备相关的events upcall被替换的方法。但是Jeff Layton指出这中解决方法只适用于部分问题,在其他情况下则可能引起系统可靠性的问题。

	     本文写在相关讨论火热进行的时候,发展难以预料。但是近期来看暴露到用户态的容器object难以进入内核。upcall的问题也许需要从其他方向进行解决,不过看起来这个问题还是需要一些时间。