://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的问题也许需要从其他方向进行解决,不过看起来这个问题还是需要一些时间。