Ansible 流程控制

一、playbook 条件语句

不管是shell还是各大编程语言中,流程控制,条件判断这些都是必不可少的,在我们使用Ansible的过程中,条件判断的使用频率极其高。
例如:
1.我们使用不同的系统的时候,可以通过判断系统来对软件包进行安装。
2.在nfs和rsync安装过程中,客户端服务器不需要推送配置文件,之前我们都是写多个play,会影响效率。
3.我们在源码安装nginx的时候,执行第二遍就无法执行了,此时我们就可以进行判断是否安装过。

1.判断系统

# ansible判断
[root@m01 ~]# ansible web01 -m setup
[root@m01 ~]# vim xitong.yml
- hosts: web_group
tasks:
- name: Install Centos httpd
shell: "yum install -y httpd"
when: ansible_distribution == "CentOS"

- name: Install Ubuntu httpd
shell: "apt-get apache2"
when: ansible_distribution == "Ubuntu"
2.判断主机
[root@m01 ~]# cat base.yml
- hosts: nfs_group
tasks:
- name: Create www Group
group:
name: www
gid: 666
state: present
when: ansible_fqdn != "nfs"

- name: Create www User
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
when: ansible_fqdn != "nfs"
3.判断服务是否安装
[root@m01 ~]# cat php.yml  
- hosts: web_group
tasks:
- name: Tar php Package
unarchive:
src: /root/package/php.tar.gz
dest: /tmp/

#使用shell模块,检查php是否安装,将结果赋值给注册的变量
- name: Check php Install Status
shell: "rpm -qa | grep php | wc -l"
register: get_php_instll_status

#调用注册的变量,当变量中stdout_lines为0的时候,才会安装php
- name: Install php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_instll_status.stdout_lines == 0
4.判断系统版本启动服务
# 1、写法一:使用列表的形式
[root@m01 ~]# vim startserver.yml
- hosts: web_group
tasks:
- name: Start CentOS 6 Server
shell: "/etc/init.d/httpd start"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "6"

- name: Start CentOS 7 Server
shell: "systemctl restart httpd"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "7"

# 2、写法二:多条件and连接(or是或者)
[root@m01 ~]# vim startserver.yml
- hosts: web_group
tasks:
- name: Start CentOS 6 Server
shell: "/etc/init.d/httpd start"
when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "6")

- name: Start CentOS 7 Server
shell: "systemctl restart httpd"
when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "7")
5.判断服务是否启动
[root@m01 ~]# vim web.yml
- hosts: web_group
tasks:
- name: Check Httpd Server
command: systemctl is-active httpd
ignore_errors: yes
register: check_httpd

- name: debug outprint
debug: var=check_httpd

- name: Httpd Restart
service:
name: httpd
state: restarted
when: check_httpd.rc == 0

二、playbook 循环语句

在之前的学习过程中,我们经常会有传送文件,创建目录之类的操作,创建2个目录就要写两个file模块来创建,如果要创建100个目录,我们需要写100个file模块???妈耶~~~~ 当然不是,只要有循环即可,减少重复性代码。
1.定义循环安装服务
[root@m01 ~]# vim install.yml 
- hosts: nfs_group
tasks:
- name: install server
yum:
name: "{{ page }}"
state: present
vars:
page:
- tree
- nfs-utils
- httpd
2.定义循环启动服务
#错误写法
[root@m01 ~]# vim start.yml
- hosts: nfs_group
tasks:
- name: Start Server
systemd:
name: "{{ package }}"
state: started
vars:
package:
- nfs-utils
- httpd
- tree

#正确写法
[root@m01 ~]# vim start.yml
- hosts: nfs_group
tasks:
- name: Start Server
systemd:
name: "{{ item }}"
state: started
with_items:
- nfs-utils
- httpd
- tree
3.字典定义变量
# 1.创建多个用户和组
[root@m01 ~]# cat user.yml
- hosts: all # 1.创建多个组
tasks:
- name: Create Some Group
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
state: present
with_items:
- { name: "mm", gid: "1000" }
- { name: "ping", gid: "1001" }
- { name: "egon", gid: "1002" }

- name: Create Some User # 2.创建多个用户
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: "{{ item.group }}"
shell: "{{ item.shell }}"
create_home: "{{ item.create_home }}"
with_items:
- { name: "mm", uid: "1000", group: "mm", shell: "/sbin/nologin", create_home: "false" }
- { name: "ping", uid: "1001", group: "ping", shell: "/bin/bash", create_home: "false" }
- { name: "egon", uid: "1002", group: "egon", shell: "/bin/bash", create_home: "true" }

三、playbook handlers 触发器

1.什么是handlers?
handler用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。
在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可。
2.配置触发器
[root@m01 ~]# cat nginx.yml 
- hosts: web01
tasks:
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx

- name: Start Nginx Server
systemd:
name: nginx
state: started

handlers:
- name: restart_nginx
systemd:
name: nginx
state: restarted
3.触发器使用注意事项
1.无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次。

2.Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。

3.Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。

4.如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的--force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。

5.不能使用handlers替代tasks
4.简单优化后的php文件
[root@m01 ~]# cat php.yml 
- hosts: web_group
tasks:
- name: Tar php Package
unarchive:
src: /~/package/php.tar.gz
dest: /tmp/

- name: Check php Install Status
shell: "rpm -qa | grep php | wc -l"
register: get_php_instll_status

- name: Install php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_instll_status.stdout_lines == 0

- name: Config php Server
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
with_items:
- { src: "/~/conf/php.ini", dest: "/etc" }
- { src: "/~/conf/www.conf", dest: "/etc/php-fpm.d/" }
notify: restart_php

- name: Start php Server
systemd:
name: php-fpm
state: started

handlers:
- name: restart_php
systemd:
name: php-fpm
state: restarted