五、Ansible Facts Variables

1、什么是facts

Ansible facts 变量主要用来自动采集,”被控端主机“ 自身的状态信息。

比如:被动端的,主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。

2、facts使用场景

1.通过facts变量检查被控端硬件CPU信息,从而生成 不同的Nginx配置文件。

2.通过facts变量检查被控端内存状态信息,从而生成 不同的memcached的配置文件。

3.通过facts变量检查被控端主机名称信息,从而生成 不同的Zabbix配置文件。

4.通过facts变量检查被控端主机IP地址信息,从而生 成不同的redis配置文件。

5.通过facts变量........

3、facts语法示例

1.通过 facts 获取被控端的主机名与IP地址,然后通过debug 输出;
cat facts.yml
- hosts: webserverss
  tasks:
    - name: Output variables ansible facts
      debug:
        msg: >
          this default IPv4 address "{{ansible_fqdn}}" is "{{ansible_default_ipv6.address}}"
          
2.获取facts变量,可以使用filter过滤特定的关键项
ansible localhost -m setup -a "filter='ansible_default_ipv4'"

3.如果没有使用facts变量需求,可以关闭其功能,加速ansible执行性能;
cat facts.yml
- hosts: web
  gather_facts: no #关闭信息采集
  tasks:

4、案例1-根据主机IP地址生成Redis配置

catredis.yml
- hosts: webservers
  tasks:
    - name: Installed Redis Server
      yum:
        name: redis
        state: present
    - name: Configure Redis Server
      template:
        src: ./redis.conf.j2
        dest: /etc/redis.conf
      notify: Restart Redis Server
    - name: Started Redis Server
      systemd:
        name: redis
        state: started
        enabled: yes
  handlers:
    - name: Restart Redis Server
      systemd:
        name: redis
        state: restarted

# 配置文件进行如下修改
[root@manager ansible_variables]# cat
redis.conf.j2
...
bind 127.0.0.1 {{ ansible_eth1.ipv4.address }}
...

5、案例2-根据主机CPU生成Nginx配置

# (172.16.1.7 1核)、(172.16.1.8 2核)
# ansible_processor_cores: 4 核心数 ( 每颗物理CPU的核心数)
# ansible_processor_count: 2 颗数 (有几个CPU )
# ansible_processor_vcpus: 8 总核心数

cat nginx.yml
- hosts: webservers
  tasks:
    - name: Install Nginx Server
      yum:
        name: nginx
        state: present
    - name: Configure Nginx.conf
      template:
        src: ./nginx.conf.j2
        dest: /tmp/nginx.conf
      notify: Restart Nginx Server
    - name: Started Nginx Server
      systemd:
        name: nginx
        state: started
        enabled: yes
  handlers:
    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted
        
# nginx配置文件内容
cat nginx.conf.j2
user www;
worker_processes {{ ansible_processor_vcpus * 2 }};
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {

worker_connections 1024;
}
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr -$remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    sendfile on;
    tcp_nopush on;
    keepalive_timeout 65;
    gzip on;
    include /etc/nginx/conf.d/*.conf;
}

6、案例3-根据主机内存生成Memcached配置

# (172.16.1.7 1G)、(172.16.1.8 2G)

cat memcached.yml
- hosts: webserver
  tasks:
    - name: Installed Memcached Server
      yum: name=memcached state=present
    - name: Configure Memcached Server
      template: src=./memcached.j2 dest=/etc/sysconfig/memcached
    - name: Service Memcached Server
      service: name=memcached state=started enabled=yes
# memcached配置文件如下
cat memcached.j2
PORT="11211"
USER="memcached"
MAXCONN="1024"
#根据内存状态生成不同的配置(支持+-*/运算)
CACHESIZE="{{ ansible_memtotal_mb //2 }}"
# 总内存/2
# CACHESIZE="{{ ansible_memtotal_mb * 0.8 }}" # 使用内存80%
OPTIONS=""

7、案例4-根据主机名称生成zabbix配置

1)准备两台物理内存不一样的主机
172.16.1.7 web01
172.16.1.8 web02
2)编写zabbix服务playbook
cat zabbix_agent.yml
- hosts: all
  tasks:
    - name: Installed ZabbixAgent
      yum:
        name: https://mirror.tuna.tsinghua.edu.cn/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.0-2.el7.x86_66.rpm
        state: present
    - name: Configure ZabbixAgent
      template:
        src: ./zabbix_agentd.conf.j2
        dest: /etc/zabbix/zabbix_agentd.conf
      notify: Restart ZabbixAgent
    - name: Started ZabbixAgent
      systemd:
        name: zabbix-agent
        state: started
        enabled: yes
  handlers:
    - name: Restart ZabbixAgent
      systemd:
        name: zabbix-agent
        state: restarted
3)zabbix-agent配置文件
[root@manager ansible_variables]# grep
"^Hostname" zabbix_agentd.conf.j2
Hostname={{ ansible_hostname }}

8、案例6-使用facts批量修改主机名称

# 面试题:批量修改200台主机名称-解法2
# 不能使用shell模块
# web_7 web_8
cat te.yaml
- hosts: all
  tasks:
    - name: # 首先打印facts变量的内容
      debug: msg={{ ansible_default_ipv6.address }}
    - name: # 方式1 使用hostname模块将主机名修改为web_{ip}
      hostname: name=web_{{ ansible_default_ipv6.address }}
    - name: # 方式2 获取facts变量,然后提取IP地址,以.结尾的最后一列
      hostname: name=web_{{ ansible_default_ipv6.address.split('.')[-1] }}

9、facts变量性能优化

1 关闭facts采集加速执行-方式1
编写 TASK 任务 sleep10 秒,针对 15 台机器同时执行,需要消耗的时间大概是 1m56.980s
cat ansible_facts.yml
- hosts: all
  tasks:
    - name: sleep 10
      command: sleep 10
使用 gather_facts: no 关闭 facts信息采集,发现仅花费了 0m38.164s ,整个速度提升了3倍;
cat ansible_facts.yml
- hosts: all
  gather_facts: no
  tasks:
    - name: sleep 10
      command: sleep 10
      
2 缓存facts变量加速执行-方式2
当我们使用 gather_facts: no 关闭 facts,确实能加速 Ansible 执行,但是有时候又需要使用 facts 中的内容,还希望执行的速度快一点,这时候可以设置facts 的缓存;
yum install python-pip
pip install redis

cat /etc/ansible/ansible.cfg
[defaults]
# smart 表示默认收集 facts,但 facts 已有的情况下不会收集,即使用缓存 facts
# implicit 表示默认收集 facts,要禁止收集,必须使用 gather_facts: False;
# explicit 则表示默认不收集,要显式收集,必须使用
gather_facts: Ture。
gathering = smart #在使用 facts 缓存时设置为smart
fact_caching_timeout = 86400
fact_caching = redis
fact_caching_connection =172.16.1.41:6379:1
# 若 redis 设置了密码
# fact_caching_connection =172.16.1.41:6379:1:passwd

编写 Playbook 测试;
cat ansible_facts.yml -f 20
- hosts: all
  gather_facts: no
  tasks:
    - name: sleep 10
      command: sleep 10

测试结果如下:
执行第一次花费了 1m49.881s 因为第一次需要将facts 信息缓存至Redis
执行第二次花费了 0m38.130s 可以看出使用Redis 缓存 facts变量,整体执行时间提高了3倍