原来的服务的是怎样部署的?
1. 通过二进制安装
典型的有C/C++的程序,一般官网会提供编译好的安装包,例如MySQL,下载后直接配置使用即可。 这样的方式感觉还不错,把数据和程序都整理在一个目录里,扩容的时候直接拷贝即可,这样部署也是 单实例的。
2. 通过包管理工具安装
例如yum,使用官方源安装,或者使用国内的镜像源安装,一般也都是编译好的,还会安装好man手册。 优点是省心,一条命令即可,OK安装完了,What?到底安装了什么东西?在哪儿?不能一目了然。 有的在/etc下,有的在/var下,扩容时怎么办?
3. 编译安装
好处是能最大化控制结构清晰,指定prefix,都安装在一个目录下,包括所有该服务相关文件,引擎+配置+数据+log 引擎及工具有什么,一目了然,但是man手册不好查了。不过这样管理对于传统的服务来说,扩容还是比较 高效率的,目录结构组织清晰。而且编译过程也是学习的过程。缺点是如何安装比较大的程序,编译是非常 耗时的(只是首次编译,后续扩容只要版本够用则不用再编译),而且存在大量的依赖,往往会依赖像gcc-c++/ autoconf/automake/openssl,编译安装过程比较繁琐复杂,如果是安装小程序,则没有关系。
4. 通过配置管理工具安装
常用的配置管理工具有ansible/puppet/rex等,配置管理工具有各自的配置语法,这又带来了另一重复杂度。 不过对于大型环境来说可能会有帮助,对于服务器不多,业务部署环境简单的场景来说,似乎有些笨重。
原来的方法有什么问题?
1. 多实例部署困难
多实例的目的是提高资源利用率. 每个程序多实例的实现都有自己的一套方法,对于运维管理来讲就存在千百种管理方法。
2. 难以扩容迁移/复用
扩容迁移复用其实指的都是一个意思,软件如何从一台服务器迁移到另一台服务器后还能正常启动使用? 这里头的问题就多了,主要问题是环境不一致。如果不是静态编译的话,会存在动态库依赖,动态语言(Ruby, Python等) 就更不用说了,会有更多的依赖,除了依赖C库外,还依赖第三方的和其本身的库。再加上网络环境的不一致,无法访问外网等, 比如,有的网络不能访问外网也不能访问镜像源,在这种情况下,想要快速实现环境一致是非常难的。 特别是使用yum安装的软件,必须要借助配置管理工具了,如ansible,puppet等,速度也不理想。
Docker解决了什么问题
Golang本身是静态编译的,几乎没有依赖,或许是说没有普通的所谓依赖。这样就可以让我们构建一次,处处运行。极大的提高了软件运行环境及配置环境的复用性。
有很多标准的软件就可以打包成标准的版本,一个文件,别人拿过来直接启动就可以用了。
我原来的方法也可讲LNMP环境打包复用,只不过只能在特定的目录启动。限于我原来的水平,还没能想到这种方法,不过我的方法已经是朝着Golang/docker的理念去做的。 现在部署一些经典的应用例如Jenkins/LNMP只需要一条命令即可。也可以启动多个实例,从而提高资源利用率。
使用docker缺点是,镜像都特别大,而且相当于做任何事情都多加了一层复杂度,管理难度大大增加了。管理集群本身的成本就很高,如果是实例数量不多的话,则得不偿失了。