自动化运维-Ansible触发器与变量

一、Ansible触发器

有这样一个场景:当nginx配置更新后,希望nginx可以自动重载配置;如果nginx配置没有做任何变动,则不做任何动作。这样的需求我们该如何实现呢?

在Ansible中,提供了一个handlers的"触发器"机制,可以用于实现上述需求。

handlers:任务执行后的条件触发器

这是Ansible中最传统、最常用的"触发器"实现。它是一类特殊的任务,只有当被其他任务通过 notify 关键词明确通知时,才会在Playbook执行的最后阶段运行。

  • 工作流程 :当一个任务执行并导致系统状态发生改变 (状态变为 changed)时,它可以使用 notify 指令去"通知"一个或多个Handler。被通知的Handler会在当前Play的所有任务执行完毕后,统一按顺序执行。

  • 关键特性

    • 条件触发:只有任务真正改变了系统状态,才会触发通知,避免不必要的操作。
    • 只执行一次 :即使在整个Playbook运行期间,一个Handler被多个任务多次通知,它也只会执行一次。这能有效避免如多次重启服务等问题。
  • 典型应用场景:最经典的用法是在配置文件被修改后,自动重启相关服务以使新配置生效。

  • 配置示例 :以下示例中,Write the apache config file 任务在更新配置文件后,会通过 notify 触发 Restart apache 这个Handler来重启服务。

    yaml 复制代码
    tasks:
      - name: Write the apache config file
        ansible.builtin.template:
          src: /srv/httpd.j2
          dest: /etc/httpd.conf
        notify:   # 任务发生改变时,通知名为 "Restart apache" 的 handler
          - Restart apache
    
    handlers:     # 定义 handler
      - name: Restart apache
        ansible.builtin.service:
          name: httpd
          state: restarted

默认情况下,所有task执行完毕后,才会执行各个handler,并不是执行完某个task后,立即执行对应的handler,如果想要在执行完某些task后立即执行对应的handler,则需要使用meta模块,如下示例所示:

yaml 复制代码
tasks:
  - name: Write the apache config file
    ansible.builtin.template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf
    notify:   # 任务发生改变时,通知名为 "Restart apache" 的 handler
      - Restart apache
  - meta: flush_handlers

handlers:     # 定义 handler
  - name: Restart apache
    ansible.builtin.service:
      name: httpd
      state: restarted

当配置文件发生改变会通知Restart apache立即执行。

二、Ansible变量

变量 :在编程语言中,变量是一个可以存储数据的"容器",其值可以被改变和重新赋值。

用途 :为一段数据赋予一个简短、易于记忆的名称,便于在代码中重复引用。

变量名规则 :有效的变量名只能包含字母、数字和下划线,并且必须以字母开头。

在 Ansible 中,可以通过以下几种形式传递变量:

1. Ad-hoc 命令行传递

在执行 ansibleansible-playbook 命令时,可以通过 -e 参数指定外部变量。

bash 复制代码
-e var=value

这种形式定义的变量拥有最高优先级。如果与其他方式定义的变量名冲突,将优先使用此处指定的值。

2. 在 Inventory 中定义变量

在 Inventory 文件中,可以通过以下两种方式定义变量:

  • 为特定主机定义变量:在主机行后直接赋值。

    复制代码
    IP/HOSTNAME variable_name=value
  • 为组定义变量 :在组名下使用 [groupname:vars] 段落。

    复制代码
    [groupname:vars]
    variable_name=value
    [all:vars]
    variable_name=value 

    all:vars下定义的变量对所有组都有效。

3. 在 Playbook 中定义变量

3.1 直接在 Playbook 中定义变量

这是最直接的方式,适用于变量数量不多、且仅在当前 Playbook 中使用的情况。变量通过 vars 关键字在 Play 的顶层定义。

yaml 复制代码
---
- hosts: webserver
  vars:
    - var1_name: hello
    - var2_name: world
  tasks:
    - name: 显示变量值
      debug:
        var: var1_name,var2_name

说明

  • vars 关键字下可以定义一个列表,每个列表项都是一个键值对形式的变量。
  • 定义的变量在整个 Play(即当前 hosts 作用域)内有效,可以在后续的所有任务中通过 {``{ 变量名 }} 引用。
  • 这种方式简单明了,适合定义环境、路径等固定值。

3.2 使用 vars_files 引入外部变量文件

当变量较多或需要在多个 Playbook 之间复用时,可以将变量定义在独立的 YAML 文件中,然后通过 vars_files 关键字引入。文件路径可以是相对路径(相对于 Playbook 文件)或绝对路径。

yaml 复制代码
---
- name: 使用外部变量文件
  hosts: webserver
  vars_files:
    - ./vars.yaml  # 引入当前目录下的 vars.yaml 文件
  tasks:
    - debug:
        msg: "变量值:{{ var1_name }}, {{ var2_name }}"

说明

  • vars_files 接受一个列表,可以同时引入多个变量文件。
  • 引入后,文件中定义的变量可以在当前 Play 的所有任务中直接使用。
  • 这种方式有助于实现配置与逻辑的分离,提升 Playbook 的可维护性。

4.在Role中定义

yaml 复制代码
---
- hosts: webserver
  roles:
    - {role:web,port:80} 

说明

role:web :表示调用变量的角色。

port:80:role可调用的变量和变量的值。

5.注册变量

将任务执行的结果使用register注册保存到变量,供后续任务使用。

yaml 复制代码
---
- hosts: webserver
  tasks:
    - name: register a variable
      shell: echo 'hello world'
      register: print_hello

    - name: show print_hello
      debug:
        msg: '{{print_hello.stdout}}'

以上shell模块执行的命令因为实际上是在被管理节点上执行的,所以输出的结果不会在剧本执行过程中输出,如果需要使用输出的结果需要将其注册为一个变量。

6.系统信息变量

系统信息变量:facts,默认会执行,可在playbook中直接调用。

属性:{{ ansible_hostname}}

层级属性:{{ ansible_devices.vda.size}}

数组: {{ ansible_dns.nameservers0 }}

如果用不到facts,建议关闭,可以提高剧本执行效率。

yaml 复制代码
---
- hosts: webserver
  gather_facts: no  #关闭,使用false也可以
  tasks:
    - name: Install nginx
      yum: 
        name:nginx
        state: present
      tags: install

系统信息变量可以通过ansible webserver -m setup 命令查看。

yaml 复制代码
---
- hosts: webserver
  tasks:
    - name: 获取bond0的名称
      debug: 
        msg: '{{ansible_bond0.device}}'

系统信息变量通过.表示层级关系。

7.内置主机变量

常用的内置变量:

inventory_hostname #清单主机名

hostvars #包含被控制主机的所有变量

hostvars.node1 #只调用node1主机所有变量

hostvars.node1.group_names #显示node1所在的组的名字

groups #所有主机以及组信息

groups.all #所有被控制主机主机名

groups.test01 #显示test01组里的所有主机名

groups_names #当前运行任务的主机所在的组的名字

hostvars:获取当前目标主机主机名

yaml 复制代码
---
- hosts: webserver
  gather_facts: no
  tasks:
    - debug:
        msg: "{{hostvars}}"
    - debug:
        msg: "{{hostvars['192.168.32.150']['inventory_hostname']}}"

group_names:当前主机所在的组:

yaml 复制代码
---
- hosts: webserver
  tasks:
    - debug:
        msg: "{{group_names}}"

groups:资产清单中所有组的列表:

yaml 复制代码
---
- hosts: webserver
  gather_facts: no
  tasks:
    - debug:
        msg: "{{groups}}"

本篇文章介绍了触发器以及7种变量的定义与使用方式,如果您有疑问,欢迎留言交流。

相关推荐
不会就选b1 小时前
Linux之线程(二)
linux·运维·服务器
HiDev_1 小时前
【非标自动化】上位机快速上手(创建winform并运行起来)
运维·自动化
乐维_lwops1 小时前
乐维社区“专家坐诊”第405期问答
运维·cmdb·运维监控·答疑·运维智能体·乐维运维智能体
esabby1 小时前
韩国站群服务器租用平台推荐与外贸建站优势深度解析
运维·服务器
Aision_2 小时前
实习手记 Day:从 ELK 到 Agent 的“最后一公里”——告警消费与上下文富化
运维·人工智能·web安全·elk·网络安全·安全威胁分析
CDN3602 小时前
俄语区跨境站点优化实战:CDN+Nginx 解决 H5 白屏、交互延迟、链路卡顿问题
运维·nginx·交互·h5 加速·nginx 轻交互调优
梦想的旅途22 小时前
企微私域 AI 创作:文案生成与 AI 配图自动化发布实战
人工智能·自动化·企业微信
zoe驿鹿2 小时前
【CI/CD】前端工程化与自动化:从“手工作坊”到“现代化工厂”的演进之路
前端·ci/cd·自动化
邀星月为媒2 小时前
高阶加餐 08|Prompt 故障定位与可观测性:模型突然变差时,别再靠“重新写一遍 Prompt”解决
服务器·数据库·prompt