ansible <host-parttens> [-f forks] [-m module] [-a args] ' args '
host-parttens:servername 或者src1:src2 同时src1:&src2
-f :指定一次运行多少并行的进程
现在执行如下命令,这个命令中,atlanta是一个组,这个组里面有很多服务器,”/sbin/reboot”命令会在atlanta组下 的所有机器上执行.这里ssh-agent会fork出10个子进程(bash),以并行的方式执行reboot命令.如前所说“每次重启10个” 即是以这种方式实现:
$ ansible atlanta -a "/sbin/reboot" -f 10
如果想通过 sudo 去执行命令,如下:
$ ansible atlanta -a "/usr/bin/foo" -u username --sudo [--ask-sudo-pass]
如果你不是以 passwordless 的模式执行 sudo,应加上 --ask-sudo-pass
(-K
)选项,加上之后会提示你输入 密码.使用 passwordless 模式的 sudo, 更容易实现自动化,但不要求一定要使用 passwordless sudo.
也可以通过``–sudo-user`` (-U
)选项,使用 sudo 切换到其它用户身份,而不是 root(译者注:下面命令中好像写掉了–sudo):
$ ansible atlanta -a "/usr/bin/foo" -u username -U otheruser [--ask-sudo-pass]
在有些比较罕见的情况下,一些用户会受到安全规则的限制,使用 sudo 切换时只能运行指定的命令.
这与 ansible的 no-bootstrapping 思想相悖,而且 ansible 有几百个模块,在这种限制下无法进行正常的工作. 所以执行 ansible 命令时,应使用一个没有受到这种限制的账号来执行.
command 模块不支持 shell 变量,也不支持管道等 shell 相关的东西.如果你想使用 shell相关的这些东西, 请使用’shell’ 模块.两个模块之前的差别请参考 模块相关 .
使用 shell 模块的示例如下:
$ ansible raleigh -m shell -a 'echo $TERM'
File Transfer
这是 /usr/bin/ansible 的另一种用法.Ansible 能够以并行的方式同时 SCP 大量的文件到多台机器. 命令如下:
$ ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts"
若你使用 playbooks, 则可以利用 template
模块来做到更进一步的事情.(请参见 module 和 playbook 的文档)
使用 file
模块可以做到修改文件的属主和权限,(在这里可替换为 copy
模块,是等效的):
$ ansible webservers -m file -a "dest=/srv/foo/a.txt mode=600"
$ ansible webservers -m file -a "dest=/srv/foo/b.txt mode=600 owner=mdehaan group=mdehaan"
使用 file
模块也可以创建目录,与执行 mkdir -p
效果类似:
$ ansible webservers -m file -a "dest=/path/to/c mode=755 owner=mdehaan group=mdehaan state=directory"
删除目录(递归的删除)和删除文件:
$ ansible webservers -m file -a "dest=/path/to/c state=absent"
Managing Packages
Ansible 提供对 yum 和 apt 的支持.这里是关于 yum 的示例.
确认一个软件包已经安装,但不去升级它:
$ ansible webservers -m yum -a "name=acme state=present"
确认一个软件包的安装版本:
$ ansible webservers -m yum -a "name=acme-1.5 state=present"
确认一个软件包还没有安装:
$ ansible webservers -m yum -a "name=acme state=absent"
对于不同平台的软件包管理工具,Ansible都有对应的模块.如果没有,你也可以使用 command 模块去安装软件. 或者最好是来为那个软件包管理工具贡献一个相应的模块.请在 mailing list 中查看相关的信息和详情.
Users and Groups
使用 ‘user’ 模块可以方便的创建账户,删除账户,或是管理现有的账户:
$ ansible all -m user -a "name=foo password=<crypted password here>"
$ ansible all -m user -a "name=foo state=absent"
更多可用的选项请参考 模块相关 ,包括对组和组成员关系的操作.
Deploying From Source Control
直接使用 git 部署 webapp:
$ ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"
因为Ansible 模块可通知到 change handlers ,所以当源码被更新时,我们可以告知 Ansible 这个信息,并执行指定的任务, 比如直接通过 git 部署 Perl/Python/PHP/Ruby, 部署完成后重启 apache.
Managing Services
确认某个服务在所有的webservers上都已经启动:
$ ansible webservers -m service -a "name=httpd state=started"
或是在所有的webservers上重启某个服务(译者注:可能是确认已重启的状态?):
$ ansible webservers -m service -a "name=httpd state=restarted"
确认某个服务已经停止:
$ ansible webservers -m service -a "name=httpd state=stopped"
Time Limited Background Operations
需要长时间运行的命令可以放到后台去,在命令开始运行后我们也可以检查运行的状态.如果运行命令后,不想获取返回的信息, 可执行如下命令:
$ ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"
如果你确定要在命令运行后检查运行的状态,可以使用 async_status 模块.前面执行后台命令后会返回一个 job id, 将这个 id 传给 async_status 模块:
$ ansible web1.example.com -m async_status -a "jid=488359678239.2844"
获取状态的命令如下:
$ ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
其中 -B 1800
表示最多运行30分钟, -P 60
表示每隔60秒获取一次状态信息.
Polling 获取状态信息的操作会在后台工作任务启动之后开始.若你希望所有的工作任务快速启动, --forks
这个选项的值 要设置得足够大,这是前面讲过的并发进程的个数.在运行指定的时间(由``-B``选项所指定)后,远程节点上的任务进程便会被终止.
一般你只能在把需要长时间运行的命令或是软件升级这样的任务放到后台去执行.对于 copy 模块来说,即使按照前面的示例想放到 后台执行文件传输,实际上并不会如你所愿.
Gathering Facts
在 playbooks 中有对于 Facts 做描述,它代表的是一个系统中已发现的变量.These can be used to implement conditional execution of tasks but also just to get ad-hoc information about your system. 可通过如下方式查看所有的 facts:
$ ansible all -m setup
我们也可以对这个命令的输出做过滤,只输出特定的一些 facts,详情请参考 “setup” 模块的文档.
Playbook 语言的示例
Playbooks 的格式是YAML(详见:YAML 语法),语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本,但它也并不是一个配置模型或过程的模型.
playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.
在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用,这在前面章节学习过.
‘plays’ 好似音符,playbook 好似由 ‘plays’ 构成的曲谱,通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 database server 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.
“plays” 算是一个体育方面的类比,你可以通过多个 plays 告诉你的系统做不同的事情,不仅是定义一种特定的状态或模型.你可以在不同时间运行不同的 plays.
对初学者,这里有一个 playbook,其中仅包含一个 play:
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
如果 action 行看起来太长,你可以使用 space(空格) 或者 indent(缩进) 隔开连续的一行:
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
在 action 行中可以使用变量.假设在 ‘vars’ 那里定义了一个变量 ‘vhost’ ,可以这样使用它:
tasks:
- name: create a virtual host file for {{ vhost }}
template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}
Handlers: 在发生改变时执行的操作
上面我们曾提到过,module 具有”幂等”性,所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的. playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动.
(当发生改动时)’notify’ actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, ‘notify’ actions 只会被触发一次.
举例来说,比如多个 resources 指出因为一个配置文件被改动,所以 apache 需要重新启动,但是重新启动的操作只会被执行一次.
这里有一个例子,当一个文件的内容被改动时,重启两个 services:
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
‘notify’ 下列出的即是 handlers.
Handlers 也是一些 task 的列表,通过名字来引用,它们和一般的 task 并没有什么区别.Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行.不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次.
这里是一个 handlers 的示例:
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了.
Ansible之roles介绍
本节内容:
- 什么场景下会用roles?
- roles示例
一、什么场景下会用roles?
假如我们现在有3个被管理主机,第一个要配置成httpd,第二个要配置成php服务器,第三个要配置成MySQL服务器。我们如何来定义playbook?
第一个play用到第一个主机上,用来构建httpd,第二个play用到第二个主机上,用来构建php,第三个play用到第三个主机上,用来构建MySQL。这些个play定义在playbook中比较麻烦,将来也不利于模块化调用,不利于多次调。比如说后来又加进来一个主机,这个第4个主机既是httpd服务器,又是php服务器,我们只能写第4个play,上面写上安装httpd和php。这样playbook中的代码就重复了。
为了避免代码重复,roles能够实现代码重复被调用。定义一个角色叫websrvs,第二个角色叫phpappsrvs,第三个角色叫dbsrvs。那么调用时如下来调用:
hosts: host1 role: - websrvs hosts: host2 role: - phpappsrvs hosts: host3 role: - dbsrvs hosts: host4 role: - websrvs - phpappsrvs
这样代码就可以重复利用了,每个角色可以被独立重复调用。下面举例说明使用方式。
二、roles示例
假设有3台主机,172.16.7.151主机上安装MySQL,172.16.7.152上安装httpd,172.16.7.153上安装MySQL和httpd。我们建立两个角色websrvs和dbsrvs,然后应用到这几个主机上。
1. 创建roles的必需目录
[root@node1 opt]# mkdir -pv ansible_playbooks/roles/{websrvs,dbsrvs}/{tasks,files,templates,meta,handlers,vars}
每个role下面有个目录叫meta,在里面可以新建文件main.yml,在文件中可以设置该role和其它role之前的关联关系。
2. 配置角色
(1)配置角色websrvs
[root@node1 opt]# cd ansible_playbooks/roles/ [root@node1 roles]# cd websrvs/ [root@node1 websrvs]# ls files handlers meta tasks templates vars
a. 将httpd配置文件上传到files目录下,我这里假设httpd.conf每台主机都是一样的,实际上应该用模板,先用一样的配置文件举例
[root@node1 websrvs]# cp /etc/httpd/conf/httpd.conf files/
直接复制的静态文件都放在files目录下。打算用模板文件的都放在templates目录下。
b.编写任务列表tasks
[root@node1 websrvs]# vim tasks/main.yml - name: install httpd package yum: name=httpd - name: install configuration file copy: src=httpd.conf dest=/etc/httpd/conf tags: - conf notify: - restart httpd - name: start httpd service: name=httpd state=started
c.由于上面的tasks中定义了notify,所以要定义handlers
[root@node1 websrvs]# vim handlers/main.yml - name: restart httpd service: name=httpd state=restarted
如果需要定义变量,则在vars目录下创建main.yml文件,在文件中写入变量,以key:value的形式定义,比如:
http_port: 8080
(2)配置角色dbsrvs
[root@node1 roles]# cd dbsrvs/ [root@node1 dbsrvs]# ls files handlers meta tasks templates vars
a.将MySQL配置文件上传到files目录下。
b.编写任务列表tasks
[root@node1 dbsrvs]# vim tasks/main.yml - name: install mysql-server package yum: name=mysql-server state=latest - name: install configuration file copy: src=my.cnf dest/etc/my.cnf tags: - conf notify: - restart mysqld - name: service: name=mysqld enabled=true state=started
c.定义handlers
[root@node1 dbsrvs]# vim handlers/main.yml - name: restart mysqld service: name=mysqld state=restarted
(3)定义playbook
【注意】:要在roles目录同级创建playbook。
[root@node1 ansible_playbooks]# vim web.yml - hosts: 172.16.7.152 roles: - websrvs [root@node1 ansible_playbooks]# vim db.yml - hosts: 172.16.7.151 roles: - dbsrvs [root@node1 ansible_playbooks]# vim site.yml - hosts: 172.16.7.153 roles: - websrvs - dbsrvs
运行:
[root@node1 ansible_playbooks]# ansible-playbook web.yml [root@node1 ansible_playbooks]# ansible-playbook db.yml [root@node1 ansible_playbooks]# ansible-playbook site.yml
当然也可以把这些内容写入同一个playbook中。playbook的名字可以自定义。