原文地址:https://medium.com/@devfire/h…
原文作者:Igor Kantor
翻译君:CODING 戴维奥普斯
前情提要
在这个系列的第一篇文章中,我们详细地介绍了 DevOps 相关的文化和基础技能;在第二篇文章中,我们进入 DevOps 中各个模块并大致指明了如何为代码部署搭建基础;在第三篇文章中,我们讨论了如何合理的整理已经部署的代码;本篇文章中,我们将讨论如何打包代码以便于后续部署和执行。
现在我们已经来到了 DevOps 周期中关于代码打包的环节。
注意:你可以看到每个部件如何构建在前一部分上,并为后续部分奠定基础,这一点很重要。
因为无论你是在与现在还是将来的雇主交谈,你都必须能够清楚地表达出 DevOps 是什么以及它为何如此重要。而这就需要你通过讲述一个连贯的故事来达成——这个故事讲述了如何最好地、快速有效地将代码从开发人员的笔记本电脑发送到能赚钱的生产环境部署。
这也就是为什么我们不仅仅是在学习一些比较流行的 DevOps 工具。我们是在学习一整套被当前商业环境所需求的 DevOps 的理念和技术,以及在他们背后支持着的技术工具。
然后请记住,其实每个部分都需要将近一个多月的学习,一整套内容学习下来应该需要将近六个月的时间。
在虚拟化出现之前
还记得那些物理服务器么?就是必须等待几周才能发货,数据中心收到,放在机架上,再花时间搞网络、安装操作系统和修补的那些?
没错,他们先来的。
举个例子,拥有居住地的唯一方法是建造一座全新的房子。需要一个住的地方?想想盖个房子需要多久吧!虽然这个主意不错,是因为至少每个人都有房子了,而不是因为建房子需要很长时间。在这个类比中,物理服务器就像一个房子。
不久人们就对这些事情花了太长时间而感到恼火,于是一些牛人就提出了虚拟化的想法:在一台物理机器上运行一堆伪装的“假机器”,让每台假机器都像一台真机。这样如果你想要一栋房子,你可以建立自己的房子并等待六周;或者你可以直接住到公寓楼里与其他租户分享资源。这个想法也许不是完美的但已经足够,最重要的是开箱即用。
这种情况持续了一段时间,相关公司(像 VMware)也因此收割了很多利益。
直到又有人认为将一堆虚拟机填充到物理机器中还不够好:我们需要将更多进程更紧凑地打包到更少的资源中。
就像你觉得,房子太贵了,公寓也太贵了。如果只想暂时租一个房间怎么办?还想要那种能随时搬进搬出的。
于是 Docker 出现了。
Docker 的诞生
Docker 是一个新的东西,但其实 Docker 的理念很早就出现了。在 2000 年的时候,有一个叫 FreeBSD 的系统就提出过相似的概念。当时和现在的想法是隔离同一操作系统中的各个进程,即所谓的“操作系统级虚拟化”。
这在实践中意味着什么?
实际上,这意味着 Docker 的受欢迎程度急剧提升巧妙地映射了微服务的兴起——一种将软件分解为许多单独组件的软件工程方法。
而这些组件需要一个家。单独部署独立的 Java 应用程序或二进制可执行文件是十分痛苦的:管理 Java 应用程序的方式与管理 C++ 应用程序的方式不同,这与你管理 Golang 应用程序的方式不同。然而 Docker 能提供单一管理界面,允许软件工程师以一致的方式打包,部署和运行各种应用程序。
对于那个时候来说,这是具有跨时代意义的。
Docker 的优势
进程隔离
Docker 允许每个服务都具有完全的进程隔离。服务 A 存在于自己的小容器中,具有所有依赖关系;服务 B 存在于其容器中,具有所有依赖性。而且两者完全不会冲突。
此外,如果一个容器崩溃,只有该容器受到影响,其余的容器(应该!)仍然能继续愉快地跑着。这也有利于安全,如果容器被泄露,那么离开该容器并破解基本操作系统是非常困难的(但并非不可能!)。
最后,如果容器行为不当(消耗太多 CPU 或内存),则可以仅将爆炸半径“压缩”到该容器内,而不会影响系统的其余部分。
部署
想想在实践中各种不同的应用是怎么搭建的。
如果它是一个 Python 的应用程序,它将有各种 Python 包。一些将被作为 pip 模块安装,另一些是 rpm 或 deb 软件包,其他的则是简单的 git clone 安装。或者如果使用 virtualenv,它将是 virtualenv 目录中所有依赖项的 zip 文件。
另外,如果它是一个 Java 应用程序,它将具有一个 gradle 构建,并将其所有依赖项拉到适当的位置。
所以将各种使用不同语言和不同运行方式的应用程序,部署到生产环境进行构建将是一项重大挑战。
这样我们该如何确保各个独立进程的安全呢?
更有甚者,如果出现冲突就会变得更加麻烦。比如一个服务需要 Python 依赖库 v1,而另一个服务是基于 Python 依赖库 v2 的,因为 v1 和 v2 不能同时在同一台机器上安装,问题就产生了。
这时候,就需要 Docker。
Docker 不仅允许完全进程隔离,还允许完全依赖性隔离,在同一个操作系统上并排运行多个容器是完全可能和常见的,每个容器都可有自己的冲突的依赖库和包。
运行管理
同样,我们管理不同应用程序的方式因应用程序而异。Java 代码的日志记录不同,启动方式不同,监视方式与 Python 不同,而 Python 与 Golang 也不同等等。
通过 Docker,我们获得了一个统一的管理界面,允许我们启动,监控,集中日志,停止和重启许多不同类型的应用程序。这是一个巨大的胜利,并大大降低了运行生产系统的运维开销。
说了这么多 Docker 的好处,也是时候说说 Docker 的局限性了。
进入 Lambda 时代
首先,运行 Docker 仍在运行服务器。服务器很脆弱,必须对它们进行管理,修补和其他方面的保护。
其次,Docker 并非 100% 安全,至少不像虚拟机那样。大公司在虚拟机内部运行托管容器而不是在裸机之上,这样做是有原因的——他们想要容器的快速启动时间和虚拟机的安全性。
第三,没有人真正按原样运行 Docker。相反,它几乎总是作为复杂的容器编排结构的一部分进行部署,例如 Kubernetes,ECS,docker-swarm 或 Nomad。这些是相当复杂的平台,需要专职人员来操作。
但是,如果我是开发人员,我只想编写代码并让其他人管运行的事,Docker,Kubernetes 和其他繁琐的东西都不是简单的东西——所以我真的需要学么?这就要具体问题具体分析了。
对于那些只想让其他人帮忙运行其代码的人来说,AWS Lambda(以及其他类似的解决方案)就是答案:
AWS Lambda 允许你在不配置或管理服务器的情况下运行代码。只需为你消耗的计算时间付费——当代码未运行时不收取任何费用。
如果你听说过“serverless”,这就是它!不再需要运行的服务器或要管理的容器,只需编写代码,将其打包成 zip 文件,上传到亚马逊并让他们处理那些烦人的问题。
此外,由于 Lambda 是瞬时的,没有什么可以破解的,所以 Lambda 在设计上也是非常安全。
这样看来像 Lambda 这类的 serverless 功能真的挺不错的,但是即使这样,也是有缺点的。
第一,就现阶段而言,Lambda 暂时不支持长时间的进程。
其次,Lambda 是功能即服务(Functions-as-a-Service),这意味着你的应用必须完全分解为微服务的形式,并与其他复杂的 PaaS 服务(如 AWS Step Functions)协调。并非每个企业都处于或者能转变成这种水平的微服务架构。
第三,对 Lambda 进行故障排除是很困难的。作为云原生的应用,所有的 bug 修复都需要在亚马逊生态系统中修复,这通常挺烦人的且不直观。
简单来说鱼和熊掌不能兼得,要根据自己的实际情况进行选择。
总结
Docker 和 Lambda 是时下最流行的云原生对应用进行包装、运行和管理的方式。它们通常是互补的,适用于不同的用例和应用场景。
无论如何,现代 DevOps 工程师必须精通两者。因此,学习 Docker 和 Lambda 是很好的短期和中期的成长目标。
到目前为止,在我们的系列中,我们已经处理了初级到中级 DevOps 相关主题。在后续章节中,我们将开始讨论更适合中级到高级 DevOps 工程师的技术。但是,与往常一样,没有捷径可循,需要一步一步脚踏实地!
译后记
CODING 近期正式推出了 CODING 2.0 致力于帮助大型企业和项目以最低的成本和精力推动 DevOps 转型,同时也上线了制品库和全新的持续集成功能,为企业搭建 DevOps 的核心枢纽。有效解决研发团队解决应用管理管理粗犷和版本追踪混乱的问题。在 CODING 2.0 的 DevOps 自动化流水线当中,持续集成的构建物自动存入制品库中,在部署时按需获取对应的版本,制品库让研发团队真正做到 deploy anytime anywhere。
同时,CODING 也会持续关注并分享软件研发领域最新理念与技术,与 DevOps 工程师一起成长。