playbook条件语句

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

ansible条件语句

#使用when判断
- hosts: web02
  tasks:
  - name: 安装apache(centos:httpd、ubuntu:apache2)
    yum:
      name: apache2
      state: present
    when: ansible_os_family == 'Debain'
  - name: 安装apache(centos:httpd、ubuntu:apache2)
    yum:
      name: httpd
      state: present
    when: ansible_os_family == 'RedHat'
-----------------------------------------------------------------------------------------------------
==:等于
!=:不等于
>:大于
>=:大于等于
<:小于
<=:小于等于
is match:匹配 使用通配符
is not match: 取反
#判断多台主机
- hosts: all
  tasks:
  - name: 安装apache(centos:httpd、ubuntu:apache2)
    yum:
      name: httpd
      state: present
    when: ansible_hostname is not match 'web*'

使用小括号进行分组运算

- hosts: all
  tasks:
  - name: 安装apache(centos:httpd、ubuntu:apache2)
    yum:
      name: httpd
      state: present
    when: ( ansible_hostname is not match 'web*' ) or ansible_hostname == 'db01'

条件运算

- hosts: all
  tasks:
  - name: 安装apache(centos:httpd、ubuntu:apache2)
    yum:
      name: httpd
      state: present
    when: ansible_os_family == "RedHat" and ansible_distribution_major_version | int >= 6
#取值完后必须交给int做整数运算
常用的数据类型有以下几种:
int:代表整数类型,例如1、2、3等。
float:代表浮点数类型,例如3.14、0.25等。
str:代表字符串类型,是由一串字符组成的序列,例如“Hello World!”、“Python Programming”等。
bool:代表布尔类型,只有True和False两个值。
list:代表列表类型,是由一系列有序元素组成的一组值,例如[1, 2, 3]、[“apple”, “banana”, “orange”]等。
tuple:代表元组类型,类似于列表类型,但元素不可修改,例如(1, 2, 3)、(“apple”, “banana”, “orange”)等。
dict:代表字典类型,是由一组键值对组成的数据类型,例如{“name”: “John”, “age”: 30}、{“apple”: 1, “banana”: 2, “orange”: 3}等。
set:代表集合类型,是由一组互不相同、无序的元素组成的数据类型,例如{1, 2, 3}、{“apple”, “banana”, “orange”}等。

ansible流程控制循环

with_item:循环

## 列表循环  注意:模块中,只有一个动作是变量时,使用列表循环
#示例:循环启动服务
- hosts: web02
  tasks:
  - name: 启动nginx php mysql
    service:
      name: "{{ item }}"
      state: stopped
      enabled: true
    with_items:
      - nginx
      - php-fpm
      - mariadb
# 字典循环  注意:模块中,有一个以上动作是变量时,使用字典循环
- name: 推送nginx配置文件
  copy:
    src: "{{ item.yl_sb }}"
    dest: "{{ item.dest }}"
  with_items:
      - { src: '/opt/ansible/nginx_php/nginx.conf','dest':'/etc/nginx.conf'}
      - {dest: '/opt/ansible/nginx_php/www.conf','dest':'/etc/nginx/conf.d/www.conf'}

ansible的触发器handlers

handlers是用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可。
#示例:
- name: 推送nginx配置文件
  copy:
    src: "{{ item.yl_sb }}"
    dest: "{{ item.dest }}"
  with_items:
    - { src: '/opt/ansible/nginx_php/nginx.conf','dest':'/etc/nginx.conf'}
    - {dest: '/opt/ansible/nginx_php/www.conf','dest':'/etc/nginx/conf.d/www.conf'}
  notify: restart nginx

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: reloaded
-----------------------------------------------------------------------------------------------------
注意:
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

ansible任务标签tags

#默认情况下,Ansible在执行一个playbook时,会执行playbook中定义的所有任务,Ansible的标签(tag)功能可以给单独任务甚至整个playbook打上标签,然后利用这些标签来指定要运行playbook中的个别任务,或不执行指定的任务。

打开标签的方式

一个任务打一个标签

#创建用户
- hosts: all
  vars_files: /root/like/bl.yaml
  tasks:
  - name: 创建www组
    group:
      name: "{{ user }}"
      gid: "{{ id }}"
      state: present
    tags: create_group     #//使用标签
  - name: 创建www用户
    user:
      name: "{{ user }}"
      uid: "{{ id }}"
      group: "{{ id }}"
      shell: /sbin/nologin
      create_home: false

一个任务打多个标签

#创建用户
- hosts: all
  vars_files: /root/like/bl.yaml
  tasks:
  - name: 创建www组
    group:
      name: "{{ user }}"
      gid: "{{ id }}"
      state: present
    tags:
      - create_group
      - nginx_group
      - php_group                   #//使用标签
  - name: 创建www用户
    user:
      name: "{{ user }}"
      uid: "{{ id }}"
      group: "{{ id }}"
      shell: /sbin/nologin
      create_home: false

多个任务打一个标签

#创建用户
- hosts: all
  vars_files: /root/like/bl.yaml
  tasks:
  - name: 创建www组
    group:
      name: "{{ user }}"
      gid: "{{ id }}"
      state: present
    tags: create_group     #//使用标签
  - name: 创建www用户
    user:
      name: "{{ user }}"
      uid: "{{ id }}"
      group: "{{ id }}"
      shell: /sbin/nologin
      create_home: false
    tags: create_group

执行方式

# -t :指定标签名即可
--skip-tags:跳过指定的标签
[root@m01 ansible]# ansible-playbook wordpress.yaml -i hosts -t 'nginx_group'

ansible playbook的复用

#在之前写playbook的过程中,我们发现,写多个playbook没有办法,一键执行,这样我们还要单个playbook挨个去执行,很鸡肋。所以在playbook中有一个功能,叫做include用来动态调用task任务列表

image-20230526134826602

只调用task:include_tasks调用整个task文件:include (新版本:import_playbook)
在saltstack中,叫做top file入口文件:

[root@m01 new]# tree nginx
nginx
├── config_nginx.yaml
├── install_nginx.yaml
└── start_nginx.yaml

[root@m01 new]# cat nginx/install_nginx.yaml
- name: 安装nginx
  yum:
    name: nginx
    state: present

[root@m01 new]# cat nginx/config_nginx.yaml
- name: 配置nginx
  copy:
    src: /opt/ansible/nginx_php/nginx.conf
    dest: /etc/nginx/nginx.conf
  notify: Restart Nginx

[root@m01 new]# cat nginx/start_nginx.yaml
- name: 启动nginx
  service:
    name: nginx
    state: started
    enabled: true
----------------------------------------------------------------------------------------------------
- hosts: all
  tasks:
  - include_tasks: nginx/install_apache.yaml
    when: ansible_hostname == 'web01'
  - include_tasks: nginx/config_nginx.yaml
    when: ansible_hostname == 'web01'
  - include_tasks: nginx/start_nginx.yaml
    when: ansible_hostname == 'web01'
# 目录规范
[root@m01 ansible]# tree
.
├── mysql
│ ├── conf
│ │ └── my.cnf
│ ├── conf_mysql.yaml
│ ├── file
│ ├── install_mysql.yaml
│ └── start_mysql.yaml
├── nfs-client
├── nfs-server
├── nginx
├── php
├── rsync-client
├── rsync-server
└── wordpress

playbook忽略错误

#语法
ignore_errors: true
#示例:
- hosts: all
  tasks:
  - name: 安装nginx
    shell: 'rpm -ivh /opt/nginx_php/*.rpm'
  when: ansible_hostname is match 'web*'
  ignore_errors: true
- name: chuangjianmulu
  file:
    path: /opt/123
    state: directory

playbook错误处理,抑制变更

#语法
changed_when: false
#示例
[root@m01 ansible]# vim db.yaml
- hosts: web01
  tasks:
  - name: 查看磁盘
    shell: 'df -h'
  changed_when: false