Ansible的debug模块介绍,fact变量采集和缓存相关操作演示

目录

一.debug模块的使用方法

1.帮助文档给出的示例

2.主要用到的参数

(1)msg:主要用这个参数来指定要输出的信息

(2)var:打印指定的变量,一般是通过register注册了的变量

(3)verbosity:调试级别,默认是0表示全部显示

3.输出信息详解

4.在debug中使用when做条件判断

(1)通过rc的结果做判断

(2)通过是否failed做判断

二.fact变量

1.setup简单用法演示

(1)通过filter进行过滤

(2)--tree将信息输出到指定目录

2.手动设置fact

3.使用set_fact模块定义变量

4.手动采集变量

三.fact缓存

1.json方式

2.redis方式

3.memcached方式基本已弃用


一.debug模块的使用方法

ansible上playbook的debug是一个常用的调试模块,主要用于在playbook执行(调试、引用变量)过程输出一些关键信息,并且可以对这些关键信息进行一定的格式化输出和条件判断

1.帮助文档给出的示例

复制代码
EXAMPLES:
​
# Example that prints the loopback address and gateway for each host
- debug:
    msg: System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}
​
- debug:
    msg: System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}
  when: ansible_default_ipv4.gateway is defined
​
# Example that prints return information from the previous task
- shell: /usr/bin/uptime
  register: result
​
- debug:
    var: result
    verbosity: 2
​
- name: Display all variables/facts known for a host
  debug:
    var: hostvars[inventory_hostname]
    verbosity: 4
​
# Example that prints two lines of messages, but only if there is an environment value set
- debug:
    msg:
    - "Provisioning based on YOUR_KEY which is: {{ lookup('env', 'YOUR_KEY') }}"
    - "These servers were built using the password of '{{ password_used }}'. Please retain this for later use."

2.主要用到的参数

(1)msg:主要用这个参数来指定要输出的信息

演示效果

复制代码
[root@main ~]# cat iduser.yaml 
---
- name: is su exist
  hosts: webservers
  tasks:
    - name: test su
      shell: id su
      register: su
      ignore_errors: yes
    - name: echo it
      debug:
        msg: "用户存在"
   
[root@main ~]# ansible-playbook iduser.yaml 
​
PLAY [is su exist] ******************************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]
​
TASK [test su] **********************************************************************************************************************************
changed: [servera]
​
TASK [echo it] **********************************************************************************************************************************
ok: [servera] => {
    "msg": "用户存在"
}
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

(2)var:打印指定的变量,一般是通过register注册了的变量

演示效果

复制代码
[root@main ~]# cat iduser.yaml 
---
- name: is su exist
  hosts: servera
  tasks:
    - name: test su
      shell: id su
      register: su
      ignore_errors: yes
    - name: echo it
      debug:
        var: su     #打印前面已经注册了的"su"变量
​
[root@main ~]# ansible-playbook iduser.yaml 
​
PLAY [is su exist] ******************************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]
​
TASK [test su] **********************************************************************************************************************************
changed: [servera]
​
TASK [echo it] **********************************************************************************************************************************
ok: [servera] => {
    "su": {
        "changed": true, 
        "cmd": "id su", 
        "delta": "0:00:00.002850", 
        "end": "2023-10-19 14:12:43.406662", 
        "failed": false, 
        "rc": 0, 
        "start": "2023-10-19 14:12:43.403812", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "uid=1000(su) gid=1000(su) groups=1000(su)", 
        "stdout_lines": [
            "uid=1000(su) gid=1000(su) groups=1000(su)"
        ]
    }
}
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

(3)verbosity:调试级别,默认是0表示全部显示

3.输出信息详解

以下面代码段为例:

"su":表示变量,在输出信息中它是一个字典类型

changed:根据此值来判断是否发生了状态改变

cmd:过程中调用的命令

failed:是否运行失败

rc:返回值,为0成功,非0失败或异常

stderr:出现异常时会在这显示错误信息

stderr_lines:以行分割的格式输出错误信息

stdout:运行成功会在此处输出返回结果

stdout_lines:以行分割的格式输出结果

复制代码
ok: [servera] => {
    "su": {
        "changed": true, 
        "cmd": "id su", 
        "delta": "0:00:00.002850", 
        "end": "2023-10-19 14:12:43.406662", 
        "failed": false, 
        "rc": 0, 
        "start": "2023-10-19 14:12:43.403812", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "uid=1000(su) gid=1000(su) groups=1000(su)", 
        "stdout_lines": [
            "uid=1000(su) gid=1000(su) groups=1000(su)"
        ]
    }
}

4.在debug中使用when做条件判断

(1)通过rc的结果做判断

复制代码
[root@main ~]# cat iduser.yaml 
---
- name: is su exist
  hosts: servera
  tasks:
    - name: test su
      shell: id su
      register: su
      ignore_errors: yes
    - name: echo it
      debug:
        msg: "用户存在"
      when: su.rc==0        #当返回值为0时才输出msg

(2)通过是否failed做判断

复制代码
[root@main ~]# cat iduser.yaml 
---
- name: is su exist
  hosts: servera
  tasks:
    - name: test su
      shell: id su
      register: su
      ignore_errors: yes
    - name: echo it
      debug:
        msg: "用户存在"
      #when: su.rc==0
      when: su is not failed      #当su变量的结果不失败时才输出
[root@main ~]# ansible-playbook iduser.yaml 
​
PLAY [is su exist] ******************************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]
​
TASK [test su] **********************************************************************************************************************************
changed: [servera]
​
TASK [echo it] **********************************************************************************************************************************
ok: [servera] => {
    "msg": "用户存在"
}
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
​

二.fact变量

setup用于获取受管节点的详细信息(硬盘、IP、cpu等信息),可以将信息作为变量在playbook中引用,setup依赖fact进行获取信息

复制代码
EXAMPLES:
​
# Display facts from all hosts and store them indexed by I(hostname) at C(/tmp/facts).
# ansible all -m setup --tree /tmp/facts
​
# Display only facts regarding memory found by ansible on all hosts and output them.
# ansible all -m setup -a 'filter=ansible_*_mb'
​
# Display only facts returned by facter.
# ansible all -m setup -a 'filter=facter_*'
​
# Collect only facts returned by facter.
# ansible all -m setup -a 'gather_subset=!all,!any,facter'
​
- name: Collect only facts returned by facter
  setup:
    gather_subset:
      - '!all'
      - '!any'
      - facter

1.setup简单用法演示

(1)命令行通过filter进行过滤

复制代码
[root@main ~]# ansible servera -m setup -a 'filter=ansible_*_ipv4'
servera | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "192.168.2.131", 
            "alias": "ens33", 
            "broadcast": "192.168.2.255", 
            "gateway": "192.168.2.1", 
            "interface": "ens33", 
            "macaddress": "00:0c:29:bc:03:89", 
            "mtu": 1500, 
            "netmask": "255.255.255.0", 
            "network": "192.168.2.0", 
            "type": "ether"
        }, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

(2)--tree将信息输出到指定目录

复制代码
[root@main ~]# ansible servera -m setup -a 'filter=ansible_*_mb' --tree /root/facts
​
[root@main ~]# cat facts/servera 
{"ansible_facts": {"ansible_memfree_mb": 5327, "ansible_memory_mb": {"nocache": {"free": 5510, "used": 338}, "real": {"free": 5327, "total": 5848, "used": 521}, "swap": {"cached": 0, "free": 2047, "total": 2047, "used": 0}}, "ansible_memtotal_mb": 5848, "ansible_swapfree_mb": 2047, "ansible_swaptotal_mb": 2047, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false}

2.手动设置fact

可以为某写主机手动定制fact,称其为本地fact,将管理节点定义好的fact文件传输给需要定制fact的节点,定制的fact默认存放在受管节点的/etc/ansible/facts.d目录下,

**示例:**为server节点自定义一个fact,使用这个fact启动servera上的httpd服务,此示例主要用到三个文件(cus.fact、afact.yaml、useafact.yaml),都放在同一目录下

复制代码
[root@main ~]# cat cus.fact      #在管理节点定义好fact文件
[su]
mypkg=httpd
myser=httpd
state=started
​
[root@main ~]# cat afact.yaml   
#定义yaml文件,在受管节点创建/etc/ansible/facts.d目录,将fact文件拷贝至这个目录
---
- hosts: servera
  vars:
    remote_dir: /etc/ansible/facts.d
    facts_file: cus.fact
  tasks:
    - name: create remote_dir in servera
      file:
        state: directory
        recurse: yes
        path: "{{ remote_dir }}"
    - name: copy local cus.fact
      copy:
        src: "{{ facts_file }}"
        dest: "{{ remote_dir }}"
​
[root@main ~]# ansible servera -m setup -a 'filter="ansible_local"'
#成功在servera上过滤出本地fact
servera | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "cus": {
                "su": {
                    "mypkg": "httpd", 
                    "myser": "httpd", 
                    "state": "started"
                }
            }
        }, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
​
[root@main ~]# cat useafact.yaml   #为servera定义yaml文件引用其下的fact进行启动httpd
---
- hosts: servera
  tasks:
    - name: using servera local fact to start httpd
      service:
        name: "{{ ansible_facts.ansible_local.cus.su.myser }}"
        #引用方式较长(ansible的facts.本地的.fact文件.fact内的字段名)
        state: "{{ ansible_facts.ansible_local.cus.su.state }}"
​
[root@main ~]# ansible-playbook useafact.yaml
​
PLAY [servera] **********************************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]
​
TASK [using servera local fact to start httpd] **************************************************************************************************
changed: [servera]
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
​
[root@main ~]# ansible servera -m shell -a 'systemctl status httpd | grep Active'
#启动成功
servera | CHANGED | rc=0 >>
   Active: active (running) since Thu 2023-10-19 15:15:09 CST; 5s ago

3.使用set_fact模块定义变量

set_fact用于自定义facts,从而通过template或作为变量在playbook中被引用,set_fact定义的变量只能在此playbook中使用有效

复制代码
EXAMPLES:
​
# Example setting host facts using key=value pairs, note that this always creates strings or booleans
- set_fact: one_fact="something" other_fact="{{ local_var }}"
​
# Example setting host facts using complex arguments
- set_fact:
     one_fact: something
     other_fact: "{{ local_var * 2 }}"
     another_fact: "{{ some_registered_var.results | map(attribute='ansible_facts.some_fact') | list }}"
​
# Example setting facts so that they will be persisted in the fact cache
- set_fact:
    one_fact: something
    other_fact: "{{ local_var * 2 }}"
    cacheable: yes
​
# As of Ansible 1.8, Ansible will convert boolean strings ('true', 'false', 'yes', 'no')
# to proper boolean values when using the key=value syntax, however it is still
# recommended that booleans be set using the complex argument style:
- set_fact:
    one_fact: yes
    other_fact: no

**示例:**通过set_fact计算进程使用内存的情况,这个计算结果也可以在playbook中引用

复制代码
[root@main ~]# ansible servera -m setup -a 'filter="ansible_memtotal_mb"'
servera | SUCCESS => {
    "ansible_facts": {
        "ansible_memtotal_mb": 5848,     #先过滤一下看参数是否存在
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
​
[root@main ~]# cat initfree.yaml 
---
- hosts: servera
  tasks:
    - name: cal pool size
      set_fact:      #定义一个变量为这个计算结果
        pool_size: "{{ ansible_memtotal_mb / 2 | int}}"
    - debug:
        var: pool_size  #输出这个变量
​
[root@main ~]# ansible-playbook initfree.yaml
​
PLAY [servera] **********************************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]
​
TASK [cal pool size] ****************************************************************************************************************************
ok: [servera]
​
TASK [debug] ************************************************************************************************************************************
ok: [servera] => {
    "pool_size": "2924.0"
}
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

4.手动采集变量

运行playbook时,ansible会先ssh到受管节点去采集fact,如果收集信息过多过大会影响执行速度和效率,可以选择关闭采集或先关闭采集完成任务再重新采集

复制代码
#显式采集行为
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]

**示例:**上述情况下,我们可以使用gather_facts显式关闭fact采集,然后执行完任务再重新采集facts

复制代码
[root@main ~]# cat nogather.yaml 
---
- hosts: servera
  gather_facts: false
  tasks:
    - name: debug this
      debug: msg="hello"
    - name: wait for 10
      wait_for:
        timeout: 6
    - name: regather facts
      setup:
        gather_subset: all  #参考EXAMPLES
​
[root@main ~]# ansible-playbook nogather.yaml 
​
PLAY [servera] **********************************************************************************************************************************
​
TASK [debug this] *******************************************************************************************************************************
ok: [servera] => {
    "msg": "hello"
}
​
TASK [wait for 10] ******************************************************************************************************************************
ok: [servera]
​
TASK [regather facts] ***************************************************************************************************************************
ok: [servera]
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

三.fact缓存

在playbook中引入fact时可以设置fact缓存,目前以是json、redis、memcached三种方式,以下是需要修改的ansible.cfg的defaults部分参数

  • gathering

是否开启fact支持三个选项:smart(默认采集facts,facts已存在时不采集,即缓存),implicit(默认采集facts,可以使用"gather_facts: false"来禁止采集),explicit(默认不采集,可以使用"gather_facts: true"来假期采集)

  • fact_caching_timeout

缓存时间,秒为单位

  • fact_caching

缓存方式,jsonfile,redis,memcached

  • fact_caching_connection

指定fact缓存的json文件位置,若没有会自动创建

1.json方式

此方式下,ansible会将fact写入控制主机的文件中

复制代码
#在ansible.cfg配置文件的defaults模块加这些参数
gathering=smart
fact_caching_timeout=86400
fact_caching=jsonfile
fact_caching_connection=/root/ansible_fact_cache

示例:

执行一个会采集fact的playbook,查看是否将fact缓存到指定的位置

复制代码
[root@main ~]# cat ansible.cfg 
[defaults]
......
gathering=smart
fact_caching_timeout=86400
fact_caching=jsonfile
fact_caching_connection=/root/ansible_fact_cache
......
​
[root@main ~]# ansible-playbook myhttpd.yaml 
​
PLAY [stop servera httpd] ***********************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [servera]
​
TASK [stop it] **********************************************************************************************************************************
ok: [servera]
​
PLAY [install serverb mod_ssl] ******************************************************************************************************************
​
TASK [Gathering Facts] **************************************************************************************************************************
ok: [serverb]
​
TASK [install it] *******************************************************************************************************************************
ok: [serverb]
​
PLAY RECAP **************************************************************************************************************************************
servera                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
​
[root@main ~]# ll /root/ansible_fact_cache/      #查看
total 56
-rw-r--r-- 1 root root 25052 Oct 19 18:00 servera
-rw-r--r-- 1 root root 25071 Oct 19 18:00 serverb

2.redis方式

需要安装redis服务且保持运行,还需要安装python支持redis的相关包,更改ansible.cfg

复制代码
fact_caching=redis   #指定redis方式
fact_caching_connection=127.0.0.1:6379:0      #指定redis服务设备的IP和端口,使用0号数据库
​
[root@main ~]# yum install -y redis  #安装redis
[root@main ~]# systemctl start redis
[root@main ~]# ps -ef | grep redis
redis      4278      1  0 17:50 ?        00:00:00 /usr/bin/redis-server 127.0.0.1:6379
root       4286   1485  0 17:51 pts/0    00:00:00 grep --color=auto redis
[root@main ~]# systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.
[root@main ~]# python --version
Python 2.7.5
[root@main ~]# yum list | grep python2-redis
python2-redis.noarch                     2.10.6-2.el7                  epel   
[root@main ~]# yum install -y python2-redis.noarch   #安装对应python版本对应的redis支持包
[root@main ~]# ansible-playbook myhttpd.yaml   #再执行一次
[root@main ~]# redis-cli    #进入查看
127.0.0.1:6379> keys *
1) "ansible_factsservera"
2) "ansible_factsserverb"
3) "ansible_cache_keys"
127.0.0.1:6379> type "ansible_cache_keys"
zset
127.0.0.1:6379> type "ansible_factsservera"   #前两个就是采集的facts
string
127.0.0.1:6379> 

3.memcached方式基本已弃用

相关推荐
知我Deja_Vu5 天前
redisCommonHelper.generateCode(“GROUP“),Redis 生成码方法
数据库·redis·缓存
没有bug.的程序员5 天前
电商秒杀系统深度进阶:高并发流量建模、库存零超卖内核与 Redis+MQ 闭环
数据库·redis·缓存·高并发·电商秒杀·流量建模·库存零超卖
troublea5 天前
ThinkPHP3.x高效学习指南
mysql·nginx·缓存
troublea5 天前
ThinkPHP6快速入门指南
数据库·mysql·缓存
梅孔立5 天前
Ansible 100 台服务器一键管控实战 进阶版
服务器·git·ansible
Emotional。5 天前
AI Agent 性能优化和成本控制
人工智能·深度学习·机器学习·缓存·性能优化
jnrjian5 天前
Oracle 共享池 库缓存下的 Library Cache Lock
数据库·缓存·oracle
Anastasiozzzz6 天前
阿亮随手记:MySQL移除查询缓存、子查询优化深分页、自增主键溢出、索引失效
数据库·mysql·缓存
難釋懷6 天前
Redis消息队列-基于Stream的消息队列-消费者组
数据库·redis·缓存
難釋懷6 天前
Redis消息队列-基于Stream的消息队列
数据库·redis·缓存