Ansible第二篇:ansible-playbook
一、Playbook语法
Ansible-playbook采用YAML语法编写。
示例:
[root@LOCALHOST ~]# cat yaml/httpd.yaml
---
- hosts: control-node # 将要执行任务的主机,已经在hosts文件中定义好了,可是单个主机或主机组remote_user: root # 在目标主机上执行任务时的用户身份vars:- pkg: httpdtasks:- name: "install httpd package."yum: name={{ pkg }} state=installed- name: "copy httpd configure file to remote host."copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.confnotify: restart httpd # 当这个任务执行状态发生改变时,触发handlers执行.- name: "boot httpd service."service: name=httpd state=startedhandlers: # handlers与tasks是同一级别- name: restart httpdservice: name=httpd state=restarted
连续的项目(即列表)用 -
减号来表示,key/value(字典)用冒号:
分隔。
playbook语法有如下特性:
- 以
---
(三个减号)开始,必须顶行写;- 次行开始写Playbook的内容,但是一般要求写明该playbook的功能;
- 严格缩进,并且不能用Tab键缩进;
- 缩进级别必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的;
- K/V的值可同行写,也可换行写。同行使用
:
分隔,换行写需要以-
分隔;
执行playbook:
[root@LOCALHOST ~]# ansible-playbook yaml/httpd.yaml PLAY [control-node] ********************************************************************************************************TASK [Gathering Facts] *****************************************************************************************************
ok: [openstack-control2]
ok: [openstack-control1]TASK [install httpd package.] **********************************************************************************************
changed: [openstack-control2]
changed: [openstack-control1]TASK [copy httpd configure file to remote host.] ***************************************************************************
changed: [openstack-control1]
changed: [openstack-control2]TASK [boot httpd service.] *************************************************************************************************
changed: [openstack-control2]
changed: [openstack-control1]PLAY RECAP *****************************************************************************************************************
openstack-control1 : ok=4 changed=3 unreachable=0 failed=0
openstack-control2 : ok=4 changed=3 unreachable=0 failed=0
二、Playbook中的变量
2.1 yaml文件中定义变量
[root@LOCALHOST ~]# cat yaml/vars.yaml
---
- hosts: compute-noderemote_user: rootvars:pkg: httpd # 定义变量tasks:- name: install httpd serviceyum: name={{ pkg }} state=installed # 引用变量
playbook中用
vars
关键字声明变量,变量定义变量名: 变量值
变量引用 :{{ 变量名 }}
2.2 引用外部变量
在命令行使用--extra-vars
参数赋值变量;
[root@LOCALHOST ~]# cat yaml/extra_vars.yaml
---
- hosts: control-noderemote_user: roottasks:- name: create a filefile:path: /tmp/{{ filename }} # 引用外部变量mode: 0644state: touch
命令行使用--extra_vars
传入变量:
[root@LOCALHOST ~]# ansible-playbook yaml/extra_vars.yaml --extra-vars "filename=temp.txt"
--extra_vars "变量名=变量值"
2.3 资产清单(inventory)中定义的变量
也就是在/etc/ansible/hosts
文件中定义的变量;
[root@LOCALHOST ~]# cat /etc/ansible/hosts
[load-node]
openstack-load1
openstack-load2[compute-node]
openstack-compute1 ansible_ssh_host=10.0.1.10 ansible_ssh_port=2002 ansible_ssh_user=stanley ansible_ssh_pass=etyfhzmweadf
openstack-compute2[control-node]
openstack-control1 filename=control1.txt # 主机变量
openstack-control2 filename=control2.txt[openstack:children]
load-node
compute-node
control-node[openstack:vars]
issue="Hello, World" # 组变量
注意:组变量定义时,不要落下关键字
vars
,[组名:vars]
。
在playbook中引用{{ 变量名 }}
即可。
ansible内置了一些固定的主机变量名,在inventory中定义其值,如下:
ansible_ssh_host将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.ansible_ssh_portssh端口号.如果不是默认的端口号,通过此变量设置.ansible_ssh_user默认的 ssh 用户名ansible_ssh_passssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)ansible_sudo_passsudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)ansible_sudo_exe (new in version 1.8)sudo 命令路径(适用于1.8及以上版本)ansible_connection与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.ansible_ssh_private_key_filessh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.ansible_shell_type目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.ansible_python_interpreter目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
参考Ansible中文权威指南。
2.4 直接使用facts变量
使用命令ansible all -m setup
获取到的主机信息,其中的KEY都可以被当作变量引用:
[root@LOCALHOST ~]# cat yaml/facts_vars.yaml
---
- hosts: compute-noderemote_user: roottasks:- name: write fqdn into fqdn.logshell: "echo {{ ansible_fqdn }} {{ ansible_eth1.ipv4.address }} > /tmp/fqdn.log"
上述代码中
{{ ansible_fqdn }}
就是直接引用的facts变量;
{{ ansible_eth1.ipv4.address }}
引用的值就相当于下面这样。
{ "ansible_eth1": {"ipv4": {"address":10.0.1.10,},},
}
最终{{ ansible_eth1.ipv4.address }}=10.0.1.10
2.5 注册变量
在playbook中用register
关键字定义一个变量,这个变量的值就是当前任务执行的输出结果;
[root@LOCALHOST ~]# cat yaml/reg_vars.yaml
---
- hosts: load-noderemote_user: roottasks:- name: show dateshell: "/bin/date"register: date # 注册一个变量- name: Record time logshell: "echo {{ date.stdout }} > /tmp/date.log"
引用注册变量要用
{{ date.stdout }}
表示标准输出。[root@openstack-load1 ~]# cat /tmp/date.log 2018年 03月 29日 星期四 15:52:01 CST
如果直接{{ date }}
这样引用,则文件中写入的是如下内容:
{stderr_lines: [], uchanged: True, uend: u2018-03-29 15:49:52.609894, failed: False, ustdout: u2018\u5e74 03\u6708 29\u65e5 \u661f\u671f\u56db 15:49:52 CST, ucmd: u/bin/date, urc: 0, ustart: u2018-03-29 15:49:52.602918, ustderr: u, udelta: u0:00:00.006976, stdout_lines: [u2018\u5e74 03\u6708 29\u65e5 \u661f\u671f\u56db 15:49:52 CST]}
2.6 变量优先级
上述这些变量定义的方法,它们的优先级如下:
- 在命令行中定义的变量(即用
-e
或--extra-vars
定义的变量); - 在Inventory中定义的连接变量(比如:ansible_ssh_user);
- 大多数的其他变量(命令行转换、play中的变量、included的变量、role中的变量等);
- 在Inventory中定义的其他变量;
- Facts变量;
- “Role”默认变量,这个是默认的值,很容易丧失优先权。
三、Playbook中的方法
3.1 handlers
在需要被监控的任务(tasks)中定义一个notify,只有当这个任务被执行时,才会触发notify对应的handlers去执行相应操作。
[root@LOCALHOST ~]# cat yaml/httpd.yaml
---
- hosts: control-noderemote_user: rootvars:- pkg: httpdtasks:- name: "install httpd package."yum: name={{ pkg }} state=installed- name: "copy httpd configure file to remote host."copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.confnotify: restart httpd- name: "boot httpd service."service: name=httpd state=startedhandlers:- name: restart httpdservice: name=httpd state=restarted
在使用handlers的过程中,有以下几点需要注意:
- handlers只有在其所在的任务被执行时,都会被运行;
- handlers只会在Play的末尾运行一次;如果想在一个Playbook的中间运行handlers,则需要使用meta模块来实现,例如:
- meta: flush_handlers
。- 如果一个Play在运行到调用handlers的语句之前失败了,那么这个handlers将不会被执行。我们可以使用mega模块的
--force-handlers
选项来强制执行handlers,即使在handlers所在Play中途运行失败也能执行。
3.2 tags
tags用于让用户选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断。
ansible的标签(Tags)功能可以给角色(Roles)、文件、单独的任务,甚至整个Playbook打上标签,然后利用这些标签来指定要运行Playbook中的个别任务,或不执行指定的任务。
[root@LOCALHOST ~]# cat yaml/httpd.yaml
---
- hosts: control-noderemote_user: rootvars:- pkg: httpdtasks:- name: "install httpd package."yum: name={{ pkg }} state=installed- name: "copy httpd configure file to remote host."copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.confnotify: restart httpd- name: "start httpd service."tags:- start_httpd # 给“start httpd service”这个任务打个标签service: name=httpd state=startedhandlers:- name: restart httpdservice: name=httpd state=restarted
在命令行中调用:
[root@LOCALHOST ~]# ansible-playbook yaml/httpd.yaml --tags start_httpdPLAY [control-node] ********************************************************************************************************TASK [Gathering Facts] *****************************************************************************************************
ok: [openstack-control1]
ok: [openstack-control2]TASK [start httpd service.] ************************************************************************************************
ok: [openstack-control1]
ok: [openstack-control2]PLAY RECAP *****************************************************************************************************************
openstack-control1 : ok=2 changed=0 unreachable=0 failed=0
openstack-control2 : ok=2 changed=0 unreachable=0 failed=0
四、Playbook的流程控制
4.1 when 条件判断
当关键字when
后面的条件满足时(也就是通过运算得到的结果为true时),才会执行当前任务。
示例如下(yaml/when.yaml):
---
- hosts: load-node,imgremote_user: roottasks:- name: "touch flag file"command: "touch /tmp/this_is_{{ ansible_distribution }}_system" when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == '6') or(ansible_distribution == "Debian" and ansible_distribution_major_version == '7')
上述代码中,
ansible_distribution
和ansible_distribution_major_version
都是是Facts变量,分别表示Linux发行版和版本号
执行结果如下图:
4.2 循环语句
Playbook中的循环类型,如下表:
循环类型 | 关键字 |
---|---|
标准循环 | with_items |
遍历字典 | with_dict |
遍历目录文件 | with_fileglob |
遍历文件列表的内容 | with_file |
嵌套循环 | with_nested |
并行遍历列表 | with_together |
遍历列表和索引 | with_indexed_items |
重试循环 | until |
查找第一个匹配文件 | with_first_found |
随机选择 | with_random_choice |
在序列中循环 | with_sequence |
注意:列表中前三个为常用的循环语句。
4.2.1 标准循环 with_items
示例1(with_items_1.yaml):
---
- name: when and with_itemshosts: load-noderemote_user: rootgather_facts: false tasks:- name: Create thress groupsgroup: name=testgroup6 state=presentignore_errors: yesregister: excu_result- name: Append excu_result to tmp.txtshell: "echo {{ excu_result }} > /tmp/tmp.txt"- name: Create some usersuser: name={{ item }} group=testgroup6 state=presentwhen: excu_result|successwith_items:- testuser1- testuser2- testuser3
释义:
gather_facts: false
表示运行此playbook时不收集目标主机的系统信息。因为默认此项是开启的,每次运行playbook都会收集主机facts,这会影响playbook的运行速度。将gather_facts
设为false
即可关闭。
when:excu_result|success
的意思为当变量excu_result执行结果为成功状态,则执行当前的任务。其中success为Ansible内部过滤器方法,返回True代表命令运行成功。还有excu_result|failed
表示excu_result执行结果为失败状态;excu_result|skipped
表示excu_result执行被跳过。
with_items
的值还可以写成[testuser1, testuser2, testuser3]
示例2:
添加多个用户,并将用户加入不同的组内:
- name: add several usersuser: name={{ item.name }} state=present groups={{ item.groups }}with_items:- { name: 'testuser1', groups: 'wheel' }- { name: 'testuser2', groups: 'root' }
4.2.2 遍历字典 with_dict
输出用户的姓名和电话:
---
- hosts: load-noderemote_user: roottasks:- name: print phone recordsdebug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.phone }})"with_dict: {'alice':{'name':'Alice Appleworth', 'phone':'13243252136'}, 'bob':{'name':'Bob Banarama', 'phone': '18766761211'}}
注意:Playbook中对字典的循环,与python中对字典循环类似,取值方法也一样。
4.2.3 遍历目录文件 with_fileglob
遍历/root/sh/
目录下的所有文件,并将其拷贝至目标主机。
[root@LOCALHOST ~]# cat yaml/with_fileglob.yaml
---
- hosts: DH-TESTremote_user: rootgather_facts: falsetasks:- name: create a directoryfile: path=/root/script state=directoryignore_errors: yesregister: result- name: copy some scriptscopy: src={{ item }} dest=/root/script owner=root mode=600when: result|successwith_fileglob:- /root/sh/*
注意:with_fileglob匹配单个目录中的所有文件,非递归匹配模式。
作者: Jeson老师
链接:http://www.imooc.com/article/22753
执行结果如下图:
4.2.4 其它循环
其它循环请参考 Jeson老师的手记
五、Playbook任务计时插件
Github地址: https://github.com/jlafon/ansible-profile
安装这个插件后会显示 ansible-playbook 执行每一个任务所花费的时间。
这个插件安装很简单,只需要简单的三个命令即可完成安装。在你的 playbook 文件的目录下创建一个目录,目录名 callback_plugins 然后将下载的 profile_tasks.py 文件放到该目录下即可。
# mkdir callback_plugins
# cd callback_plugins
# wget https://raw.githubusercontent.com/jlafon/ansible-profile/master/callback_plugins/profile_tasks.py
六、Playbook异常处理
6.1 ignore_errors
在有些情况下,一些必须运行的命令或脚本会报一些错误,而这些错误并不一定真的说明有问题,但是经常会给接下来要运行的任务造成困扰,甚至直接导致playbook运行中断。
这时候,我们可以在相关任务中添加ignore_errors: true
来屏蔽当前任务的报错信息。ansible也将视该任务运行成功,不再报错,这样就不会对接下来要运行的任务造成额外困扰。但是要注意的是,我们不应过度依赖ignore_errors
,因为它会隐藏所有的报错信息,而应该把精力集中在寻找报错的原因上面,这样才能从根本上解决问题。
例如:
[root@LOCALHOST ~]# cat yaml/httpd.yaml
---
- hosts: load-noderemote_user: rootvars:- pkg: httpdtasks:- name: "install httpd package."yum: name={{ pkg }} state=installed- name: "copy httpd configure file to remote host."copy: src=/root/config/httpd.conf dest=/etc/httpd/conf/httpd.confnotify: restart httpdignore_errors: true # 忽略错误- name: "start httpd service."tags:- start_httpdservice: name=httpd state=startedhandlers:- name: restart httpdservice: name=httpd state=restarted
上述代码中,任务
"copy httpd configure file to remote host."
中的src是一个不存在的路径,所以此任务运行一定会出错。这个playbook运行结果如下图:
从运行结果图中可以看到有两个
...ignoring
,表示忽略了这些错误,并继续执行下面的任务。
6.2 failed_when
当满足一定的条件时,主动抛出错误。
[root@LOCALHOST ~]# cat yaml/failed_when.yaml
---
- hosts: DH-TESTremote_user: rootgather_facts: falsetasks:- name: get processshell: ps aux | wc -l register: process_countfailed_when: process_count > 3- name: touch a filefile: path=/tmp/test3.txt state=touch owner=root mode=0700
failed_when: process_count > 3
当进程数大于3时主动抛出错误,后续任务就不会执行了。如果不满足条件,则不会抛出错误。
6.3 changed_when
[root@LOCALHOST ~]# cat yaml/changed_when.yaml
---
- hosts: DH-TESTremote_user: rootgather_facts: falsetasks:- name: touch a filefile: path=/tmp/changed_test state=touch
上述Playbook执行结果如下图:
如果想要关闭状态改变的提示,则可以添加changed_when: false
,如下:
[root@LOCALHOST ~]# cat yaml/changed_when.yaml
---
- hosts: DH-TESTremote_user: rootgather_facts: falsetasks:- name: touch a filefile: path=/tmp/changed_testi2 state=touchchanged_when: false # 关闭状态改变提示
执行结果如下图:
七、Roles
Roles是一种利用在大型Playbook中的剧本配置模式,它有着自己特定的结构。用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
剧本roles设计思路:将公共任务、资源、变量等对象尽可能独立。
一个roles的案例如下所示:
site.yml # 主入口文件
webservers.yml # webserver类型服务所用的剧本
dbservers.yml # 数据库类型的服务所用的剧本
files/ # 存放通用的将要被上传的文件
templates/ # 存放通用的模板文件
roles/ # roles目录名称是固定的common/ # 此目录下的各个组件是所有角色共用的tasks/ # 存放通用的任务文件handlers/ # 存放通用的处理器文件vars/ # 存放通用的变量文件 meta/ # 存放通用的角色依赖文件webservers/ # 存放webserver类型的服务的各个组件 files/ # 存放webserver角色需要的上传文件templates/ # 存放webserver角色需要的模板文件tasks/handlers/vars/meta/
而在playbook中,可以这样使用roles:
---
- hosts: webserversroles:- common- webservers
也可以向roles传递参数,例如:
---
- hosts: webserversroles:- common- { role: foo_app_instance, dir: '/opt/a', port: 5000 }- { role: foo_app_instance, dir: '/opt/b', port: 5001 }
甚至也可以条件式地使用roles,例如:
---- hosts: webserversroles:- { role: some_role, when: "ansible_os_family == 'RedHat'"
7.1 创建role的步骤
(1) 创建以roles命名的目录;
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等;
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建;
(4) 在roles目录的同级目录下创建一个yaml文件,如:site.yml ,在此文件中调用各角色;
7.2 role内各目录中可用的文件
tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;此文件可以使用include包含其它的位于此目录中的task文件;
files目录:存放由copy或script等模块调用的文件;
templates目录:template模块会自动在此目录中寻找Jinja2模板文件;
handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;在handler中使用include包含的其它的handler文件也应该位于此目录中;
vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量;
meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持;
default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件;
7.3 简单部署LAMP的Roles案例
先看一下这个roles的目录结构:
[root@LOCALHOST ansible-examples-master]# tree [root@LOCALHOST ansible-examples-master]# tree lamp_simple
lamp_simple
├── group_vars
│ ├── all
│ └── dbservers
├── hosts
├── LICENSE.md
├── README.md
├── roles
│ ├── common
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── ntp.conf.j2
│ ├── db
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── my.cnf.j2
│ └── web
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── copy_code.yml
│ │ ├── install_httpd.yml
│ │ └── main.yml
│ └── templates
│ └── index.php.j2
└── site.yml14 directories, 17 files
查看各个playbook的内容:
- 查看主机清单文件
# cat lamp_simple/hosts
[webservers]
web3[dbservers]
web2
- 查看主入口文件
# cat lamp_simeple/site.yml
---
# This playbook deploys the whole application stack in this site.- name: apply common configuration to all nodeshosts: allremote_user: rootroles:- common- name: configure and deploy the webservers and application codehosts: webserversremote_user: rootroles:- web- name: deploy MySQL and configure the databaseshosts: dbserversremote_user: rootroles:- db
- 查看变量文件:
# cat lamp_simple/group_vars/all
---
# Variables listed here are applicable to all host groupshttpd_port: 80
ntpserver: 192.168.1.2
repository: https://github.com/bennojoy/mywebapp.git
# cat lamp_simple/group_vars/dbservers
---
# The variables file used by the playbooks in the dbservers group.
# These don't have to be explicitly imported by vars_files: they are autopopulated.mysqlservice: mysqld
mysql_port: 3306
dbuser: foouser
dbname: foodb
upassword: abc
- 查看通用hanlder文件:
# cat lamp_simple/roles/common/handlers/main.yml
---
# Handler to handle common notifications. Handlers are called by other plays.
# See http://docs.ansible.com/playbooks_intro.html for more information about handlers.- name: restart ntpservice: name=ntpd state=restarted- name: restart iptablesservice: name=iptables state=restarted
- 查看通用tasks文件:
# cat lamp_simple/roles/common/tasks/main.yml
---
# This playbook contains common plays that will be run on all nodes.- name: Install ntpyum: name=ntp state=presenttags: ntp- name: Configure ntp filetemplate: src=ntp.conf.j2 dest=/etc/ntp.conftags: ntpnotify: restart ntp- name: Start the ntp serviceservice: name=ntpd state=started enabled=yestags: ntp- name: test to see if selinux is runningcommand: getenforceregister: sestatuschanged_when: false
- 查看通用模板文件:
# cat lamp_simple/roles/common/templates/ntp.conf.j2
driftfile /var/lib/ntp/driftrestrict 127.0.0.1
restrict -6 ::1server {{ ntpserver }}includefile /etc/ntp/crypto/pwkeys /etc/ntp/keys
- 查看db角色的handlers文件:
# cat lamp_simple/roles/db/handlers/main.yml
---
# Handler to handle DB tier notifications- name: restart mysqlservice: name=mysqld state=restarted- name: restart iptablesservice: name=iptables state=restarted[root@LOCALHOST ansible-examples-master]# cat lamp_simple/roles/db/handlers/main.yml
---
# Handler to handle DB tier notifications- name: restart mysqlservice: name=mysqld state=restarted- name: restart iptablesservice: name=iptables state=restarted
- 查看db角色的tasks文件:
# cat lamp_simple/roles/db/tasks/main.yml
---
# This playbook will install mysql and create db user and give permissions.- name: Install Mysql packageyum: name={{ item }} state=installedwith_items:- mysql-server- MySQL-python- libselinux-python- libsemanage-python- name: Configure SELinux to start mysql on any portseboolean: name=mysql_connect_any state=true persistent=yeswhen: sestatus.rc != 0- name: Create Mysql configuration filetemplate: src=my.cnf.j2 dest=/etc/my.cnfnotify:- restart mysql- name: Start Mysql Serviceservice: name=mysqld state=started enabled=yes- name: insert iptables rulelineinfile: dest=/etc/sysconfig/iptables state=present regexp="{{ mysql_port }}"insertafter="^:OUTPUT " line="-A INPUT -p tcp --dport {{ mysql_port }} -j ACCEPT"notify: restart iptables- name: Create Application Databasemysql_db: name={{ dbname }} state=present- name: Create Application DB Usermysql_user: name={{ dbuser }} password={{ upassword }} priv=*.*:ALL host='%' state=present
- 查看db角色的模板文件:
# cat lamp_simple/roles/db/templates/my.cnf.j2
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
port={{ mysql_port }}[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
- 查看web角色的handlers文件:
# cat lamp_simple/roles/web/handlers/main.yml
---
# Handler for the webtier: handlers are called by other plays.
# See http://docs.ansible.com/playbooks_intro.html for more information about handlers.- name: restart iptablesservice: name=iptables state=restarted
- 查看web角色的tasks文件:
# cat lamp_simple/roles/web/tasks/main.yml
---
- include: install_httpd.yml
- include: copy_code.yml
# cat lamp_simple/roles/web/tasks/install_httpd.yml
---
# These tasks install http and the php modules.- name: Install http and php etcyum: name={{ item }} state=presentwith_items:- httpd- php- php-mysql- git- libsemanage-python- libselinux-python- name: insert iptables rule for httpdlineinfile: dest=/etc/sysconfig/iptables create=yes state=present regexp="{{ httpd_port }}" insertafter="^:OUTPUT "line="-A INPUT -p tcp --dport {{ httpd_port }} -j ACCEPT"notify: restart iptables- name: http service stateservice: name=httpd state=started enabled=yes- name: Configure SELinux to allow httpd to connect to remote databaseseboolean: name=httpd_can_network_connect_db state=true persistent=yeswhen: sestatus.rc != 0`
# cat lamp_simple/roles/web/tasks/copy_code.yml
---
# These tasks are responsible for copying the latest dev/production code from
# the version control system.- name: Copy the code from repositorygit: repo={{ repository }} dest=/var/www/html/- name: Creates the index.php filetemplate: src=index.php.j2 dest=/var/www/html/index.php
查看web角色的模板文件:
# cat lamp_simple/roles/web/templates/index.php.j2
<html><head><title>Ansible Application</title></head><body></br><a href=http://{{ ansible_default_ipv4.address }}/index.html>Homepage</a></br>
<?php Print "Hello, World! I am a web server configured using Ansible and I am : ";echo exec('hostname');Print "</BR>";
echo "List of Databases: </BR>";{% for host in groups['dbservers'] %}$link = mysqli_connect('{{ hostvars[host].ansible_default_ipv4.address }}', '{{ hostvars[host].dbuser }}', '{{ hostvars[host].upassword }}') or die(mysqli_connect_error($link));{% endfor %}$res = mysqli_query($link, "SHOW DATABASES;");while ($row = mysqli_fetch_assoc($res)) {echo $row['Database'] . "\n";}
?>
</body>
</html>
执行这个roles
# ansile-playbook -i lamp_simple/hosts lamp_simple/site.yml
八、Ansible Galaxy
Ansible Galaxy是Ansible官方Roles分享平台(galaxy.ansible.com),在Galaxy平台上所有人可以免费上传或下载Roles,在这里好的技巧、思想、架构得以积累和传播。
8.1 ansible-galaxy命令的用法:
[root@LOCALHOST tasks]# ansible-galaxy --help
Usage: ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...Options:-h, --help show this help message and exit-c, --ignore-certs Ignore SSL certificate validation errors.-s API_SERVER, --server=API_SERVERThe API server destination-v, --verbose verbose mode (-vvv for more, -vvvv to enableconnection debugging)--version show program's version number and exitSee 'ansible-galaxy <command> --help' for more information on a specific command.
搜索lamp相关的roles:
命令:ansible-galaxy search lamp
结果如下图:
来安装一个搜索到的角色:
命令:ansible-galaxy install vivaserver.lamp
[root@LOCALHOST ~]# ansible-galaxy install vivaserver.lamp
- downloading role 'lamp', owned by vivaserver
- downloading role from https://github.com/vivaserver/ansible-lamp/archive/master.tar.gz
- extracting vivaserver.lamp to /root/.ansible/roles/vivaserver.lamp
- vivaserver.lamp (master) was installed successfully
根据输出提示,安装的role放在
/root/.ansible/roles/vivaserver.lamp
查看这个role目录结构:
[root@LOCALHOST vivaserver.lamp]# tree /root/.ansible/roles/vivaserver.lamp/
/root/.ansible/roles/vivaserver.lamp/
├── files
│ ├── favicon.ico
│ └── www.html
├── LICENSE
├── meta
│ └── main.yml
├── README.md
├── screenshot.png
└── tasks└── main.yml3 directories, 7 files
按作者搜索roles:
[root@LOCALHOST ~]# ansible-galaxy search zabbix --author dj-wasabiFound 5 roles matching your search:Name Description---- -----------dj-wasabi.zabbix-javagateway Installing and maintaining zabbix-javagateway for RedHat/Debian/Ubuntu.dj-wasabi.zabbix-server Installing and maintaining zabbix-server for RedHat/Debian/Ubuntu.dj-wasabi.zabbix-web Installing and maintaining zabbix-web for RedHat/Debian/Ubuntu.dj-wasabi.zabbix-proxy Installing and maintaining zabbix-proxy for RedHat/Debian/Ubuntu.dj-wasabi.zabbix-agent Installing and maintaining zabbix-agent for RedHat/Debian/Ubuntu.
上述命令中
dj-wasabi
是作者的用户名
8.2 批量安装多个roles
# cat roles.txt
user1.role1,v1.0.0
user2.role2,v0.5
user2.role3
安装:
# ansible-galaxy install -r roles.txt
Ansible第二篇:ansible-playbook相关推荐
- 接上一篇Ansible和celery的结合,在celery的tasks.py文件里为了实现并发不阻塞的需求,用到了多进程
接上一篇Ansible和celery的结合,在celery的tasks.py文件里为了实现并发不阻塞的需求,用到了多进程 举例如下:tasks.py文件如下: import signal from m ...
- Ansible系列-基础篇-Ansible Inventory的合理化配置
欢迎关注个人公众号 DailyJobOps 原文地址:Ansible系列-基础篇-Ansible Inventory的合理化配置 这里写目录标题 Ansible Inventory内置参数 Inven ...
- Ansible 学习总结(3)—— Ansible 常用模块与 playbook 实例讲解
一.Ansible 安装 下载安装并解压 python 3.7 包 安装 wget yum -y install wget 下载 python 文件 wget https://www.python.o ...
- Ansible第一篇:基础
一.配置文件 ansible.cfg /etc/ansible/ansible.cfg 是ansible安装好后的默认配置文件,但是配置文件可以存在于多个地方,ansible读取配置文件的顺序依次是: ...
- Jenkins + Ansible + Gitlab之ansible篇
Ansible介绍 什么是Ansible? Ansible是一个开源部署工具 开发语言:Python 特点:SSH协议通信,全平台,无需要编译,模块化部署管理 作用:推送Playbook进行远程节点快 ...
- 自动化运维工具ansible学习+使用ansible批量推送公钥到远程主机
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 目录: 一.ansible简介 1.1.ansible是什么 1.2.ansible如何工作 ...
- 自动化运维工具ansible学习+使用ansible批量推送公钥到远程主机[学习马哥]
目录: 一.ansible简介 1.1.ansible是什么 1.2.ansible如何工作 1.3.ansible优缺点 1.4.ansible安装方式 1.5.ansible文件简单介绍 1.6. ...
- Django框架之第二篇
Django框架之第二篇 一.知识点回顾 1.MTV模型 model:模型,和数据库相关的 template:模板,存放html文件,模板语法(目的是将变量如何巧妙的嵌入到HTML页面中). view ...
- java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...
23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...
最新文章
- android h5弹窗,Android嵌套html5页面中alert 弹出框问题
- 两台SQL Server数据同步解决方案
- 利用TLD2131组成LED矩阵显示实验电路板
- 由于Eclipse版本不符造成的异常
- java中处理字符编码(网页与数据库)(转)
- Python socket的客户端
- node.js路由控制
- C++ 长指针与指针的区别
- 【C012】Python - 基础教程学习(三)
- 解读全球热点,传递科研进展,这份AI内参要承包你的AI信息源
- DBUtils的概述
- gstreamer的rtsp推流(笔记)
- iview关闭抽屉弹层时清空Select弹框高亮样式
- 你还在 Docker 中跑 MySQL?恭喜你,好下岗了!
- 关于『区位码』、『国标码』、『机内码』的转换问题
- [QT] QT加载百度离线地图(二)
- Filesystem Hierachy Standar 学习
- 对嵌入式开发方向的一些思考:在物联网方向
- 风生水起的VR直播丨VR直播市场何时迎来爆发期?
- 手机/网络风暴——诺基亚、谷歌、苹果交锋在即