一、执行文件
Playbook配置文件使用YAML语法,具有简
洁明了,结构清晰等特点。Playbook配置文件类似于shell脚本,是一个YAML格式的文件,用于保存针对特定需求的任务列表,前面介绍的ansible命令虽然可以完成各种任务,但是当配置一系列任务时,逐条输入命令就显得效率非常低下,更有效的方式在playbook配置中配置所有的任务代码,利用ansible-playbook命令执行该文件,可以实现自动化运维,YAML文件的扩展名通常为.yaml或.yml。
YAML语法和其他高级语言类似,其结构通过缩进来展示,通过“-“来表达选项,通过冒号“:”来分隔键和值。整个文件以“---”开始并以“…”结束,如下所示
修改hosts文件
[root@ansible ~]# vim /etc/ansible/hosts[test01]
192.168.2.222[test02]
192.168.2.223[root@ansible ~]# vim /etc/ansible/test1.yml #创建test,yml文件--- #开头格式(可忽略)
- hosts: test01 #表示对test01(192.168.200.112)的操作remote_user: root #远端执行用户身份roottasks: #任务列表- name: adduser #任务名称user: name=user2 state=present #执行user模块创建用户tags: #创建tag标签- testa #tag标签为testa- name: addgroup #任务名称group: name=tests system=yes #执行group模块创建一个组账号tags: #创建tag标签- testb #tag标签为testb
- hosts: test02 #表示对test02(192.168.200.113)的操作remote_user: root #远端执行用户身份roottasks: #任务列表- name: cf #任务名称copy: src=/etc/passwd dest=/home #执行copy模块复制文件tags: #创建tag标签- testc #tag标签为testsc
... #结尾格式(可忽略)
所有的“-”和“:”后面均有空格,而且要注意缩进和对齐
Playbook的核心元素包含:
- hosts:任务的目标主机,多个主机用冒号分隔,一般调用/etc/ansible/hosts中的分组信息
- remote_user:远程主机上,运行此任务的默认为root运行
- tasks:任务,即定义的具体任务,由模块定义的操作列表
- handlers:触发器,类似tasks,只是在特定的条件下才会触发任务。某任务的状态在运行后changed时,可通过“notify”通知给相应的handlers进行触发执行。
- roles:角色,将hosts剥离出去,由tasks,handlers等所组成的一种特定的结构集合。
用法
Playbook 文件定义的任务需要通过ansible-playbook命令进行调用并执行,ansible-playbook命令用法如下
用法:ansible-playbook [option] /PATH/TO/PLAYBOOK.yaml
其中[option]部分的功能包括
1.--syntax-check:检测yaml文件的语法
2.-C(--check):测试,不会改变主机的任何配置
3.--list-hosts:列出yaml文件影响的主机列表
4.--list-tasks:列出yaml文件的任务列表
5.--list-tags:列出yaml文件中的标签
6.-t TAGS(--tags=TAGS):表示只执行指定标签的任务
7.--skip-tags=SKIP_TAGSS:表示除了指定标签任务,执行其他任务
8.--start-at-task=START_AT:从指定任务开始往下运行
实验案例
1.语法检查
[root@ansible ~]# ansible-playbook --syntax-check /etc/ansible/test1.yml playbook: /etc/ansible/test1.yml #没有报错提示
2.预测试
[root@ansible ~]# ansible-playbook -C /etc/ansible/test1.yml PLAY [test01] *****************************************************************************************************TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.200.112]TASK [adduser] ****************************************************************************************************
changed: [192.168.200.112]TASK [addgroup] ***************************************************************************************************
changed: [192.168.200.112]PLAY [test02] *****************************************************************************************************TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.200.113]TASK [cf] *********************************************************************************************************
changed: [192.168.200.113]PLAY RECAP ********************************************************************************************************
192.168.200.112 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.200.113 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3.列出主机
[root@ansible ~]# ansible-playbook --list-hosts /etc/ansible/test1.yml playbook: /etc/ansible/test1.ymlplay #1 (test01): test01 TAGS: []pattern: [u'test01']hosts (1):192.168.2.222play #2 (test02): test02 TAGS: []pattern: [u'test02']hosts (1):192.168.2.223
4.列出任务
[root@ansible ~]# ansible-playbook --list-tasks /etc/ansible/test1.yml playbook: /etc/ansible/test1.ymlplay #1 (test01): test01 TAGS: []tasks:adduser TAGS: [testa]addgroup TAGS: [testb]play #2 (test02): test02 TAGS: []tasks:cf TAGS: [testc]
5.列出标签
[root@ansible ~]# ansible-playbook --list-tags /etc/ansible/test1.yml playbook: /etc/ansible/test1.ymlplay #1 (test01): test01 TAGS: []TASK TAGS: [testa, testb]play #2 (test02): test02 TAGS: []TASK TAGS: [testc]
6.进行测试
[root@ansible ~]# ansible-playbook /etc/ansible/test1.yml PLAY [test01] *****************************************************************************************************TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.200.112]TASK [adduser] ****************************************************************************************************
changed: [192.168.2.222]TASK [addgroup] ***************************************************************************************************
changed: [192.168.2.222]PLAY [test02] *****************************************************************************************************TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.2.223]TASK [cf] *********************************************************************************************************
changed: [192.168.2.223]PLAY RECAP ********************************************************************************************************
192.168.2.222 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.2.223 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
7.测试查看
[root@client1 ~]# tail -1 /etc/passwduser2:x:1002:1002::/home/user2:/bin/bash[root@client1 ~]# tail -1 /etc/grouptests:x:981:[root@client2 ~]# ls /home/
passwd Rich test
通常情况下会先执行ansible-playbook -C /PATH/TO/PLAYBOOK.yml命令进行测试,测试没问题后再执行ansible-playbook /PATH/TO/PLAYBOOK.yml命令
二、触发器
需要触发才能执行的任务,当之前定义在tasks中的任务执行完成后,若希望在基础上触发其他的任务,这时就需要定义handlers。例如,当通过ansible的模块对目标主机的配置文件进行修改之后,如果任务执行成功,可以触发一个触发器,在触发器中定义目标主机的服务重启操作,以便配置文件生效,handlers触发器具有以下优点。
- handlers是Ansible提供的条件机制之一,handlers和task很类似,但是他在被task通知的时候才会触发执行
- handlers只会在所有任务执行完成后执行,而且即使被通知了很多次,它也只会执行一次,handlers按照定义的顺序依次执行
handlers触发器的实验实例如下
[root@ansible ~]# vim /etc/ansible/httpd.yml--- #固定开头格式
- hosts: Rich #指定运行主机为Rich组remote_user: root #指定对端运行用户的身份tasks: #任务列表- name: xxx #定义任务名称command: sed -i 's/Listen 80/Listen 8080/g' /etc/httpd/conf/httpd.conf #模块为command:使用sed命令替换监听端口为8080notify: #完成任务后调用restart httpd server触发器- rehttpd handlers: #配置触发器- name: rehttpd #指定触发器名字service: name=httpd state=restarted #指定触发条件为重启httpd服务
... #结尾句
预执行
[root@ansible ~]# ansible-playbook -C /etc/ansible/httpd.yml PLAY [Rich] *******************************************************************************************************TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.2.223]
ok: [192.168.2.222]TASK [xxx] ********************************************************************************************************
skipping: [192.168.2.223]
skipping: [192.168.2.222]PLAY RECAP ********************************************************************************************************
192.168.2.222 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 192.168.2.223 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
执行
[root@ansible ~]# ansible-playbook /etc/ansible/httpd.yml PLAY [Rich] *******************************************************************************************************TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.200.113]
ok: [192.168.200.112]TASK [xxx] ********************************************************************************************************
[WARNING]: Consider using the replace, lineinfile or template module rather than running 'sed'. If you need to
use command because replace, lineinfile or template is insufficient you can add 'warn: false' to this command task
or set 'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [192.168.2.223]
changed: [192.168.2.222]RUNNING HANDLER [rehttpd] *****************************************************************************************
changed: [192.168.2.222]
changed: [192.168.2.223]PLAY RECAP ********************************************************************************************************
192.168.2.222 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.2.223 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
查看结果
[root@client1 ~]# netstat -lnpt | grep httpdtcp6 0 0 :::8080 :::* LISTEN 79542/httpd [root@client2 ~]# netstat -lnpt | grep httpdtcp6 0 0 :::8080 :::* LISTEN 79051/httpd
三、角色
将多种不同的tasks的文件集中存储在某个目录下,则该目录就是角色,角色一般存放在/etc/ansible/roles/目录中,可通过ansible的配置文件来调整默认的角色目录。/etc/ansible/roles目录下有很多的子目录,其中每一个子目录对应一个角色。每个角色也有自己的目录结构。
/etc/ansible/roles/为角色集合,该目录下有自定义的各个子目录
- mariadb:mysql角色
- apache:httpd角色
- nginx:nginx角色
每个角色的定义,以特定的层级目录结构进行组织,以Mariadb(mysql角色)为例
- file:存放copy或script等模块调用的文件
- templates:存放template模块查找所需要的模板文件的目录,如mysql配置文件等模板
- tasks:任务存放目录
- handlers:存放相关触发执行器的目录
- vars:变量存放的目录
- meta:用于存放此角色元数据
- default:默认变量存放目录,文件中定义了此角色使用的默认变量
上述目录中tasks,handlers,vars,meta,default至少应该包含一个main.yml,该目录下也可以有其他的yml文件,但是需要在main.yml文件中用include指定将其他.yml文件包含进来。
有了角色之后,可以直接在yaml文件中(playbook配置文件)中调用角色示例如下
- hosts: test01
remote_user: root
roles:
- mysql #调用角色名
- httpd #调用角色名
可以只调用一个角色,也可以调用多个角色,当定义了角色后,用ansible-playbook PLAYBOOK文件执行即可,此时ansible会到角色集合的目录(/etc/ansible/roles)去找mysql和httpd目录,然后依次运行mysql目录和httpd目录下的所有代码。
实验案例
下面通过一个实例配置数据库角色,要求被管理主机自动安装Mariadb,安装完成后上传提前准备好的配置文件到远端主机。重启服务,然后新建testdb数据库,并允许test用户对其拥有所有权限。
1. 被管理端配置yum源
[root@client1 ~]# cd /etc/yum.repos.d/[root@client1 yum.repos.d]# lsbackup CentOS-Media.repo[root@client1 yum.repos.d]# yum clean all
2. 配置数据库角色
[root@ansible ~]# mkdir -pv /etc/ansible/roles/mariadb/{files,tasks,handlers}
mkdir: 已创建目录 "/etc/ansible/roles/mariadb"
mkdir: 已创建目录 "/etc/ansible/roles/mariadb/files"
mkdir: 已创建目录 "/etc/ansible/roles/mariadb/tasks"
mkdir: 已创建目录 "/etc/ansible/roles/mariadb/handlers"#创建需要的文件路径 注意不要写错[root@ansible ~]# vim /etc/ansible/mariadb.yml
---
- hosts: test01:test02remote_user: rootroles: - mariadb
...
[root@ansible ~]# cd /etc/ansible/roles/mariadb/[root@ansible mariadb]# lsfiles handlers tasks[root@ansible mariadb]# cd tasks/[root@ansible tasks]# vim main.yml--- //固定开头格式
- name: install mariadb //指定任务名称安装mariadb数据库yum: name=mariadb-server state=present //执行yum模块安装mariadb
- name: move config file //指定任务名称移除原有配置文件shell: "[ -e /etc/my.cnf ] && mv /etc/my.cnf /etc/my.cnf.bak" //判断有就移除
- name: provide a new config file //创建一个新的配置文件copy: src=my.cnf dest=/etc/my.cnf //src源会自动到files文件去找my.cnf文件
- name: reload mariadb //指定任务名称为重启mariadbshell: systemctl restart mariadb //shell模块重启
- name: create database testdb //按要求添加执行如下sql语句shell: mysql -u root -e "create database testdb;grant all privileges on testdb.* to test@192.168.2.% identified by 'test123';flush privileges;"notify: //配置触发器- restart mariadb //为重启mariadb
...[root@ansible mariadb]# cd ../handlers/[root@ansible handlers]# vim main.yml---
- name: restart mariadb //引用上面配置的触发器service: name=mariadb state=restarted //触发后重启mariadb
...[root@ansible handlers]# cd ../files/[root@ansible files]# cp /etc/my.cnf /etc/ansible/roles/mariadb/files/[root@ansible files]# lsmy.cnf //准备my.cnf文件[root@ansible files]# cd /etc/ansible/[root@ansible ansible]# tree
.
├── ansible.cfg
├── hosts
├── httpd.yml
├── mariadb.retry
├── mariadb.yml
├── roles
│ └── mariadb
│ ├── files
│ │ └── my.cnf
│ ├── handlers
│ │ └── main.yml
│ └── tasks
│ └── main.yml
└── test.yml[root@ansible ansible]# cd[root@ansible ~]# ansible-playbook -C /etc/ansible/mariadb.yml //预执行PLAY [test01] **********************************************************************************************************************************************************TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [192.168.2.222]TASK [mariadb : install mariadb] ***************************************************************************************************************************************
changed: [192.168.2.222]TASK [mariadb : move config file] **************************************************************************************************************************************
skipping: [192.168.2.222]TASK [mariadb : provide a new config file] *****************************************************************************************************************************
ok: [192.168.2.222]TASK [mariadb : reload mariadb] ****************************************************************************************************************************************
skipping: [192.168.2.222]TASK [mariadb : create database testdb] ********************************************************************************************************************************
skipping: [192.168.2.222]PLAY RECAP *************************************************************************************************************************************************************
192.168.2.222 : ok=3 changed=1 unreachable=0 failed=0 //无报错直接执行 注意sql语句不要写错 [root@ansible ~]# ansible-playbook /etc/ansible/mariadb.yml //直接执行PLAY [test01] **********************************************************************************************************************************************************TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [192.168.2.222]TASK [mariadb : install mariadb] ***************************************************************************************************************************************
changed: [192.168.2.222]TASK [mariadb : move config file] **************************************************************************************************************************************
changed: [192.168.2.222]TASK [mariadb : provide a new config file] *****************************************************************************************************************************
changed: [192.168.2.222]TASK [mariadb : reload mariadb] ****************************************************************************************************************************************
changed: [192.168.2.222]TASK [mariadb : create database testdb] ********************************************************************************************************************************
changed: [192.168.2.222]RUNNING HANDLER [mariadb : restart mariadb] ****************************************************************************************************************************
changed: [192.168.2.222]PLAY RECAP *************************************************************************************************************************************************************
192.168.2.222 : ok=7 changed=6 unreachable=0 failed=0
3、Ansible端验证
[root@ansible ~]# ansible test01 -m shell -a 'mysql -u root -e "show databases;"'192.168.200.112 | SUCCESS | rc=0 >>
Database
information_schema
mysql
performance_schema
test
testdb #client端验证授权[root@client1 ~]# mysqlWelcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 5.5.56-MariaDB MariaDB ServerCopyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.MariaDB [(none)]> show grants for test@'192.168.2.%';
+-----------------------------------------------------------------------------------------------------------------+
| Grants for test@192.168.2.% |
+-----------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'192.168.2.%' IDENTIFIED BY PASSWORD '*676243218923905CF94CB52A3C9D3EB30CE8E20D' |
| GRANT ALL PRIVILEGES ON `testdb`.* TO 'test'@'192.168.2.%' |
+-----------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)MariaDB [(none)]> exit
Bye
四、变量
4.1、在playbook中使用自定义变量
[root@ansible ~]# vim /etc/ansible/test_vars.yml---
- hosts: allvars: #定义变量- name: "cloud" #第一个name变量age: "3" #第二个age变量tasks:- name: "{{ name }}" #{{}}两对大括号引用变量,变量名两头空格shell: echo "myname {{ name }},myage {{ age }}"register: var_result- debug: var=var_result
...特别提示:引用变量需要在双引号中引用。[root@ansible ~]# ansible-playbook /etc/ansible/test_vars.yml[WARNING]: Found variable using reserved name: name #这里提示,name是一个保留的内置变量,我们在自定义时不能用PLAY [all] **************************************************************************************************************************************************************TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [192.168.2.222]
ok: [192.168.2.223]TASK [cloud] ********************************************************************************************************************************************************
changed: [192.168.2.223]
changed: [192.168.2.222]TASK [debug] ************************************************************************************************************************************************************
ok: [192.168.2.223] => {"var_result": {"changed": true, "cmd": "echo \"myname cloud,myage 3\"", "delta": "0:00:00.040323", "end": "2019-05-15 22:45:38.739879", "failed": false, "rc": 0, "start": "2019-05-15 22:45:38.699556", "stderr": "", "stderr_lines": [], "stdout": "myname cloud,myage 3", "stdout_lines": ["myname cloud,myage 3"]}
}
ok: [192.168.2.222] => {"var_result": {"changed": true, "cmd": "echo \"myname cloud,myage 3\"", "delta": "0:00:00.039473", "end": "2019-05-15 22:45:38.740609", "failed": false, "rc": 0, "start": "2019-05-15 22:45:38.701136", "stderr": "", "stderr_lines": [], "stdout": "myname cloud,myage 3", "stdout_lines": ["myname cloud,myage 3"]}
}PLAY RECAP **************************************************************************************************************************************************************
192.168.2.222 : ok=3 changed=1 unreachable=0 failed=0
192.168.2.223 : ok=3 changed=1 unreachable=0 failed=0
我们修改一下name这个变量再发送,就不会出警告了
[root@ansible ~]# vim /etc/ansible/test_vars.yml---
- hosts: allvars: #定义变量- names: "cloud" #第一个name变量age: "3" #第二个age变量tasks:- name: "{{ names }}" #{{}}两对大括号引用变量,变量名两头空格shell: echo "myname {{ names }},myage {{ age }}"register: var_result- debug: var=var_result
...
4.2、在playbook中使用ansible的内置变量
使用ansible all -m setup | more查看ansible内置变量
[root@ansible ~]# vim /etc/ansible/test_setupvars.yml---
- hosts: allgather_facts: True #使用ansible内置变量tasks:- name: setup varshell: echo "ip {{ ansible_all_ipv4_addresses[1] }} cpu {{ ansible_processor_count }}" #查看cpu及内核情况register: var_result- debug: var=var_result
...[root@ansible ~]# ansible-playbook /etc/ansible/test_setupvars.ymlPLAY [all] ****************************************************************************************************************************TASK [Gathering Facts] ****************************************************************************************************************
ok: [192.168.2.222]
ok: [192.168.2.223]TASK [setup var] **********************************************************************************************************************
changed: [192.168.2.222]
changed: [192.168.2.223]TASK [debug] **************************************************************************************************************************
ok: [192.168.2.223] => {"var_result": {"changed": true, "cmd": "echo \"ip 192.168.2.223 cpu 1\"", "delta": "0:00:00.042725", "end": "2019-05-16 09:09:02.193466", "failed": false, "rc": 0, "start": "2019-05-16 09:09:02.150741", "stderr": "", "stderr_lines": [], "stdout": "ip 192.168.2.223 cpu 1", "stdout_lines": ["ip 192.168.2.223 cpu 1"]}
}
ok: [192.168.2.222] => {"var_result": {"changed": true, "cmd": "echo \"ip 192.168.2.222 cpu 1\"", "delta": "0:00:00.042745", "end": "2019-05-16 09:09:02.206099", "failed": false, "rc": 0, "start": "2019-05-16 09:09:02.163354", "stderr": "", "stderr_lines": [], "stdout": "ip 192.168.2.222 cpu 1", "stdout_lines": ["ip 192.168.2.222 cpu 1"]}
}PLAY RECAP ****************************************************************************************************************************
192.168.2.222 : ok=3 changed=1 unreachable=0 failed=0
192.168.2.223 : ok=3 changed=1 unreachable=0 failed=0[root@ansible ~]# vim /etc/ansible/test_setupvars.yml ---
- hosts: allgather_facts: True #使用ansible内置变量tasks:- name: setup varshell: echo "ip {{ ansible_all_ipv4_addresses[1] }} cpu {{ ansible_processor_count }}" >> /tmp/test
- name: setup var2shell: echo "time {{ ansible_date_time["date"] }}" >> /tmp/test #添加时间register: var_result- debug: var=var_result
...执行继续查看变化
5.Template模板
配置文件如果使用copy模块去下发的话,那么所有主机的配置都是一样的; 如果下发的配置文件里有可变的配置,需要用到template模块。
5.1、利用template模块下发可变的配置文件
[root@ansible ~]# vim /tmp/testmy name is {{ myname }} #自定义变量
my name is {{ ansible_all_ipv4_addresses[1] }} #系统变量[root@ansible ~]# vim /etc/ansible/filevars.yml
---
- hosts: allgather_facts: True #开启系统变量vars:- myname: "cloud" #自定义变量tasks:- name: template testtemplate: src=/tmp/test dest=/root/test #使用template下发可变配置文件
...[root@ansible ~]# ansible-playbook /etc/ansible/filevars.ymlPLAY [all] ************************************************************************TASK [Gathering Facts] ************************************************************
ok: [192.168.2.222]
ok: [192.168.2.223]TASK [template test] **************************************************************
changed: [192.168.2.223]
changed: [192.168.2.222]PLAY RECAP ************************************************************************
192.168.2.222 : ok=2 changed=1 unreachable=0 failed=0
192.168.2.223 : ok=2 changed=1 unreachable=0 failed=0 [root@client2 ~]# vim /root/test my name is cloud
my name is 192.168.2.223
5.2、下发配置文件里面使用判断语法
[root@ansible ~]# vim /tmp/if.j2{% if PORT %} #if PORT存在
ip=0.0.0.0:{{ PORT }}
{% else %} #否则的话
ip=0.0.0.0:80
{% endif %} #结尾[root@ansible ~]# vim /etc/ansible/test_ifvars.yml---
- hosts: allgather_facts: True #开启系统内置变量vars:- PORT: 90 #自定义变量tasks:- name: jinja2 if testtemplate: src=/tmp/if.j2 dest=/root/test
...[root@ansible ~]# ansible-playbook /etc/ansible/test_ifvars.ymlPLAY [all] ************************************************************************TASK [Gathering Facts] ************************************************************
ok: [192.168.2.222]
ok: [192.168.2.223]TASK [jinja2 if test] *************************************************************
changed: [192.168.2.222]
changed: [192.168.2.223]PLAY RECAP ************************************************************************
192.168.2.222 : ok=2 changed=1 unreachable=0 failed=0
192.168.2.223 : ok=2 changed=1 unreachable=0 failed=0 [root@client1 ~]# cat /root/test #if PORT存在
ip=0.0.0.0:90#结尾
如果我们将变量PORT值为空的话,就会是另外的结果
[root@ansible ~]# vim /etc/ansible/test_ifvars.yml---
- hosts: allgather_facts: True #开启系统内置变量vars:- PORT: #变量为空tasks:- name: jinja2 if testtemplate: src=/tmp/if.j2 dest=/root/test
...[root@ansible ~]# ansible-playbook /etc/ansible/test_ifvars.ymlPLAY [all] ************************************************************************TASK [Gathering Facts] ************************************************************
ok: [192.168.2.222]
ok: [192.168.2.223]TASK [jinja2 if test] *************************************************************
changed: [192.168.2.222]
changed: [192.168.2.223]PLAY RECAP ************************************************************************
192.168.2.222 : ok=2 changed=1 unreachable=0 failed=0
192.168.2.223 : ok=2 changed=1 unreachable=0 failed=0[root@client1 ~]# cat /root/test #否则的话
ip=0.0.0.0:80#结尾
六、基于Playbook部署Nginx综合案例
1、创建目录结构
[root@ansible ~]# mkdir -pv /etc/ansible/roles/nginx/{files,handlers,tasks,templates,vars}
mkdir: 已创建目录 "/etc/ansible/roles/nginx"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/files"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/handlers"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/tasks"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/templates"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/vars"
2、目录查看结构
[root@ansible ansible]# tree
.
├── ansible.cfg
├── hosts
├── nginx.retry
├── nginx.yaml
└── roles└── nginx├── files│ └── nginx-1.16.0.tar.gz├── handlers│ └── main.yaml├── tasks│ └── main.yaml├── templates│ └── nginx.conf└── vars└── main.yaml7 directories, 9 files
3、定义一个主调用文件
[root@ansible ansible]# vim /etc/ansible/nginx.yaml ---
- hosts: crushlinux #执行的主机范围gather_facts: True #开启系统内置变量remote_user: rootroles: #启用roles原型配置- nginx #执行nginx原型模组
...
4、files:存储由copy或script等模块调用的文件;
[root@ansible ansible]# ls -l /etc/ansible/roles/nginx/files/nginx-1.16.0.tar.gz -rw-r--r-- 1 root root 1032345 5月 16 00:30 /etc/ansible/roles/nginx/files/nginx-1.16.0.tar.gz
5、handlers:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
[root@ansible ansible]# vim /etc/ansible/roles/nginx/handlers/main.yaml ---
- name: start nginxraw: /usr/local/nginx/sbin/nginx
...
6、tasks:目录至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;
[root@ansible ansible]# vim /etc/ansible/roles/nginx/tasks/main.yaml ---
- name: yum installyum: name={{ item }} state=latestwith_items:- openssl-devel- pcre-devel- zlib-devel- gcc- gcc-c++- make- name: user nginxshell: useradd -M -s /sbin/nologin nginx- name: packagecopy: src=nginx-1.16.0.tar.gz dest=/usr/src- name: install nginxshell: cd /usr/src ; tar xf nginx-1.16.0.tar.gz -C /usr/src ; cd /usr/src/nginx-1.16.0 ; ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre && make && make install
- name: copy conf filetemplate: src=nginx.conf dest=/usr/local/nginx/conf/nginx.confnotify:- start nginx
...
7、templates:存储由template模块调用的模板文本;
[root@ansible ansible]# vim /etc/ansible/roles/nginx/templates/nginx.conf user nginx;
worker_processes {{ ansible_processor_vcpus }};
{% if ansible_processor_vcpus == 1 %}
worker_cpu_affinity 10;
{% elif ansible_processor_vcpus == 2 %}
worker_cpu_affinity 01 10;
{% elif ansible_processor_vcpus == 4 %}
worker_cpu_affinity 0001 0010 0100 1000;
{% elif ansible_processor_vcpus == 8 %}
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
{% else %}
worker_cpu_affinity 0001 0010 0100 1000;
{% endif %}error_log logs/error.log;
pid logs/nginx.pid;events {use epoll;worker_connections 65535;
}http {include mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log logs/access.log main;sendfile on;keepalive_timeout 65;gzip on;server {listen {{ nginxport }};server_name {{ server_name}};location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
}
8、vars:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
[root@ansible ansible]# vim /etc/ansible/roles/nginx/vars/main.yaml ---
nginxport: "80"
server_name: "www.crushlinux.com"
...
9、其他:
meta:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
default:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
10、测设部署
[root@ansible ansible]# vim hosts[web]
192.168.2.222
192.168.2.223[root@ansible ansible]# ansible-playbook /etc/ansible/nginx.yaml PLAY [crushlinux] *******************************************************************************************************************************************************TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [192.168.2.223]
ok: [192.168.2.222]TASK [nginx : yum install] **********************************************************************************************************************************************
ok: [192.168.2.222] => (item=[u'openssl-devel', u'pcre-devel', u'zlib-devel', u'gcc'])
ok: [192.168.2.223] => (item=[u'openssl-devel', u'pcre-devel', u'zlib-devel', u'gcc'])TASK [nginx : user nginx] ***********************************************************************************************************************************************
changed: [192.168.2.222]
changed: [192.168.2.223]TASK [nginx : package] **************************************************************************************************************************************************
ok: [192.168.2.223]
ok: [192.168.2.222]TASK [nginx : install nginx] ********************************************************************************************************************************************
changed: [192.168.2.222]
changed: [192.168.2.223]TASK [nginx : copy conf file] *******************************************************************************************************************************************
ok: [192.168.2.222]
ok: [192.168.2.223]PLAY RECAP **************************************************************************************************************************************************************
192.168.2.222 : ok=6 changed=2 unreachable=0 failed=0
192.168.2.223 : ok=6 changed=2 unreachable=0 failed=0
11、检验
[root@client1 ~]# netstat -anptl | grep nginxtcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 13778/nginx: master [root@client2 ~]# netstat -anptl | grep nginxtcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 13778/nginx: master