50.Ansible变量,判断,监控触发

Ansible变量-概述

一、变量概述

变量提供了便捷的方式来管理Ansible playbook的每一个项目中的动态值,比如 nginx-1.6.3 这个软件包的版本,在其它地方或许会反复使用,那么如果讲此值设置为变量,然后再在其他的playbook中调用,会方便许多。如此一来还方便维护,减少维护的成本。

二、定义变量的方式

  1. 通过命令行:进行变量定义。
  2. 在 play 文件中:进行变量定义。
  3. 通过 Inventory 主机信息文件:进行变量定义。

三、变量的优先级

当变量冲突时,读取优先级顺序为:命令行 > playbook 文件 > Inventory 文件。
例如:

  • 命令行中:age = 11
  • play 文件中:age = 12
  • Inventory 中:age=13
    最终的 age 结果为 11。

一、在 Play 里定义变量

案例 1:定义单个变量

在 Ansible 中,可以在 Play 里定义单个变量。以下是示例代码:

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars:
    pk: wget
  tasks:
    - name: Install package
      yum:
       name: "{{ pk }}"
       state: present

在上述代码中,定义了一个名为 pk 的变量,其值为 wget。在 tasks 部分,通过 yum 模块安装名为 {{ pk }} 的软件包,这里的 {{ pk }} 就是引用了前面定义的变量。

案例 2:定义多个变量(使用列表方式)

可以使用列表的方式定义多个变量,示例如下:

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars:
    pk: 
      - wget
      - tree
      - lrzsz
  tasks:
    - name: Install package
      yum:
       name: "{{ pk }}"
       state: present

这里定义的 pk 变量是一个列表,包含了 wgettreelrzsz 三个值。在 yum 模块中,name: "{{ pk }}" 会尝试安装列表中的所有软件包。

案例 3:定义路径的变量

变量单独调用

变量单独调用时必须加双引号,如下示例:

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars:
    - pk1: 10.0.0.41
    - pk2: backup
  tasks:
    - name: create file
      file:
       path: "{{ pk1 }}"
       state: touch

变量带路径的情况

如果变量带路径,不需要使用双引号。错误示例:

如果是变量开头,就要加双引号

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars:
    - pk1: 10.0.0.41
    - pk2: backup
  tasks:
    - name: create file
      file:
       path: /root/"{{ pk1 }}"
       state: touch

正确写法:

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars:
    - pk1: 10.0.0.41
    - pk2: backup
  tasks:
    - name: create file
      file:
       path: /root/{{ pk1 }}
       state: touch

案例 4:创建名称为 backup_10.0.0.41 的目录

通过组合不同变量来创建具有特定名称的目录,示例如下:

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars:
    - pk1: 10.0.0.41
    - pk2: backup
  tasks:
    - name: create file
      file:
       path: /root/{{ pk2 }}_{{ pk1 }}
       state: directory

上述代码通过组合 pk2pk1 变量的值,在 /root 目录下创建了名为 backup_10.0.0.41 的目录。

二、在 vars_file 文件中定义变量

  • systemctl mask tmp.mount:此命令用于永久卸载tmp挂载。

1. 创建存放变量的文件

使用以下命令创建并查看v.yml文件,在其中定义变量:

[root@ansible ansible]# cat v.yml
pk1: lrzsz
pk2: tree

此文件定义了两个变量pk1pk2,分别赋值为lrzsztree

2. 在 play 中调用变量

创建var.yml文件来调用v.yml中定义的变量:

vars_files: v.yml

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars_files: v.yml
  tasks:
    - name: create file
      file:
       path: /root/{{ pk2 }}_{{ pk1 }}
       state: directory

上述 playbook 中:

  • hosts: backup指定目标主机组为backup
  • vars_files: v.yml加载v.yml文件中的变量。
  • tasks部分定义了一个任务,namecreate file,使用file模块根据变量pk1pk2创建一个目录/root/{{ pk2 }}_{{ pk1 }}

3. 案例:使用列表调用多个变量

变量文件依旧使用v.yml

[root@ansible ansible]# cat v.yml 
pk1: lrzsz
pk2: tree
h1: abaaba
h2: sbsbssbb
h3: heiehiehei
h4:
  - wget
  - tree
  - nginx
  - mariadb

var.yml文件内容如下:

[root@ansible ansible]# cat var.yml
- hosts: backup
  vars_files: v.yml
  tasks:
    - name: yum lrzsz wget
      yum:
       name: 
         - "{{ pk1 }}" 
         - "{{ pk2 }}"
       state: present

此 playbook 通过yum模块,根据变量pk1pk2安装对应的软件包。

三、使用 ansible 的内置变量

Ansible 的内置变量可以通过setup模块来查看。以下是一个使用内置变量的var.yml示例:

#例如
ansible backup -m setup -a 'filter=ansible_hostname'
  from cryptography.exceptions import InvalidSignature
backup | SUCCESS => {
    "ansible_facts": {
        "ansible_hostname": "backup01"
    },
    "changed": false
}


###常用fact变量
ansible_hostanme                  ##主机名
ansible_memtotal_mb               ##内存大小(总计) 单位mb
ansible_processor_vcpus           ##cpu核心总数数量

ansible_default_ipv4.address      ##默认的网卡ip eth0
ansible_distribution              ##默认发行版本名字 Centos Ubuntu Debian.
ansible_distribution_version      ##系统的版本
ansible_date_time.date            ##年-月-日


ansible_all_ipv4_addresses:         ##仅显示ipv4的信息。
ansible_devices:                    ##仅显示磁盘设备信息。
ansible_distribution:               ##显示是什么系统,例:centos,suse等。
ansible_distribution_major_version   ## 显示是系统主版本。
ansible_distribution_version:       ##仅显示系统版本。
ansible_machine:                    ##显示系统类型,例:32位,还是64位。
ansible_eth0:                        ##仅显示eth0的信息。
ansible_hostname:                    ##仅显示主机名。
ansible_kernel:                        ##仅显示内核版本。
ansible_lvm:                        ##显示lvm相关信息。
ansible_memtotal_mb:                   ##显示系统总内存。
ansible_memfree_mb:                    ##显示可用系统内存。
ansible_memory_mb:                    ##详细显示内存情况。
ansible_swaptotal_mb:                ##显示总的swap内存。
ansible_swapfree_mb:                ##显示swap内存的可用内存。
ansible_mounts:                        ##显示系统磁盘挂载情况。
ansible_processor:                    ##显示cpu个数(具体显示每个cpu的型号)。
ansible_processor_vcpus                 ##显示cpu个数(只显示总的个数)。
[root@ansible ansible]# cat var.yml 
- hosts: backup
  tasks:
    - name: Create file 
      file:
       path: /root/{{ ansible_hostname }}_{{ ansible_default_ipv4.address }} 
       state: directory

在这个 playbook 中,使用ansible_hostname(主机名)和ansible_default_ipv4.address(默认 IPv4 地址)这两个内置变量来创建一个目录。

四、在主机清单中定义变量

这种方式不推荐使用。在/etc/ansible/hosts文件中定义变量:

相当于子组,lnmp里的主机可以调用这些变量

[root@ansible ansible]# cat /etc/ansible/hosts
nfs ansible_ssh_host=10.0.0.31

[lnmp]
backup ansible_ssh_host=10.0.0.41
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8
db01 ansible_ssh_host=10.0.0.51

[lnmp:vars]
pk1=wget
pk2=lrzsz

var.yml文件中调用这些变量:

[root@ansible ansible]# cat var.yml 
- hosts: backup
  tasks:
    - name: Create file 
      file:
       path: /root/{{ pk1 }}_{{ pk2 }}
       state: directory

通过在主机清单的[组名:vars]部分定义变量,可在对应的组主机的 playbook 中使用这些变量。

五、官方推荐方式变量

1. 定义主机的变量

在当前目录创建host_vars目录,按照主机清单来定义变量文件。例如,主机清单中有backup ansible_ssh_host=10.0.0.41,则在host_vars下创建一个backup文件,在其中定义变量:

  • 组里能调用变量,是group_vars目录下面创建
  • 单个主机调用变量,是host_vars目录下面创建
  • 就记住group_vars就行,改目录和vars.yml在一级
  • group_vars/all/all.yml所有都能用
[root@Ansible ~/ansible]# ll
drwxr-xr-x 2 root root 6 Jan  1 21:45 group_vars
drwxr-xr-x 2 root root 6 Jan  1 21:45 host_vars

[root@Ansible ~/ansible]# cat group_vars/lnmp/lnmp.yml 
dir: sd123


[root@ansible oldboy]# cat host_vars/backup 
pk1: lrzsz
pk2: wget

vars.yml文件中使用这些变量:

[root@ansible oldboy]# cat vars.yml 
- hosts: backup
  tasks:
    - name: Install lrzsz wget
      yum:
        name:
          - "{{ pk1 }}"
          - "{{ pk2 }}"
        state: present

[root@Ansible ~/ansible]# cat var.yml 
- hosts: web01
  tasks: 
    - name: create dir
      file: 
        path: /root/{{ dir }}
        state: touch

2. 定义组的变量

group_vars目录下按照组名定义变量文件。例如,主机清单如下:

[root@ansible oldboy]# cat /etc/ansible/hosts
nfs ansible_ssh_host=10.0.0.31
[lnmp]
backup ansible_ssh_host=10.0.0.41
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8
db01 ansible_ssh_host=10.0.0.51

group_vars/lnmp文件中定义变量:

[root@ansible oldboy]# cat group_vars/lnmp 
name: oldboy
age: 10

vars.yml文件中使用这些变量:

[root@ansible oldboy]# cat vars.yml 
- hosts: web01
  tasks:
    - name: touch file
      file:
        path: /root/{{ name }}_{{ age }} 
        state: touch

3. 对所有的组定义变量

group_vars/all文件中定义变量:

[root@ansible oldboy]# cat group_vars/all 
name: old
age: 11

这个文件中定义的变量可以在所有组的主机中使用。

Ansible 变量注册

一、Ansible 执行命令与结果返回问题

  • Ansible 执行命令有时不直接出结果。它的模块运行后会有返回值,像脚本执行后给的反馈,能让我们知道操作是否成功。但默认这些返回值不显示,把它们存到变量里,通过调用变量名获取,这就是变量注册 。

二、变量注册返回命令详细信息

示例 1:列出 /root 目录详细信息

  1. 创建 playbook 文件 re.yml
[root@ansible oldboy]# cat re.yml
- hosts: web01
  tasks:
    - name: list /root
      command: ls -l
  1. 使用变量注册获取 ls -l 详细信息
    创建 playbook 文件 li.yml
[root@ansible oldboy]# cat li.yml
- hosts: web01
  tasks:
    - name:  list root
      command: ls -l
      register: ng_re


    - name: print ng_re env
      debug:
        msg: "{{ ng_re }}"

上述代码中,通过 register: ng_rels -l 命令的执行结果注册到变量 ng_re 中,然后使用 debug 模块输出该变量信息。

三、变量注册返回 nginx 检查结果

示例 2:检查 Nginx 配置并返回结果

  1. 创建 playbook 文件 re.yml
[root@ansible oldboy]# cat re.yml
- hosts: web01
  tasks:
    - name: Check Nginx Config
      command: nginx -t
  1. 使用变量注册获取 nginx 检查结果
    同样使用 re.yml 文件
[root@ansible oldboy]# cat re.yml
- hosts: web01
  tasks:
    - name: Check Nginx Config
      command: nginx -t
      register: ng_re


    - name: print ng_re env
      debug:
        msg: "{{ ng_re }}"

这里将 nginx -t 命令的执行结果注册到变量 ng_re 中,并通过 debug 模块输出。

四、获取子集的值

示例 3:获取 nginx 检查结果的特定子集

不带子集正常输出结果:

[root@Ansible ~/ansible]# ansible-playbook  var.yml 

TASK [nginx -t] ********************************************************************************************************************************************************************
changed: [web01]

TASK [preint ls_l env] *************************************************************************************************************************************************************
ok: [web01] => {
    "msg": {
        "changed": true,
        "cmd": [
            "nginx",
            "-t"
        ],
        "delta": "0:00:00.006205",
        "end": "2025-01-02 09:19:42.364234",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2025-01-02 09:19:42.358029",
        "stderr": "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf test is successful",
        "stderr_lines": [
            "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
            "nginx: configuration file /etc/nginx/nginx.conf test is successful"
        ],
        "stdout": "",
        "stdout_lines": []
    }
}

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

[root@Ansible ~/ansible]# 

带上子集 .stderr_lines 的结果:

[root@ansible oldboy]# cat re.yml
- hosts: web01
  tasks:
    - name: Check Nginx Config
      command: nginx -t
      register: ng_re


    - name: print ng_re env
      debug:
        msg: "{{ ng_re.stderr_lines }}"

此例中,通过 ng_re.stderr_lines 获取 ng_re 变量中的 stderr_lines 子集信息并输出。

TASK [preint ls_l env] *************************************************************************************************************************************************************
ok: [web01] => {
    "msg": [
        "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
        "nginx: configuration file /etc/nginx/nginx.conf test is successful"
    ]
}

五、查看内置变量

示例 4:查看 Ansible 内置变量

[root@ansible oldboy]# cat re.yml
- hosts: web01
  tasks:
    - name: Check Nginx Config
      command: nginx -t
      register: ng_re


    - name: print ansible_kernel env
      debug:
        msg: "{{ ansible_kernel }}"

上述代码展示了如何查看 Ansible 内置变量 ansible_kernel,输出系统内核信息。

六、官方推荐写法

示例 5:获取变量特定属性的官方推荐写法

[root@ansible oldboy]# cat re.yml
- hosts: web01
  tasks:
    - name: Check Nginx Config
      command: nginx -t
      register: ng_re


    - name: print ng_re env
      debug:
        msg: "{{ ng_re['rc'] }}" 等同于 "{{ ng_re.rc }}"

这里展示了获取变量 ng_rerc 属性的两种写法,官方推荐的使用方括号 [] 的写法与使用点号 . 的写法是等效的。

Ansible 中 when 判断

when判断案例

案例 1:在特定主机(web01)上安装 wget

  • 需求:对lnmp组操作,仅在web01服务器上安装wget命令。
  • playbook 内容
[root@ansible oldboy]# cat w.yml
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: absent
      when: ansible_hostname == "web01"

使用 == 精确匹配

案例 2:在特定 IP 地址的主机上安装 wget

  • 需求:只在 IP 地址是10.0.0.8的服务器上安装wget命令。
  • playbook 内容
[root@ansible oldboy]# cat w.yml
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ansible_default_ipv4.address == "10.0.0.8"

案例 3:在满足 IP 和主机名条件的主机上安装 wget

  • 需求:在 IP 地址是10.0.0.7且主机名是web01的服务器上安装wget
  • playbook 内容
[root@ansible oldboy]# cat w.yml
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: 
        - ansible_default_ipv4.address == "10.0.0.7"
        - ansible_hostname == "web01"

案例 4:在满足 IP 或主机名条件的主机上安装 wget

  • 需求:在 IP 地址是10.0.0.7或者主机名称是web02的服务器上安装wget
  • playbook 内容
[root@ansible oldboy]# cat w.yml
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ( ansible_default_ipv4.address == "10.0.0.7" ) or ( ansible_hostname == "web02" )

其他判断字符 search 的使用

  • 需求:对lnmp组内主机,当主机名包含web时安装wgetwhen: ansible_hostname is search “web”搜索
  • playbook 内容
[root@ansible oldboy]# cat w.yml
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ansible_hostname is search "web"

综合案例:安装、配置、检测并根据结果重启 Nginx

需求

  1. 安装nginx
  2. 配置nginx
  3. 检测nginx配置文件,通过变量注册接收结果。
  4. 重启nginx,通过when判断,若nginx配置文件正确则重启,错误不重启。

playbook 内容

[root@ansible ansible]# cat nginx.yml
- hosts: web02
  tasks:
    - name: Nginx Repo 
      yum_repository:
        name: nginx
        description: Nginx YUM repo
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes

    - name: create group www
      group:
        name: www
        gid: 666

    - name: Create www user
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: Install Nginx Server
      yum:
        name: nginx
        state: present

    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/

    - name: check nginx conf
      shell: nginx -t
      ignore_errors: yes
      register: ng_re

    - name: Start Nginx Server
      systemd:
        name: nginx
        state: restarted
        enabled: yes
      when: ng_re.stderr_lines is search "ok"

notify监控handlers触发

一、目的

实现对 Nginx 服务器配置文件变化的监控,当配置文件发生变化时,触发相应的 handlers 来重启 Nginx 服务器。

二、配置

总体配置:

[root@ansible ansible]# cat nginx.yml
- hosts: web02
  tasks:
    - name: Nginx Repo 
      yum_repository:
        name: nginx
        description: Nginx YUM repo
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes


    - name: Install Nginx Server
      yum:
        name: nginx
        state: present

    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/
      notify: Restart Nginx Server        # 监控nginx配置文件是否发生变化 如果一致不触发handlers,如果发生变化则触发handlers进行重启动作

    - name: check nginx conf
      shell: nginx -t
      ignore_errors: yes
      register: ng_re



    - name: create group www
      group:
        name: www
        gid: 666

    - name: Create www user
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

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

  handlers:
    - name: Restart Nginx Server        # 必须和notify后的名称一致
      systemd:
        name: nginx
        state: restarted
      when: ng_re.stderr_lines is search "ok"

notify说明

- name: Configure Nginx Server
  copy:
    src: nginx.conf
    dest: /etc/nginx/
  notify: Restart Nginx Server

handlers:
  - name: Restart Nginx Server
    systemd:
      name: nginx
      state: restarted
    when: ng_re.stderr_lines is search "ok"
  • 通知机制notify: Restart Nginx Server 表示当此任务执行且 nginx.conf 文件内容发生变化(即源文件与目标文件不同时),会触发名为 Restart Nginx Server 的 handlers。

handlers说明

- name: Configure Nginx Server
  copy:
    src: nginx.conf
    dest: /etc/nginx/
  notify: Restart Nginx Server

handlers:
  - name: Restart Nginx Server
    systemd:
      name: nginx
      state: restarted
    when: ng_re.stderr_lines is search "ok"
  • handlers 名称Restart Nginx Server,此名称必须与 notify 中指定的名称完全一致,以便在接收到通知时能够正确触发。
  • 条件判断when: ng_re.stderr_lines is search "ok" 是一个条件语句。它表示只有当变量 ng_restderr_lines 中包含 “ok” 时,才会执行重启 Nginx 服务的操作。ng_re 是之前通过 nginx -t 命令检查 Nginx 配置文件语法时注册的变量,通过这种方式确保只有在配置文件语法检查通过的情况下才重启 Nginx 服务,避免因配置错误导致服务无法正常启动。

总结

上述配置通过 notifyhandlers 的配合,实现了对 Nginx 配置文件变化的监控以及在必要时重启 Nginx 服务的功能,并且通过条件判断保证了重启操作是在配置文件语法正确的前提下进行,有助于提高 Nginx 服务器运行的稳定性和可靠性。

综合案例nfs重构

  • 重构nfs,并且web服务器自动挂载
1.定义主机清单
[root@ansible ~]# cat /etc/ansible/hosts
[lnmp]
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8
nfs ansible_ssh_host=10.0.0.31

2.配置playbook
[root@ansible oldboy]# cat nfs.yml
- hosts: lnmp
  vars:
    dir: /data/wp
  tasks:
    - name: Install nfs-utils
      yum:
        name: nfs-utils
        state: present

    - name: Configure nfs Server
      copy:
        src: exports
        dest: /etc/
      notify: Restart nfs Server
      when: ansible_hostname == "nfs"

    - name: create Group www
      group:
        name: www
        gid: 666

    - name: Create www User
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: Create "{{ dir }}"
      file:
        path: "{{ dir }}"
        state: directory
        owner: www
        group: www

    - name: Start nfs Server
      systemd:
        name: nfs
        state: started
        enabled: yes
       when: ansible_hostname == "nfs"
       
    - name: web mount
      mount:
        src: 172.16.1.31:{{ dir }}
        path: /mnt
        fstype: nfs
        state: mounted
      when: ansible_hostname is search "web"


  handlers:
    - name: Restart nfs Server
      systemd:
        name: nfs
        state: restarted

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇