部署脚本演进

####缘由 系统在外网开发,但测试、生产环境却在内网私有云上,两边的网络不通,像Jenkins之类的持续集成工具都无法使用。内网环境的部署都是通过手工操作的。整个项目大大小小7个包,从外网拷到内网,再备份、部署,花的时间也不少。后期随着用户访问量增加,系统横向扩展是必不可少的。应用部署在多台服务器上,这时如果还采用手工方式,那工作量将成倍增加。其实除了从外网拷到内网这一步需要手工操作外,其他的都可以实现自动化。按照谷歌SRE的标准,部署工作属于琐事,应尽量将时间减少到最小。于是这段时间整理了备份部署的流程,并编写了相关的脚本。

####脚本需求 灵活性: 系统最后将产品化,会在不同的环境下使用。脚本应体现足够的灵活性,满足在不同环境下部署的需要。

支持分布式部署: 产品中的各个应用模块都支持横向扩展,脚本需支持多服务器并行部署,当服务器增加时,部署工作量不应随之增加。

####部署流程 准备一台部署服务器,所有的脚本统一在这里管理,运行。如果没有多余的机器,也可和某一个应用共用一台服务器。备份、部署流程如下:

####单机部署脚本 为保证脚本的灵活性,把可能变化的值都写到一个配置文件里,脚本运行前会先加载该配置文件,以获取相应的参数值。

每个应用一个部署脚本,后面可以灵活组合,也可以做一个简单的人机交互界面,方便小白人员使用。

实现集中式部署,需要解决两个问题:

  1. 部署服务器和各应用服务器之间实现ssh双向免密连接。方法如下: a. 用“ssh-keygen -t rsa” 命令生成公/密钥。 b. 用“ssh-copy-id -i ~/.ssh/id_rsa.pub 用户名@ip”命令把公钥复制到远程服务器。 然后在另一台服务上再操作一遍,就可实现双向免密连接

  2. 脚本虽然在部署服务器上运行,但其中关键的命令是要在远程应用服务器上执行的,用以下方式实现:

    ssh root@$ccuap_server_ip  << remotessh
    # the script here will be run in remote app server
    ...
    ...
    # exit when finished.
    exit
    remotessh # don't leave space at beginning.
    

    另外,脚本中尽量不要使用rm -rf xxx,特别是像 rm -rf $path/这样的命令,有很大的风险。一旦变量path为空,就相当于“rm -rf /”, 如果又恰好以root用户执行的,那后果就相当严重了。我的办法是先mv到临时文件夹中,后面再统一清理。

####并行部署脚本 开始的想法是通过“deployXXX.sh server1 server2”这样的方式来实现多服务器部署。这种方法服务器多了也不太方便,脚本里又需要加各种判断,循环,增加了复杂度,不易维护。后来发现有并行ssh工具,并行部署的问题就变的简单了。我用到的工具是这两个:

  1. mussh 该命令可以并行的在多台服务器上执行一段脚本,用法如下:
    mussh -H hosts -C xx.sh
    

    hosts文件里维护一个主机列表,每行一个主机名或ip。 xx.sh就是要执行的脚本 mussh无需安装,网上下载的压缩包,直接解压就可使用。

  2. pscp 并行scp,可以同时复制文件到多台服务器上,用法如下:
    pscp -h hosts source dest
    

    网上下载pssh安装包,建议源码安装,pscp是里面的一个工具。 有了这两个个工具,把前面的部署脚本修改下,就可以实现多服务器并行部署了。

Written on August 17, 2019