【CICD】部署方式
在前面的学习中,我们了解了,CI 流程有什么用,以及是如何运作起来的。从本节开始,我们将会开始学习 CD 流程。
持续部署(英语:Continuous deployment,缩写为 CD),是一种软件工程方法,意指在软件开发流程中,以自动化方式,频繁而且持续性的,将软件部署到生产环境(production environment)中,使软件产品能够快速的发展。
当然,在学习持续部署(CD)前,我们要先了解一下在此之前我们是如何做的。
刀耕火种的手工作坊时代:SSH
在软件开发中,有一个非常需要关注的方向就是如何去把我们开发好的产品部署到服务器上,即如何将我们的产品摆上货架。
回顾历史所能探索到的、比较有体系的部署方式就是通过 ssh 了,ssh 是 linux 内置的一个网络协议,我们可以通过 ssh 来实现远程登录以及文件传输。因此,通过 ssh 进行发布就是一种比较常见的选择了。
我们可以通过 ssh 的 sftp 协议将本地编译好的应用(比如 java 中的 war 包)传输到服务器上,或者通过 ssh 远程登录到服务器上然后通过版本控制工具下载源码打包编译,然后在服务器上起一个持久化的应用,比如apache /tomcat 之类注册到系统的服务,或者通过 screen / tmux 之类的终端工具起一个永不挂断的终端应用。更有甚者也可以通过nohup 命令启动,tail -f 查看日志, kill 中断应用。
当然程序员永远不可能满足于此,程序员们可以编写一些自动化脚本帮我们去做这些事情。比如编写一个 py 脚本,建立一个ssh 连接,自动化的在远程服务器上执行一些命令,实现一键部署,这在当时是很多程序员的首选方案。
然而,总的来看,将一个后端服务在服务器上启动的方式有很多种,但是这些方式也还是逃不开粗糙的本质,我们透过花里胡哨的操作与自动化脚本,究其本质还是脱离不了 ssh 的限制。其内核还是一个一对一的操作,即一个client 终端对应一个server 服务端,这就决定了不论怎么样,这种部署方式对于大规模去应用是不可行的。不管做到何种地步都逃脱不了其手工作坊的本质,更何况还会有各种各样运行环境带来的边界问题困扰着当时的程序员。
那么有没有可能有更加优雅方式,实现从手工作坊完成到工业革命的蜕变呢?
Docker 对此举起了革命的旗帜。
工业革命的制品工坊:Docker Image
docker image 的引入对业界产生了一些颠覆性的变革,首先一点就在于环境的隔离性。为什么这么说呢?以 Linux 的软件生态举例,在 Linux 的包管理中有很多软件都是以源码发布的,不仅仅是因为开源的问题,而是因为 Linux 的生态多样性导致很难预先编译出一个或者多个二进制文件可以同时兼容不同的 Linux 环境,因此与其提供二进制文件不如直接提供源码,让使用者在自己的环境下编译出一个自己环境能够解析的二进制文件。
而类似的问题也存在部署的时候,试想一下,一个应用在本地是正常的,到了线上就出现各种各样奇怪的问题,那是一件多么令人崩溃的一件事情。而不仅于此,如果在服务器 A 是正常的,然后觉得没有问题了,欢天喜地的将文件部署到服务器 B 上,结果出现了问题,那才是真的令人崩溃。
与此类似的,源码编译依赖各种各样版本的编译器,运行时依赖各种各样版本的动态链接库。而这些往往都是在一个环境/系统中唯一的。在实际出现问题之前,这是一个完全混沌的系统,因为你在出现实际问题之前往往很难观察或者说处理不同版本环境的兼容问题——而当实际出现问题以后,往往已经产生了损失。
因此,可以看到,一个完全隔离的运行环境是多么重要,特别的,docker 的环境是一个系统级别的环境,比起应用级别的环境更加底层也更加彻底。系统级别的环境隔离意味着在所有的环境都拥有完全一样的上下文,一台服务器的成功意味着所有服务器的成功。所以我们可以看到,环境隔离是多么重要,而docker 的成功也很大程度上来源于此。
docker image 意味着所有的操作都是可复制的。而工业制品与手工业的区别也在于此,这就是为什么我会将 docker 的出现称为工业革命。后续,软件工程师们围绕着docker image 的强大隔离性和原子性,出现了诸如自动扩容、滚动升级、高可用、分布式、以及我们本书主要讲的CICD等一系列提升软件质量与服务稳定的优秀实践。
总结
在本节,我们了解了 docker 的重要性以及能力,下一节我们会学习如何通过 docker 构建一个自己应用的镜像,以及在后续学习如何将这个镜像部署到服务器上。
小思考: 你平时是如何部署应用的呢?
