服务器部署的决策与实践(3) 软件安装方法的选择
之前谈了我对服务器操作系统和软件版本选择的看法,这周来讲讲我通常是如何安装软件的,以及为什么选择这些方法。
本文是 服务器部署的决策与实践 系列的一部分。
我最常用的安装方式,是操作系统自带的包管理器,加上合适的源。所谓合适,就是要视软件具体情况而定,但总体的原则仍然是在满足功能和性能需要的前提下,降低维护成本。
官方源
比如上周就提到过,对于 nginx ,我通常只用于简单的反代,无论性能还是功能,操作系统自带的版本均能胜任,因此就直接使用系统自带的源。
第三方源
至于 PostgreSQL,做为我最核心的应用平台,新版本提供的特性以及性能优势就会比较重要,所以会采用第三方源来安装较新版本,寻找第三方源可以先从软件官网入手,看看是否有软件官方背景的源。比如 PostgreSQL 官方就为 Debian、Red Hat/CentOS、SUSE、Ubuntu 这些发行版提供了源和相应的操作说明。

如果你使用这些发行版或者其衍生系统,就可以按照里面的指引进行安装。但方法大同小异,先在包管理器的配置目录下添加一个新源的配置文件,里面包含了源的名称、地址、是否启用、GPG校验等信息,然后更新包管理器的缓存使其生效,最后找到相应的软件进行安装。
使用软件官方背景的源通常能获得最新的版本和及时的安全更新,里面通常也会同时提供多个支持周期内的版本,方便按需选用。
# yum search postgresql*-server
Failed to set locale, defaulting to C.UTF-8
Last metadata expiration check: 1:31:07 ago on Sun Dec 27 13:20:58 2020.
================================== Name Matched: postgresql*-server ===================================
postgresql13-server.x86_64 : The programs needed to create and run a PostgreSQL server
postgresql12-server.x86_64 : The programs needed to create and run a PostgreSQL server
postgresql11-server.x86_64 : The programs needed to create and run a PostgreSQL server
postgresql10-server.x86_64 : The programs needed to create and run a PostgreSQL server
postgresql96-server.x86_64 : The programs needed to create and run a PostgreSQL server
postgresql95-server.x86_64 : The programs needed to create and run a PostgreSQL server
有些软件的官方并不直接提供源,而是推荐其他的第三方源,比如 Node.js 官网只提供源码和二进制包两种形式,第三方源则是推荐商业公司 nodesource 提供的源。
比起使用二进制包或从源码编译,通过第三方源安装的优势主要是降低维护成本,首先通过包管理器进行安装不用考虑安装位置和启动脚本的问题,软件安装完毕后可以直接用 systemd 管理软件的启停以及开机启动,不需要自己编写控制脚本。如果你开了 SELinux 等功能,权限的设置也会更容易,因为各种设置管理都会符合所用操作系统的常规操作思路。另外就是软件的更新可以通过定时脚本完成,不需要手动干预。
当然第三方源,视情况而定,也会有相应的缺陷,比如和系统环境冲突,预先编译版本功能不完整,以及难以多版本并存等。
系统环境冲突是指第三方源可能会占用官方源中同名软件的位置,安装时会替换掉系统自带的版本,如果这个软件本身和系统结合紧密,就可能引起一些问题,比如 yum 本身是用 python 实现的,你用第三方源换掉官方源中的 python 就可能导致系统层面的问题。不过现在大多数第三方源都会通过更名来减少冲突,比 IUS 源中的 python 会叫做 python35u 来避免和官方包重名。
冲突的另一种形式是 lib 冲突,比如安装 IUS 源中的 MySQL 会提示要安装新的 mysql-lib ,而原来的版本正在被其他软件使用。这时必须卸载掉依赖 mysql-lib 的软件才能继续,尽管我在实际使用中没有感受到什么问题,但也可能埋下了隐患。
从源代码编译
预先编译版本功能不完整,是说第三方源中提供的版本在编译时所采用的参数通常也是在性能、功能上做了取舍,相对小众的功能可能没有包含在其发布的二进制版本中,这个问题我在使用 nginx 时遇到过。nginx 提供了基础的 webdav 功能,但其未包含在官方提供的二进制版本中,遇到这种情况,就要考虑自己编译了。但自己编译就会遇到依赖缺失的问题,甚至部分软件编译所需的环境比较复杂,需要掌握和开发语言相关的一些工具才能进行,大大提高了安装维护的成本,因此不到万不得已就不要选择自己编译了。特别是遇到功能不完整的情况,首先要检查缺失的功能是否是以动态库或插件形式提供的,比如安装了上面提到的 postgresql13-server 之后,会发现很多常用扩展缺失了,但其实是因为这些功能被拆封到了附加的包中,方便用户按需取用,比如前面说的情况,只要再安装 postgresql13-contrib 就能解决。
# yum search postgresql13-*
Failed to set locale, defaulting to C.UTF-8
Last metadata expiration check: 0:52:34 ago on Sun Dec 27 19:27:23 2020.
==================================== Name Matched: postgresql13-* =====================================
postgresql13-docs.x86_64 : Extra documentation for PostgreSQL
postgresql13-libs.x86_64 : The shared libraries required for any PostgreSQL clients
postgresql13-odbc.x86_64 : PostgreSQL ODBC driver
postgresql13-test.x86_64 : The test suite distributed with PostgreSQL
postgresql13-devel.x86_64 : PostgreSQL development header files and libraries
postgresql13-pltcl.x86_64 : The Tcl procedural language for PostgreSQL
postgresql13-plperl.x86_64 : The Perl procedural language for PostgreSQL
postgresql13-server.x86_64 : The programs needed to create and run a PostgreSQL server
postgresql13-contrib.x86_64 : Contributed source and binaries distributed with PostgreSQL
postgresql13-llvmjit.x86_64 : Just-in-time compilation support for PostgreSQL
postgresql13-plpython3.x86_64 : The Python3 procedural language for PostgreSQL
而对于为了提高性能而选择自己编译的做法,很多数情况下是属于过早优化和自我感动。这是一个“当你需要的时候,你自然会知道“的问题,如果你不确定是否要做,那就不要做,或者至少先把通过修改配置文件就能获得的性能提升给榨干。
容器
还有一个问题是多版本并存,根据我上一篇文章的策略,其实不该遇上这个问题。如果实际工作中难免碰到,就是时候上容器技术了,其实容器能解决上面讲到大多数问题,包括某些软件官方源不包含特定组件的问题,也能通过使用其他人编译好的版本来免除自己编译的痛苦。
虽然 Docker 等容器技术比起原来的虚拟机变轻了,但是相较包管理器还是重一点,同时也引入了一门新的技术,增加了整体复杂度,所以我只是将其作为特殊情况的备用方案。解决诸如同时运行一个软件的多个版本,运行当前发行版不支持的版本,或者运行需要复杂环境的软件等问题。
总结
总结一下,我安装软件首选策略是通过系统自带的包管理器,结合适当的源来进行,基本上已经能满足日常的生产环境部署需求,而在遇到特定情况时才会采取从源代码编译或者使用容器技术等作为辅助手段。
上面讲到的都是针对单个具体软件的安装方法,那么如果有多台服务器需要安装时,如何提高效率并保证安装的一致性呢?终于轮到 Ansible 出场了。