关于批量部署
关于服务器批量部署这一块,现在比较流行的有ansible,saltstack这两个开源项目,掌握它们之一固然是好的,但是不可忽视的是它们的学习成本。
就拿ansible来说,它本身也是通过中控机并行的对服务器发起ssh远程命令,而它真正厉害之处在于:任务编排。
什么是编排?
把我们要的部署的任务拆成几个步骤,给每个步骤编写部署逻辑并提供一个检查成功的方法,将这一切写在一个ansible的执行计划文件中,那么接下来ansible会替我们完成这个计划,中途失败与重试等问题都由ansible全权负责,程序监督任务,人就可以解放出来了。
在项目发展期运维水平较低,更多的靠人与高效简单的工具来完成一些简单的运维:
- 几十台~上百台服务器的规模。
- 服务器的标准化环境搭建。
- 项目代码的上线与回滚。
即便没有ansible这样的任务编排系统,我们依旧可以自己编写脚本逻辑,亲自保障部署的幂等性和可靠性,只是无法复用罢了。
(我曾经在公司用ssh管理过50台服务器的项目部署升级,为了缩短串行处理时间将50台服务器的ssh/scp命令全部置于后台执行,执行结果都无从知晓)
轻量级方案
我个人认为:100台以内的服务器如果可以提供清晰的执行结果列表,让我能够识别哪些服务器执行失败,并且能够提供并行的部署能力即可,至于100台以上怎么办?找一位会ansible的专业运维即可。
幸好有开源的工具为我们直接提供并行的ssh/scp,这个项目叫做:pssh(并行的ssh),提供pssh,pscp…等多个实用的工具,并能够提供清晰的执行结果返回值,因此用脚本识别处理执行结果也不会很麻烦。
下面简单的记录一下安装与使用的思路,希望帮助你快速的用起来。
sshpass建立信任关系
作为中控机,首先需要解决的就是ssh访问其他服务器的密码验证问题,一般我们都通过配置信任关系解决。
如何给几十台机器初始化信任关系呢?并不复杂,我们需要安装一个sshpass工具,它和expect工具原理类似,都是在ssh连接的时候自动输入密码,但是sshpass显然在使用方面比expect更简单。
首先下载并安装sshpass(点击找到下载链接):
1 2 3 |
liangdongdeMacBook-Pro:sshpass-1.06 liangdong$ pwd /Users/liangdong/sshpass/sshpass-1.06 liangdongdeMacBook-Pro:sshpass-1.06 liangdong$ ./configure && make && make install |
然后为中控机生成ssh的公钥(大家都应该很熟悉),这条命令可以避免你输入一些信息:
1 |
echo -e 'y\n' | ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa |
现在,需要利用sshpass的能力,将中控机的公钥拷贝到各个服务器上的~/.ssh/authorized_keys文件中,从而建立信任关系:
1 2 3 4 5 6 7 8 |
liangdongdeMacBook-Pro:sshpass liangdong$ cat trust.sh #!/bin/bash # 中控机的公钥(ssh-keygen手动生成即可) pub_key=`cat ~/.ssh/id_rsa.pub` # 将公钥下发到每台机器上 sshpass -p '目标机器的密码' ssh -o "StrictHostKeyChecking=no" root@目标机器的HOST "echo -e 'y\n' | ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa;echo $pub_key>~/.ssh/authorized_keys" |
作为一个简单例子,这个脚本仅下发了一台机器:
- 首先取出中控机的公钥备用。
- sshpass -p 可以指定目标机器的密码,这样就实现了免密。(实现原理是这样的:sshpass创建2个单向管道并启动ssh子进程,分别重定向ssh子进程的标准输入/输出到2个管道上,这样ssh进程原本写到命令行的内容就被sshpass拦截,sshpass识别出对方机器要求输入密码的时候就将密码通过标准输入管道写给ssh进程,ssh进程再通过socket发给对端服务器)
- ssh部分和普通写法没有区别,做的事情是为每个服务器生成ssh key,并将中控机公钥写到它们的authorized_keys文件中去。(传-o StrictHostKeyChecking=no,为了避免ssh出现y/n提示)
在此之后,使用ssh/pssh就可以直接连接到目标服务器而无需密码了,但是-o StrictHostKeyChecking=no仍旧必须传递,具体原因参考这里。
安装pssh
项目在google-code维护,可以自行了解安装。
原理方面:
pssh在实现上使用了python,在网络并行方面使用IO多路复用使用了poll(代码可见这里),在文件的读写方面通过python threading实现并发(实际受限于Python的GIL锁)。
相关博客介绍:
pscp并行拷贝
无论任何部署任务,我非常建议将所有逻辑写到一个脚本中,并将脚本下发到各个服务器上,最终远程执行脚本即可;非常不建议的做法是将逻辑写在中控机上,然后远程执行每一条命令,这不是一种合理的做法。
因此,我编写一个测试用的部署脚本,它确保nginx正确安装:
1 2 3 4 5 6 7 8 9 10 11 |
liangdongdeMacBook-Pro:sshpass liangdong$ cat setup.sh #!/bin/bash # 如果nginx不存在,就安装 if [ ! -f "/usr/sbin/nginx" ];then yum install -y nginx # 安装失败返回1 if [ $? -ne 0 ];then exit 1 fi fi |
我们现在使用pscp将部署脚本分发到机器上去:
1 2 |
liangdongdeMacBook-Pro:sshpass liangdong$ pscp -H root@目标HOST -O "StrictHostKeyChecking=no" -r ./setup.sh /root [1] 13:10:54 [SUCCESS] root@目标HOST |
- 命令将setup.sh拷贝了目标机的/root目录下。
- 打印的每一行代表某个Host的拷贝成功情况。
- 利用-h参数传入一个包含多个Host的文件可以实现并行拷贝。
pssh并行部署
部署脚本已下发完成,现在需要并行的执行:
1 2 |
liangdongdeMacBook-Pro:sshpass liangdong$ pssh -H root@目标HOST -t 300 -O "StrictHostKeyChecking=no" "/bin/bash /root/setup.sh" [1] 13:16:33 [SUCCESS] root@目标HOST |
- 同样可以使用-h传入Host文件实现并行。
- -t控制单个Host的最长执行时间(这是普通ssh无法做到的)。
- 命令部分执行setup.sh脚本,脚本退出码是0则成功,否则失败。
默认pssh不会将远程执行的标准输出和标准错误打到屏幕上,而是仅仅列举每个Host的执行结果,如果你希望打印输出可以用-P选项或者自己看看完整的–help帮助。
本篇博客很简单,就到这里了!
如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~
