3亿Docker容器部署的挑战及应对方案
发布日期:2016-3-21 9:3:30
IronWorker 是一个面向开发者的任务队列服务,开发人员可在不设置和管理任何基础设施的基础上,调度执行大规模的任务。几个月前,IronWorker 开始使用 Docker,如今其内部已部署了3亿多个 Docker 容器,本文中分享了 IronWorker 在使用基于 Docker 的基础架构的时候,遇到的挑战、解决方法,及其中的收获。 以下为译文: IronWorker 是一个任务队列服务,他让开发人员在不用设置和管理任何基础设施的基础上,调度执行大规模的任务。我们3年多前推出这项服务的时候,使用了包含所有的语言和代码包的LXC容器运行任务。Docker使我们能够轻松地升级和管理一组容器,为客户提供更多的语言环境和安装包。我们刚开始使用的是v0.7.4版本的 Dokcer ,使用过程中遇到一些困难(不能正常关闭曾是个大问题,不过后来被解决了)。我们不仅成功地克服了所有的困难,并且发现 Docker 不仅满足了我们的需求,更是超出了我们的预期。因此我们在我们的基础架构中推广使用 Docker 。基于我们的经验来看,这样做是有意义的。 Docker的优势: 资源分配 基于 LXC 的容器是操作系统级别的虚拟化方法,所有的容器共享系统内核,但每个容器可被约束使用指定的资源,比如 CPU 、内存和 I/O 。 Docker 提供 REST API 、环境版本控制、获取/提交镜像、轻松获取统计数据等功能。 Docker 支持使用 CoW 文件系统来更安全的隔离数据。这意味着,任务中对文件的所有改变都分开存储,并可用一个命令清除。 LXC 不能跟踪这种变化。 更新维护镜像十分容易 Doker 使用类似 git 的十分强大的方法来管理 image ,使得它能很方便地管理大量的、不断变化的环境,他的 image 分层系统不仅节省空间而且使我们拥有更细区分度的 images 。 现在,我们能够跟上快速更新的语言的节奏,例如我们能够提供一个新的专为媒体处理而设计的 ffmpeg stack 。我们现在有多达15个不同的堆栈并且正在迅速扩大。 Dockerfiles使得集成简单 我们的团队遍布世界各地。只要发布一个简单的 Dockerfile 即可下班,当你休息的时候,可保证其他工作的人能够生成和你的一样的镜像。克服了不同地方的人有不同的作息时间的困难。干净的镜像使得它部署和测试更快。我们的迭代周期更快,团队里每个人更加开心。 不断壮大的社区 Docker 现在更新得很快,甚至比 chrome 还快。更重要的是,参与增加新功能和修复 bug 的社区数量在大量增加。 无论是为为镜像贡献还是为 Docker 做贡献,甚至是为 Docker 的周边工具做贡献,有一大批聪明的人正在为其努力,因此我们也不能置身事外。我们发现 Docker 的社区十分活跃有意义,我们非常高兴能够成为其中一员。 Docker + CoreOS 我们也处在探索阶段,但是我们发现 Docker 和 CoreOS 的结合对于我们来说似乎是更好地选择。Docker 提供了稳定的镜像管理和容器。CoreOS 提供了一个精简的云(如阿里云)操作系统、机器级别分布式编排和虚拟状态管理。这个组合关注问题的不同方面,是一个更合理的基础设施栈。 挑战 每一个服务器端的技术需要微调和定制,尤其是大规模运行的时候,Docker 也不例外。(例如:我们跑不到5000万的任务,一个月50万小时计算,并且不断更新我们的镜像)。下面是我们使用大量 Docker 容器数时遇到的一些挑战: 向后兼容性不够 该领域的快速创新虽然是一个优势,但是也存在缺点。其中之一是向后兼容性差。在多数情况下,我们遇到的问题主要是是命令行语法、 API 的改变,从产品角度来说这不是一个严重的问题。但是在某些情况下,它影响了操作性能。例如,在任何启动容器后引发的 Docker 错误,我们要解析 STDERR 并根据错误类型进行响应(例如重试)。很不幸的是,错误的输出格式随着版本不同变化,不得不在不断变化的结果中调试,使我们十分疲惫。 图注:Docker的错误率 这个问题相对来说还比较好解决,但意味着每次的更新要经过多次验证,并且你需要一直开发直到这个更新的版本被发布到了系统大部分环境中。我们几个月前使用v0.7.4,现在我们的系统更新到v1.2.0.在这个领域我们已经有了一个很大的进步。 有限的工具和库 虽然 Docker 有一个四个月前发布的稳定版本,围绕它的一些工具仍然不稳定。采用 Docker 生态圈中的大部分工具意味着需要投入更多的精力。为了使用最新的功能、修复 bug ,你团队中需要有人熬夜加班对这些功能,频繁的进行一些修改.也就是说,我们很高兴有一些 Docker 周边的工具在开发,而且很期待能够有一个工具在其中脱颖而出。我们对 etcd 、 fleet 、 kubernetes 比较看好。 删除操作时间长 起初删除容器时间长,需要太多的磁盘I/O操作。这导致我们的系统速度明显变慢,形成了瓶颈。我们不得不增加可用的内核数目,而这个数量远远超出我们所需的。 图注:快速删除Docker容器的解决方案 通过研究使用 devicemapper(一个 Docker 的文件系统驱动),我们发现设置一个选项有作用--storage-opt dm.blkdiscard=false ,这个选项告诉 Docker 删除容器时跳过花费时间长的磁盘操作,大大加速了容器的关闭过程。当修改好删除脚本后,这个问题就没了。 战胜困难 接下来根据我们的经验,更深入的讲我们讲我们遇到的问题和我们的解决方法。问题列表主要来自我们 Ironworker 的首席开发兼工程运营总监 Roman Kononov 和一直在调试和规范化我们 Docker 操作的 Sam Ward 。 图注:Debug时的一个异常 说明一下,当我们遇到和 Docker 相关或者其它系统相关的问题,我们可以自动的重新执行任务,对用户没有任何影响(重试是平台的内置功能)。 内存限制开关 Docker 其中的一个发布的版本中突然新增了内存限制选项,删除了 LXC 中的选项。其结果是一些工作进程到达内存界限,然后了整体不响应。这弄得我们措手不及,因为即使使用了它不支持的设置, Docker 也没有出错。解决方法很简单,即在 Docker 内部设置内存限制。 卷无法卸载 因为 Docker 没有可靠地卸载卷,容器不能正确地停止。这导致容器永远在运行,即使已经完成了任务。解决办法就是显示地调用用户自己写得一些列脚本来卸载卷,删除文件夹。幸运的是,这个问题是之前我们使用 Docker v0.7.6 版本时遇到的,当 Docker 更新到 v0.9.0 解决了这个问题后我们就删除了那些冗长的脚本。 未来计划 正如你所看到的,我们对 Docker 投入很多,我们在接下得每天会继续投入。除了用它来隔离用户在 IronWorker 中运行的代码,我们也准备在其他的一些领域使用它。这些领域包括: 企业内部部署版 使用 Docker 作为主要分发方法, IronMQ 企业内部部署版简化了我们的分发工作,并且提供了一个简单通用的在几乎任何云(如阿里云)环境中都能部署的方法。就像我们在共有云上运行的服务,客户需要的就是可以运行 Docker 容器的服务器,同时他们可以相对容易的获得在测试或生产环境中运行的多台服务器(如阿里云服务器)的云服务。 生成和加载程序 我们也在用 Docker 容器在 IronWorker 中生成和加载程序。一个显著的进步是为用户改进了,大规模、特定任务负载和工作流的创建、上传、运行任务的过程。还有一个好处是用户可在本地测试程序,而测试环境和我们的生产服务一致。 IronWorker 后台 除了使用 Docker 作为任务的容器,我们也在使用它来管理每个服务器上运行的用来管理和启动任务的进称。每一进程着的主要任务是从队列中拿一个任务,把它放到合适的 Docker 容器中,运行,监测,运行完后删除环境。有趣的是同一台机器上我们有容器化的代码来管理其它容器。把我们所有的基础设施环境放到 Docker 的容器中让我们在 CoreOS 上的运行相当容易。 IronWorker, IronMQ,以及 IronCache APIs 和其他的运维团队一样,我们也不喜欢部署。能够把我们的所有的服务打包 Docker 容器中,然后简单、确定地部署,我们十分地激动。不用再配置服务器,我们需要的就只是能够运行 Dokcer 容器的服务器。我们正在替换我们的服务器搭建,使用 Docker 容器在服务器上为我们发布的产品搭建环境。变得的灵活、简单,有更可靠的协议栈。 原文出自:https://docker.cn/p/docker-in-production-what-weve-learned 上一条: 学会爱上复杂的多云 下一条: 云计算怎样改变数据保护
|