Ansible playbook 与handler

Playbook(剧本)

我们之前执行ansble是通过ad-hoc的方式来执行的,这样执行的好处就是我的任务只有1个的时候非常的方便,坏处那就是一次只能执行一个任务

如果我现在有这样一种场景:我要根据我上一个任务执行的结果来决定下一个任务是否执行,这个ad-hoc能做到吗?是不可以的,我们只能自行判断他是否执行成功,是否要继续下一个任务

说更直白一点,playbook就是一系列ad-hoc的集合,你可以把你想执行的所有任务都写到里面去,他会从上至下的执行,并且playbook还有很多ad-hoc做不到的

1. yaml

playbook使用yaml语法来编写

1.1 yaml的语法规则

  1. 大小写敏感
  2. 使用缩进标识层级关系
  3. 使用缩进时必须是空格,不能是Tab键
  4. 缩进的空格数不重要,只要同一层级保持一致就可以

1.2 yaml的数据类型

  1. 纯量:单个的,已经是最小个体,无法再拆分

  2. 数组:一组按次序排列的值,数组元素使用 短横线开头

    - var01

    - var02

  3. 字典:采用键值对的方式

1.3 yaml的示例

基本信息:
  名称: 张三
  年龄: 30
  性别: 男

地址:
  国家: 中国
  省份: 广东
  城市: 广州
  街道: 中山路
  邮编: 510000

联系方式:
  电话: 
    - 类型: 手机
      号码: 13800000000
    - 类型: 工作
      号码: 020-88888888
  邮箱: zhangsan@example.com

技能:
  编程语言:
    - Python
    - Java
    - JavaScript
  工具:
    - Git

这就是一个yaml语法的示例了

2. ansible-playbook

2.1 playbook入门

我们现在来编写一个简单的playbook

[ansible@master ansible]$ vim first_playbook.yaml
- name: This is first ansible playbook
  hosts: all
  tasks:
    - name: This is the First task
      shell: whoami

这就是一个简单的playbook了,我们先来逐行分析

  • 第一行 - name: 代表这个play的名字,一个playbook里面可以包含多个play
  • hosts:指定要运行的主机
  • tasks:指定任务
  • 第四行 - name :指定这个任务的名字
  • shell:这个是我们要使用的模块名
  • whoami:是我们需要执行的命令

2.2 执行playbook

我们写完剧本之后如何去执行呢?

[ansible@master ansible]$ ansible-playbook first_playbook.yaml

PLAY [This is first ansible playbook] ******************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.200.210]

TASK [This is the First task] **************************************************
changed: [192.168.200.210]

PLAY RECAP *********************************************************************
192.168.200.210            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

使用ansible-playbook 然后去指定这个剧本就可以执行他了,剧本执行完之后下面是有汇总的,ok表示没有发生更改,changed表示命令执行成功并且主机发生了更改

2.3 使用playbook安装软件

- name: Install sotfware
  hosts: all
  tasks:
    - name: start install
      yum:
        name: redis
        state: present

去执行这个剧本

[ansible@master ansible]$ ansible-playbook second.yaml 

PLAY [Install sotfware] ********************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.200.210]

TASK [start install] ***********************************************************
changed: [192.168.200.210]

PLAY RECAP *********************************************************************
192.168.200.210            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

如果你自己正在操作的话你就能很直观的看见OK的部分是绿色的,发生改变的地方是黄色的

image-20240620154345326

修改这个剧本,让redis开机自启

[ansible@master ansible]$ vim second.yaml 
- name: Install sotfware
  hosts: all
  tasks:
    - name: start install
      yum:
        name: redis
        state: present
    - name: enabled redis
      systemd:
        name: redis
        enabled: yes
        state: started

注意了,这里有2个任务了,所以任务名前面也是需要加上短横线的

[ansible@master ansible]$ ansible-playbook second.yaml 

PLAY [Install sotfware] ********************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.200.210]

TASK [start install] ***********************************************************
ok: [192.168.200.210]

TASK [enabled redis] ***********************************************************
changed: [192.168.200.210]

PLAY RECAP *********************************************************************
192.168.200.210            : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

我们可以看见,start install 这个任务现在变成了 ok ,之前执行的时候都是changed的,这是因为ansible的模块具有幂等性,也就说无论你执行多少次,他只有第一次执行的时候会发生改变,你后续再去执行,他一看,你要安装的软件我的主机上有,那我就不执行这个了

3. 更多示例

再多写几个yaml的示例大家应该也就能看懂了

---
- name: Ansible Playbook Example for Creating Users and Groups
  hosts: all
  become: yes
  tasks:
    - name: Create the first group
      group:
        name: group1
        state: present

    - name: Create the second group
      group:
        name: group2
        state: present

    - name: Create a user and add to both groups
      user:
        name: demo_user
        groups: group1,group2
        append: yes
        state: present

这个剧本就是 使用group模块创建了group1和group2,并且使用user模块创建了一个用户,并且group1和group2作为这个用户的附属组

- name: Ansible Playbook Example for Package Installation and Configuration
  hosts: all
  tasks:
    - name: Install nginx package
      package:
        name: nginx
        state: present

    - name: Copy nginx configuration file
      copy:
        src: /path/to/local/nginx.conf
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'

    - name: Restart nginx service
      service:
        name: nginx
        state: restarted

这个剧本就是说先安装一个nginx,然后使用copy模块将本地的文件发送到远程主机,最后重启nginx服务

多写一点就熟练了
我就说一个事:剧本里面不要按Tab键,虽然现在最新版的vim可以将你的tab转换为空格,但是我也不建议按tab

Handler

在ansible的playbook中,handler也是一个任务,只不过这个任务默认不执行,只有被触发才会执行

handler通过设置notify来监视某个任务,只有当这个任务在主机上发生改变时才会触发handler,handler会在所有的play都执行完之后才会执行,这样避免了handler监视的多个task执行结果都发生变化后导致handler重复执行

1. handler简单示例

只需要通过一个简单的示例就能明白这个是怎么玩的了

- name: test handler
  hosts: all
  tasks:
    - name: install redis
      yum:
        name: redis
        state:  present
      notify: start redis
      
  handlers:
    - name: start redis
      systemd:
        name: redis
        state: started

注意这里的handlers是与tasks一个层级的,并且handlers下面的name需要与notify后面写的name一致

来到远程主机看看是否被启动

[root@node1 ~]# systemctl is-active redis
active

我们来将redis给停止,然后重新执行剧本

[root@node1 ~]# systemctl stop redis.service
[ansible@master ansible]$ ansible-playbook handler.yaml 

PLAY [test handler] ************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.200.210]

TASK [install redis] ***********************************************************
ok: [192.168.200.210]

PLAY RECAP *********************************************************************
192.168.200.210            : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

回到远程主机查看状态

[root@node1 ~]# systemctl is-active redis
inactive

发现他是没有启动的,没有启动的原因就是我们监视的那个任务他是没有在主机上发生改变了,我们给定的任务是安装redis,在第一次执行的时候因为主机没有redis,所以他安装了,并且监视到了他有发生改变,所以他会将redis给启动,但我们将redis给停掉之后再去执行剧本,他已经安装过了,无法继续安装,所以这个任务没有发生改变,那么对应的handler也就不会执行了,没执行就不会启动redis了

posted @ 2024-06-20 16:00  FuShudi  阅读(29)  评论(0编辑  收藏  举报