使用 Fabric 批量执行服务器任务
2012年10月29日 | 标签: fabric, linux, mac os x | 作者:vpsee
我们的服务器和虚拟机的环境配置都由 puppet 管理,但有时候需要临时执行某些任务和操作,比如同时更换500台服务器的密码、同时更新或者重启500台虚拟机、在特定几台服务器上添加或者一个用户、上传一个特定文件/脚本到1000台服务器等等。这些任务用 Puppet 可以做,但是不是最简洁的办法。我们需要一种工具能完成大量服务器上的批量操作,并且要简单可编程,Fabric 就是这样一个基于 Python 的服务器批量管理库/工具,Fabric 使用 ssh(通过 paramiko 库)在多个服务器上批量执行任务,我们只需要用 Python 编写这些任务脚本并指定要执行这些任务的服务器就可以了。
Fabric 依赖 paramiko,所以需要安装这两个:
$ sudo pip install fabric $ sudo pip install paramiko
编写一个简单的 Fabric 例子,在1台服务器上打印系统信息(uname -s):
$ vi fabfile.py #!/usr/bin/python from fabric.api import run def host_os(): run('uname -s')
在 vpsee.com 这台主机(host)上使用 root 帐户执行上面的任务 host_os:
$ fab -H [email protected] host_os [[email protected]] Executing task 'host_os' [[email protected]] run: uname -s [[email protected]] Login password for 'root': [[email protected]] out: Linux Done. Disconnecting from [email protected]... done.
来看一个更复杂点的例子,在多个服务器(grid00, grid02, …, grid05)上更换 root 密码(假设原密码是 root),注意加上 @parallel,这样任务是并行执行的,在大量服务器上会快很多:
#!/usr/bin/python # -*- coding: utf-8 -*- from fabric.api import * import string from random import choice import socket import paramiko env.user = 'root' env.password = 'root' env.hosts = [ 'grid00', 'grid01', 'grid02', 'grid03', 'grid04', 'grid05'] @task @parallel def passwd(user, passwd=False): with settings(hide('running', 'stdout', 'stderr'), warn_only=True): if isup(env.host): if not passwd: passwd = genpass() sudo("echo -e '%s\n%s' | passwd %s" % (passwd, passwd, user)) def genpass(length=10): return ''.join(choice(string.ascii_letters + string.digits) for _ in range(length)) def isup(host): print 'connecting host: %s' % host timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(1) up = True try: paramiko.Transport((host, 22)) except Exception, e: up = False print '%s down, %s' % (host, e) finally: socket.setdefaulttimeout(timeout) return up
使用 fab -l 查看我们刚编写的 fabfile.py 里面的可用命令,这个命令就是那个函数名 def passwd(user, passwd=False):
$ fab -l Available commands: passwd
使用这个命令批量更换 grid00-grid05 的 root 密码为 test,passwd 传递参数的时候接冒号,并且用户名和密码参数用逗号隔开:
$ fab passwd:root,test [grid00] Executing task 'passwd' [grid01] Executing task 'passwd' [grid02] Executing task 'passwd' [grid03] Executing task 'passwd' [grid04] Executing task 'passwd' [grid05] Executing task 'passwd' connecting host: grid05 connecting host: grid04 connecting host: grid02 connecting host: grid03 connecting host: grid01 connecting host: grid00 Done.
Fabric 的强大之处在于可以用 Python 编写各种任务(函数),这些任务可以指定到任何服务器上(通过 ssh),非常适合管理大量服务器、批量处理任务。另外 Fabric 工作方式非常简单容易理解,就是简单的 ssh 而已,没有内幕没有架构,不像其他工具什么客户端服务器端、什么中间代码、什么 DSL 领域专属语言(嗯,说的就是 puppet, chef)。Fabric 使用起来只需要懂点 Python 就可以了,不需要学命令、api、框架之类的。我们喜欢简单、容易理解的工具。
喜欢,学习了
Ansible怎么样?
http://ansible.cc/faq.html
强大~
ansible 和 fabric 不太算一类,ansible 应该和 puppet, chef, cfengine 等在一起算作 configuration management 工具,fabric 更像是 deployment/automation 工具。ansible 后面设计的想法不错,虽然其作者(也是 cobbler, func 的作者)的想法是不用像 puppet, chef 那样需要琢磨透一种配置语言,不过 ansible 还是需要一种 YAML 格式的配置语言 Playbooks.
那么saltstack呢?
http://saltstack.org/
fabric支持ssh跳板登录么?
ansible好像支持fabric的功能,比如更改用户密码:
ansible 127.0.0.1 -K -m shell -a “/bin/echo username:mypassword | /usr/sbin/chpasswd”
127.0.0.1可以用一组主机,就可以同时在多台主机上执行命令。
ansible简介:https://github.com/hyao/ansible/blob/devel/README_zh.md
playbook简介(翻译中):https://github.com/hyao/ansible-docs/blob/master/zh/playbooks.rst
如果所有的虚拟机在客户手上,而我想对虚拟机进行某个设置(比如升级下内核),又无法获得客户虚拟机管理权限,这种情况怎么办???
技术流啊,网站非常不错,推荐了。
既然用 puppet,可以考虑下 mcollective。
fabric依赖与ssh,稳定性不是很好,实际使用中容易出现问题。
mcollective使用消息中间件来做,不同的是需要在客户机有个daemon来接收处理这个消息,比较满足自家机器的管理,灵活性更高。
@nomyself
嗯,考虑过 MCollective,配置比 Fabric 复杂,MCollective 依赖 ActiveMQ 中间消息件,ActiveMQ 又依赖 Java 工具包。我们喜欢简单的工具~
MCollective用做跨idc,分布式部署很有用。想想,每个IDC里的内部服务器不能直接访问,ssh通过跳板又比较麻烦。
你好!我的执行结果如下,不知道为啥报错啦!请教下:
[root@linuxblind fabric]# fab passwd:root,test
[linuxblind] Executing task ‘passwd’
[linuxblind2] Executing task ‘passwd’
[linuxblind3] Executing task ‘passwd’
connecting host: linuxblind3
connecting host: linuxblind2
connecting host: linuxblind
Fatal error: Needed to prompt for a connection or sudo password (host: linuxblind), but input would be ambiguous in parallel mode
Aborting.
Fatal error: Needed to prompt for a connection or sudo password (host: linuxblind3), but input would be ambiguous in parallel mode
Aborting.
Fatal error: Needed to prompt for a connection or sudo password (host: linuxblind2), but input would be ambiguous in parallel mode
Aborting.
Fatal error: One or more hosts failed while executing task ‘passwd’
Aborting.
楼主给力的,简单顺手才是王道。
其实自己写一个也很容易,我手里自己写的一个ssh_sudo.rb,只有51行。
通过ssh做类似的事情。中间还增加了sudo这个操作。
[build101:~/bin]$ wc -l ssh_sudo.rb
51 ssh_sudo.rb
[build101:~/bin]$
[build101:~/bin]$ ssh_sudo.rb logs101 whoami
root
[build101:~/bin]$