孙琪 译 分布式实验室
Docker正在风靡全球,成为开发和运行容器化应用的标准。
在以前,这类技术已经对于系统系统管理员和PaaS(平台即服务)的提供商产生了很大的作用。但是我们却很少听到创业公司对Docker的使用。尤其是那些处在初期阶段、初始员工数在1~10人的创业公司。这种印象与Datadoc HQ最近的调查(https://www.datadoghq.com/docker-adoption/)也比较相符:
如果你仍然不确定是否值得耗费精力使用Docker,我们觉得我们可以阐释一下使用面向容器的架构对我们的创业公司的作用。也会阐释为什么Docker值得一用,如果你尚未开始使用Docker。
研发经验
如果你在一家"two pizza(http://t.cn/RYvhYhH)"的小创业公司工作,那么你的团队中很可能有不少“多面手”类型的选手。一旦项目不再独立,你就会很快进入开发环境的大坑。
考虑一个简单的场景,一位前段工程师需要一个尚未发布的后端API接口。你可以使用模拟的接口数据来测试、开发,暂时的克服一下困难;或者,着手搭建开发环境。这些都可以。但是,都不如运行与后端代码兼容的系统来得敏捷。
docker-compose这种工具可以为我们创造奇迹。团队新手唯一需要做的事情,就是安装这个东西(https://www.docker.com/docker-mac)。调用一次docker-compose就可以让Docker为你搭建所有开发环境相关事宜,然后你就可以直接开始编码了。
这些工具本身的描述属性(Dockerfile)简单直接地解释了各个运行时组建如何互相通信。这使得你的顶层架构设计更加容易。
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- 5000:80
networks:
- frontend
depends_on:
- redis
result:
image: dockersamples/examplevotingapp_result:before
ports:
- 5001:80
networks:
- backend
depends_on:
- db
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
networks:
frontend:
backend:
volumes:
db-data:
可移植性
Docker不仅在开发过程中有用,也可以简化打包代码部署生产环境的过程。这是因为Docker使得生产环境和测试环境更为对称。这是开发/生产均势12要素(https://12factor.net/dev-prod-parity)中的一点。
对于不同的语言,我们已经有了非常棒的管理工具,例如rbenv(Ruby version management)和nvm(Node Version Manager)。这些工具使的我们从繁杂的运营时版本匹配的工作中解放出来。如果你的代码基于一些晦涩的原生二进制代码或者是某个特定的文件系统结构,那这些工具会更有用。
容器会在此基础上更进一步。容器使的我们可以把我们的应用程序与所需的运行环境完美的打包在一起。
这种可移植性也在混合云的构建过程中非常有效。这一点从我们的云迁移过程可以有更深入的理解。
当时,我们对于云服务商的不稳定性非常不满。我们决定迁移到“IaaS之王”——AWS亚马逊云服务。
我们预感到这次迁移早晚都要进行。所以,到那时我们会需要把我们的应用迁移到Docker上运行几个月。等到我们彻底告别我们原有的云的时候,整个迁移过程就可以在短短几天内完成。
如此大规模的迁移可以认为是小概率事件。但是我从未觉得增加灵活性有什么问题。
如果所做的事情与app无关,就完全没有意义。AWS等云服务商提供的已经投产的解决方案(https://aws.amazon.com/cn/cloudwatch/)或许可以解决监控、日志等在迁移过程中的割切问题。但是这些可以用容器化的开源解决方案实现,更加易于部署,而且可以让你避免“云监狱(http://t.cn/Rcdulfj)”的窘境。
编排
你需要还是不需要编排系统,并不是正确的问题。需要面对的问题是,你是否想让编排系统自管理、还是靠人工在凌晨3点修复系统崩溃的问题。
这个比喻所指的事情,涉及到很多迁移的部分。软件系统变得更加复杂,而且在运行时切割得更厉害。当网络分区的时候,软件系统会变的脆弱。
现在,容器本身并不能解决这个问题。恰恰相反,容器的短暂性使得你的系统变得无比动态化。这导致部署的时候难以保证运行时的依赖关系。
当系统规模需要扩展到集群时,情况更糟糕。使用集群,你永远无法精准确认你的进程可能在那个环节退出运行。这使得定位和为进程编址更加困难。但是从单一主机部署方案过渡到集群部署所必须要面对的情况。
我们尝试了几种集群系统,包括Google的Kubernetes、Mesosphere的Marathon和Hashicorp的Nomad。
我们最终使用了Docker自带的Docker Swarm集群管理工具来管理我们大部分的部署。我们使用的是简单的"Docker for AWS CloudFormation"模板(https://docs.docker.com/docker-for-aws/)。
首先,针对你的系统应该运行的服务,明确地描述所期待的系统状态。这样Swarm会持续地监控容器的实际状态。当某个节点失败时,Swarm会通过将工作负载重新编排到其他节点,使得服务达到预期的状态。如果某个节点无法恢复,Swarm也会通过重新部署新服务器的方式自行修复集群。
也许部署你自己的容器集群并不是你的需求。不过,新的CaaS(Containers-as-a-Service,容器即服务)平台正在涌现,通常不会比你的底层基础架构需要更多投入。
你会遇到很多概念,例如服务发现、负载均衡、软件定义网络、持久化存储、任务调度一集RAFT共识。从新概念漩涡到这些听起来很酷的行话,你肯定会有一次刺激但是有有趣的经历。
降低你的基础设施投资
你不需要再看一篇所谓的关于“我们如何通过换到{{ 随机某种语言 }}减少了{{ xxx台 }}服务器”的文章了(原作者可能可能习惯写js. 译者注)。我尽量给各位带来一点不一样的东西。
微服务概念最近非常火。我们已经将我们的服务拆分成几个不同的服务,参见我们的Beta Labs(https://medium.com/@betalabs)。这种方式使得我们可以使用不同的语言和开发框架实现一个项目。这也是的我们可以自由选择做某项工作时最好的开发工具。
请先忍耐我一下,我正试着用10个甚至更少的字来定义微服务。
12因素中的“一个代码基库,多处部署(https://12factor.net/codebase)”的原则,要求每个服务都应以其自身应用的方式部署在云平台上。而这恰好是PaaS服务收费模式的由来。
我们来看一组数字。在Hueroku环境中运行一个Ruby语音的app,需要至少运行两个web标准1倍速测量器。这是的你每个月需要花费50美刀,总共运行一个应用,而且只能使用512MB的内存。
上面说的是为前端服务花费的每月50美刀每GB的存储。加上另一个为简单的后台处理所需的测量器,又是每月25美刀。
你可能还也想要一些轻量级的后端服务,比如一些中间件或者有自定义逻辑的broker,这需要每个中间件一个服务器实例。你可能需要为此每月再花费100刀。
这还是我们在谈论附加组件之前呢。每月还得再花30美刀,买基础版Redis和PostgreSQL实例。Heroku的Logplex是只为流处理使用的。所以,如果你想要将日志保存的时间长一些,你需要再部署一个日志服务,这个服务得能被多个app共享使用。
让我们看看我们怎样做才能好一些。
我们借用马丁福勒对微服务的阐述。将容器与集群系统结合使用,为动态扩展你的软件服务提供了优雅且适用的平台。
部署在节点上的容器可以最大限度地利用可用资源。所有的节点共享一个内部的软件定义网络SDN。所以,你的各种服务可以互相通信,而不需要离开集群。
现在我们回到先前的例子中。这样的系统可以部署在3个节点上,基于t2.micro Docker Swarm的集群,这大概花费每月50刀。你可以使用总计3GB的内存。你还可以试试在额外存储空间中,运行你自己的容器化的Redis实例。
Heroku的测量器在CPU部分非常有优势,可以把1个核虚拟成8个核。但是,除非你的服务是用一种有原生线程的语言运行的,你会发现运行"每测量器多进程"的部署,512MB的内存并不够快。况且,如果你的工作负载是I/O为主,那么效率上的区别并不大(I/O类操作主要靠CPU)。
别误会,只要能让DevOps不成为复杂度瓶颈,这并不会比Heroku好多少。我并不是建议你或者你们团队中的任何一个人独自研究、花费好几个通宵学习如何以高可用的方式部署PostgreSQL。我只是在将两种情况做一些比较。
尽管如此,我觉得需要指出的很重要的一点是,你正在为这些可靠性、易用性付出额外的费用。基于此,你可以自行判断哪些到底是你觉得值得付的钱,哪些是你可以自己搞定的。
既然说到了Heroku,我需要提醒一点就是,你可以在Heroku上运行Docker(https://devcenter.heroku.com/articles/container-registry-and-runtime)。
内在的安全性
当把Docker平台跟PaaS平台对比时,安全性这一点并不是那么站得住脚。可是,你会发现,与在Ubuntu服务器上运行多个app的场景相比,你降低了被***的风险。
有什么不同呢?进入Linxu容器。通读Heroku的文档,你会发现曾经由Heroku支持者提出的这个引人好奇的概念,现在正是Docker的核心。随之而来的是一个更为人所赞赏的特性:隔离性。
举个最糟糕的情况的例子,某人在你的服务器里远程运行代码。听起来不太可能?看看ImageTragick(https://imagetragick.com/)。在容器中,应用会与容器有一一对应的关系。你可以将对于某一个应用的破坏隔离在那个应用的域中,而保证在这些主机上运行的其它服务的安全性。
这与虚拟机在很长时间内提供的特性相似。但是虚拟机总是会在部署和启动时稍微有点僵化、耗时长,另外运行一个完整操作系统也是需要付出很多开销。
对于虚拟机部署的场景,你当然可以让虚拟机的生存周期更长,并把它们当作爷来供着,好好维护(译意,直译:把它们当作宠物而不是耕地的牛。译者注)。但是以这种方式运行多个app就有可能需要更多的秘钥。
尽管集中化部署应用可以降低这种风险,但是这并不是说你的服务可以对开发者的误操作也免疫。比如说,你不会对访问主机的Docker daemon进程的权限上妥协。但是总的来说,容器化的环境确实减少了作为一个组织所需要面对的***面。
有一点需要谨慎,就是不要把你的Docker镜像公开化。
你喜欢它
可能上文是完全基于我们公司内部的极客们觉得有意义的事情,但是……
我们不能说我们在早先的时候没有遇到过一些边缘性细节问题。我必须承认,沉醉在这些新潮流的工具中说很容易的。
作为工程师,如果你觉得某些新工具能让你你的幸福感提升,拿你应该有能力将这些新新工具加到你的火药库中。这不正是创业公司的首要卖点么?
如果你决定暂时不使用或少使用Docker,你也几乎毁发现在未来的几年中,了解一些容器的知识是很有意义的。
结论
那么,容器化的天堂是不是一路畅通呢?呵呵,并不是。
我们是否可以等到Docker的“棱角”都“磨平”一些(技术更成熟一些)在使用更稳定的工具呢?可能能行。
作为一家创业公司,如果我们还没有用起来Docker,我们一定会失败么?这没有必然联系。
我们会再次在使用容器方面投资么?这个很确定,是的。
上面这些点,并不是专门针对创业公司的。我甚至觉得公司的规模并不相关。我对Docker的推崇,并不会影响到Docker在不同类型公司中的声誉。
我们并不是鼓吹Docker是解决这些永久问题的唯一方案。我们尚未讨论很多Docker的缺点。
但是就目前来讲,Docker确实是最一站式解决上面我们讨论的问题的最接近的方案。
总而言之,说容器会在这个时代发挥作用,这个无可厚非——等一下,你听说过serverless相关的事情么?考虑一下这个技术,相比起来,容器已经老掉牙了……
感谢阅读!如果你有任何想法或者问题,请在文后留言。如果你感到此文有益,那你就拍拍手吧!:)
原文链接:https://medium.freecodecamp.org/why-docker-makes-sense-for-startups-e9be14a1f662