一年之后重新审视 Docker —— 根本性缺陷和炒作 已翻译 100%

oschina 投递于 2015/02/08 07:57 (共 9 段, 翻译完成于 02-13)
阅读 26860
收藏 51
2
加载中

摘要

距我上次炮轰Docker的缺陷构架设计和糟糕的用户体验已经一年多了。项目不久前发布了1.0版本并且亚马逊曾给过一些差评, 但期间伴随着用户的失意,漫天的指责还有甚至利用缺陷引起的主机污染。尽管如此, Docker Hub引入的私有源终结了主机部署需要自己注册的麻烦, 同时web钩子与紧凑的一体化Github编译,都是一个良好的开端。

所以我决定再给Docker一个机会,投入生产环境6个月。结果糟透了的性能,业余的工作区和让人生气的用户体验让我只想拿脸撞桌子。实际上性能差到禁用缓存导致了更快的构建用时。

如果你期待Docker的正面消息,或者它的维护者,那么你真是太不走运了。

鑫鑫向融
鑫鑫向融
翻译于 2015/02/08 12:24
2

Dockerfile

Dockerfile 有很多问题,丑陋、约束、矛盾还有从根本上的缺陷。比方说在一个仓库里生成多个镜像,所有的镜像都需要同样的依赖环境,但是其中一个包含调试工具。Docker不支持这个(per #9198),你也不能扩展Dockerfile(per #735),使用子目录会破坏创建环境同时会阻止你使用ADD/COPY命令(per #2224),因为dockerfile使用管道方式读入的(per #2112),你也不能使用环境变量在生成镜像的时候根据条件来改变指令(per #2637)。

我们的团队曾经创建了一个基础镜像,两个特定环境的镜像,还有一些makefile脚本用来做批量改名和sed替换。一些不期望的“特性”会导致环境变量$HOME消失,然后返回无用的错误信息。实在是太恶心了。

asdfsx
asdfsx
翻译于 2015/02/10 11:31
1

Docker 缓存/层

Docker有通过使用COW(写时复制)文件系统缓存Dockerfile指令的能力。和LVM快照类似,并且直到至今只支持AuFS,这个有无数的问题。接下来在0.7发布版中不同于COW实现被引入了来改善稳定性和性能,详情

然而这个缓存系统是不智能的,导致了一些令人惊讶的负效应,不能阻止来自缓存的单指令(per #1996)。它也慢的痛苦,从这一点来说,如果阻止缓存和使用层,会让构建快一些。缓慢的上下载速度使Docker Hub的性能变得更糟糕。接下来详细描述。

这些问题都是由Docker作为一个完全的强制行线性指令执行甚至在它完全不适合的条件下的架构设计导致的。作为一个慢速构建的工作环境,你可以使用第三方工具支持异步执行,比如Salt StackPuppet 或者 甚至是 bash, 完全打败层的目标和使他们一无是处。

liuqiangchengdu
liuqiangchengdu
翻译于 2015/02/10 14:01
1

Docker Hub

Docker鼓励通过Docker Hub进行社区协作,在Docker Hub上你可以以公开或私有的方式发布你的Dockerfile,这样其他用户可以通过FROM命令来使用或者扩展你的Dockerfile,而不是复制粘贴。但是这样做也是有问题的。Dockerfile不支持多个FROM命令(per #3378, #5714 and #5726),意味着你只能继承一个镜像。Docker Hub也没有强制的版本,比如dockerfile/ubuntu:14.04的作者可以更换标签对应的内容,这就像使用一个没有强制版本的打包管理器。而且它TMD还有速度限制,这个下面会提到。

Docker Hub还有一个自动构建系统,它会检查你仓库中新的提交然后触发一个容器构建。这是完全无用的。构建配置几乎没有什么定制的能力,甚至没有最基础的构建前/后的脚本钩子。这迫使我们创建一个特殊的项目结构,在项目的根目录放一个单独的Dockerfile,这破坏了我们之前提到的构建环境,而且构建时间太TMD长了。

我们的小组曾近使用CircleCI,一个很特别的托管CI平台,它可以根据Makefile触发Docker的构建然后上传到Docker Hub上。这个也没有解决龟速的问题,看来唯一的选择就是使用我们自己的Docker仓库,但是这个实在是太复杂了。

asdfsx
asdfsx
翻译于 2015/02/13 12:38
1

安全性

Docker最初使用LXC作为基础的运行环境,但是从0.9版开始他们使用自己的容器库。通过它可以调整命名空间的性能、权限,而且可以通过定制LXC配置使用适当的exec-driver。

它需要在宿主机上启动一个守护进程,Docker上有很多安全上的缺陷,比如CVE-2014-6407CVE-2014-6408,坦白说这些缺陷都不应该出现在第一位。甚至当Gartner看到他们跟踪记录上可怜的评估时,对Docker的不完善和安全问题表示了关注

从设计上来说,Docker太信任命名空间的能力,而命名空间相比普通的hypervisor有太多的漏洞,像Xen现在有129个公开的漏洞,而Linux里有1279个漏洞。在一些场景下这是可以接受的,比如在Travis CI上的公开构建,但是在多用户的私有环境里是非常危险的。

asdfsx
asdfsx
翻译于 2015/02/13 12:09
1

容器不是虚拟机

Namespaces 和 cgroups 非常强大,它们允许一个进程以及它的子进程从共享的内核资源(入网络栈和进程列表)里获得一个仅自己可见的视图。这种细粒度的控制和隔离,配合chroot jailing和grsec,可以提供一层非常完美的保护。一些程序即使不用 docker 也可以获得这种好处,比如 uWSGI;一些不支持 Namespace 的程序则可以使用 firejail 从而运行在沙箱之中。

集装箱化的项目,比如 LXC 和 Docker,利用这些特性可以非常有效的在同一个内核空间里运行多个发行版。与 hypervisors 相比,这样的优势在于更低的内存占用,更快的启动速度,但是会降低安全性、稳定性和兼容性。一个极端的情况就是 Linux 内核接口,在内核和命名空间中运行不相容的或者未经测试的 glibc 可能产生一些无法预测的操作。

asdfsx
asdfsx
翻译于 2015/02/11 16:13
2

退回到2008年,当时LXC还在设计阶段,硬件辅助虚拟化才刚面世几年,还没有被广泛的使用,很多hypervisors在性能和稳定性上都存在问题,不过鉴于其使用成本低廉而且可以减少实体消耗(pysical footprint我觉得就是实体计算机占地面积的意思,实际上就是提高了计算机利用率,减少了计算机数量),这些缺点都是可以接受的。但是现在我们的hypervisor已经和纯物理机跑的一样快了,有时候甚至更快一点。按需托管的虚拟机也同样变得更快更便宜,比如 DigitalOcean 要比 EC2 性能更强而且更便宜,这使得我们不需要花费太多就可以做到虚拟机和应用的1对1部署。有不少特别的案例说明集装箱化是一个正确的解决途径,但是除非你能说明为什么在你的案例中它是不可或缺的,那么你就应该使用hypervisor。而且使用虚拟化你也可以同样享用命名空间的优点,即使你的应用自身不支持,像 firejail这样的工具也可以帮助你获得这些特性。

asdfsx
asdfsx
翻译于 2015/02/12 11:43
1

Docker 不是必需的

Docker 侵入式的增加了复杂的一层,让开发、调试、修复bug异常的的复杂,经常创造很多问题而不是解决问题。对于开发它带不来任何好处,因为你依然需要利用快照来实现响应式的自动扩展。更糟糕的是,如果你不使用快照那么你的产品环境的扩展将依赖于Docker Hub的稳定性。

另外在实际使用中,有很多项目把错误的把容器当做VM来使用。例如baseimage-docker,这个镜像使用init.d作为进入点,可以选择性的开启ssh server,从而简化了监控、调试、更换。但是该镜像作者们用简单的说明拒绝了这个观点。

asdfsx
asdfsx
翻译于 2015/02/10 18:20
1

结论

如果你的开发工作流还算清醒,那么你应该已经理解Docker不是必需的。所有它宣称的那些有用的特性不是没用就是实现的很糟糕,并且用命名空间就可以简单地直接实现它的主要优势。八年前Docker会是一个不错的主意,但现在它是鸡肋。

鑫鑫向融
鑫鑫向融
翻译于 2015/02/08 12:41
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(59)

LinJie_M
LinJie_M
哦 怎么办 还想看看docker呢 貌似不想看了
beyondforever68
beyondforever68
好久没人回复了啊
asdfsx
asdfsx

引用来自“卜库塔”的评论

好像翻译的人都是强烈反对这篇文章的,那为什么还要翻译那?
让大家了解下目前docker的问题。总是发现问题然后解决问题
itfanr
itfanr

引用来自“刀哥”的评论

我认为docker火不在于它自身很牛逼,也不会因为它有这样那样的问题而真的是垃圾。docker代表一种新的技术方向,解决了一些问题,满足了很多的需求,所以火了。docker会慢慢的变好,即便它挂了,它还是会有继承者,因为它的方向是对的,这就够了。
docker会改变IT运维,从而推动IT变得更加灵活、快捷。
9494 历史造英雄
刀哥
刀哥
我认为docker火不在于它自身很牛逼,也不会因为它有这样那样的问题而真的是垃圾。docker代表一种新的技术方向,解决了一些问题,满足了很多的需求,所以火了。docker会慢慢的变好,即便它挂了,它还是会有继承者,因为它的方向是对的,这就够了。
docker会改变IT运维,从而推动IT变得更加灵活、快捷。
鑫鑫向融
鑫鑫向融

引用来自“eechen”的评论

@鑫鑫向融 把goroutine协程吹上天,把pthreads多线程黑出翔,社区股沟吹,果然无节操.你让Linux上众多成熟的pthreads多线程应用情何以堪,典型的如MySQL和Java以及Event MPM的Apache,图形界面的还有常用的Firefox/Chrome,多媒体编解码的还有ffmpeg等.要不你也像人家这位博主那样写一篇好文介绍下无敌的goroutine是怎样狂虐渣渣中的战斗渣pthreads:
http://randu.org/tutorials/threads/

引用来自“鑫鑫向融”的评论

很好的多线程编程资料,引用当中的两句话,第一句用来回答你说的成熟应用,Threads can provide benefits... for the right applications! Don't waste your time multithreading a portion of code or an entire program that isn't worth multithreading. 第二句回答mysql的pthread应用 :You must be careful to equally distribute work and take extra steps to ensure non-blocking behavior in this thread model or you could experience pipeline "stalls.", 我们的问题就是pipline stalls, 而且是直接从libmysqlclient.so调用的read,recv阻塞系统调用,动态库调用的入口函数是mysql_read_query_result,可以知道是在等待一个查询结果,更详细一点我可以告诉你是在等待查询一个表是否存在或者mysql_ping检查连接是否active的结果的时候未返回 .为goroutine说一句话,它还很年轻,但不一定要比pthread差

引用来自“eechen”的评论

你把人家原文对多线程应用的注意事项拿出来用作批判pthreads不好的论据,也真够拼的.我只想说,不要因为Go用goroutine取代多线程编程就把pthreads批得一无是处.为什么Go会在中国取得那么大的关注,因为国内太TM多Google吹.
以前是Google粉,那时候不懂编程世界,现在说的这些全部都是真实的编程体会,没啥大成就,更多的是痛苦的领悟。
Nori
Nori
没有什么都是万能的
卜库塔
卜库塔
好像翻译的人都是强烈反对这篇文章的,那为什么还要翻译那?
晒太阳的小猪
晒太阳的小猪
DOCKER要乘积下功能。经管它还不完美
eechen
eechen

引用来自“eechen”的评论

@鑫鑫向融 把goroutine协程吹上天,把pthreads多线程黑出翔,社区股沟吹,果然无节操.你让Linux上众多成熟的pthreads多线程应用情何以堪,典型的如MySQL和Java以及Event MPM的Apache,图形界面的还有常用的Firefox/Chrome,多媒体编解码的还有ffmpeg等.要不你也像人家这位博主那样写一篇好文介绍下无敌的goroutine是怎样狂虐渣渣中的战斗渣pthreads:
http://randu.org/tutorials/threads/

引用来自“鑫鑫向融”的评论

很好的多线程编程资料,引用当中的两句话,第一句用来回答你说的成熟应用,Threads can provide benefits... for the right applications! Don't waste your time multithreading a portion of code or an entire program that isn't worth multithreading. 第二句回答mysql的pthread应用 :You must be careful to equally distribute work and take extra steps to ensure non-blocking behavior in this thread model or you could experience pipeline "stalls.", 我们的问题就是pipline stalls, 而且是直接从libmysqlclient.so调用的read,recv阻塞系统调用,动态库调用的入口函数是mysql_read_query_result,可以知道是在等待一个查询结果,更详细一点我可以告诉你是在等待查询一个表是否存在或者mysql_ping检查连接是否active的结果的时候未返回 .为goroutine说一句话,它还很年轻,但不一定要比pthread差
你把人家原文对多线程应用的注意事项拿出来用作批判pthreads不好的论据,也真够拼的.我只想说,不要因为Go用goroutine取代多线程编程就把pthreads批得一无是处.为什么Go会在中国取得那么大的关注,因为国内太TM多Google吹.
返回顶部
顶部