Linux架构27 Ansible变量, 定义变量的方式, 变量注册, facts缓存(本地缓存策略)

Ansible变量

一、变量概述

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

二、定义变量的方式

1.通过命令行进行变量定义
2.在play文件中进行变量定义
3.通过Inventory主机信息文件中进行变量定义
4.通过vars_files定义变量
5.通过host_vars和group_vars定义变量

如果在定义变量时,变量冲突了
在上述的三个地方分别设置了:
    1.命令行中:age=11
    2.play文件中:age=12
    3.Inventory中:age=13
    那么,最终的age结果一定是11
    变量的读取优先级为:命令行 > playbook文件 > Inventory文件
    
#注意:变量命名,应该由字母、数字、下划线组成,必须以字母开头

 

1.在playbook文件中进行变量定义

1)方式一:在模块下定义变量

- name: Install LNMP
  yum:
      name: "{{ packages }}"
  vars:
      packages:
        - nginx
        - php
        - mariadb-server

2)方式二:在hosts下面直接定义变量

[root@m01 base]# vim install.yml
- hosts: web_group
  vars:
    package:
      - httpd
      - mariadb-server
      - MySQL-python
      - php
      - nginx
  tasks:
    - name: Install Server
      yum:
        name: "{{ package }}"

3)方式三:在hosts下面直接定义多个变量

[root@m01 base]# vim install.yml
- hosts: web_group
  vars:
    web:
      - httpd
      - nginx
    db:
      - mariadb-server
      - MySQL-python
      
  tasks:
    - name: Install Server
      yum:
        name: "{{ web }}"
        
    - name: Install DB Server
      yum:
        name: "{{ db }}"

 

2.通过vars_files定义变量

刚才我们学到在playbook中使用vars定义变量,有一个缺陷,就是其他的playbook无法使用该变量。

所以我们可以采取第二种定义变量的方式,在vars_file中定义变量。

#1.配置变量文件
[root@m01 base]# vim vars.yml
web_server: nginx
db_server: mariadb-server

#2.调用变量文件再使用变量
[root@m01 base]# vim host.yml
- hosts: db_group
  vars_files: /project/base/vars.yml
  tasks:
    - name: Install Mariadb Server
      yum:
        name: "{{ db_server }}"

#3.定义多个变量文件
[root@m01 base]# vim host.yml
- hosts: db_group
  vars_files: 
      - /project/base/vars.yml
      - /project/base/vars2.yml
  tasks:
    - name: Install Mariadb Server
      yum:
        name: "{{ nginx }}"

 

3.直接使用内置变量

[root@m01 ~]# ansible "web01" -m setup    #setup模块,获取主机信息(看内置变量)
web01 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.0.7", 
            "172.16.1.7"
        ], 
    ...

# ansible_all_ipv4_addresses就是内置变量,查看内置变量
[root@m01 ~]# ansible "web01" -m setup -a 'filter=ansible_all_ipv4_addresses'
[root@m01 ~]# ansible "web01" -m setup -a 'filter=ansible_default_ipv4'

#直接使用内置变量
[root@m01 ~]# vim mkdir.yml
- hosts: web03
  tasks:
    - name: Create DIR
      file:
        path: /tmp/{{ ansible_default_ipv4['address'] }}#路径下变量可以不加引号,里面也可以.address
        state: directory

[root@m01 ~]# ansible-playbook mkdir.yml
[root@web03 tmp]# ls
10.0.0.9

#可以把内置参数写在vars_file中,也可以定义变量再使用
[root@m01 ~]# vim mkdir.yml
- hosts: web03
  vars:
    - remote_ip: "{{ ansible_default_ipv4['address'] }}"
  tasks:
    - name: Create IP DIR
      file:
        path: /tmp/{{ remote_ip }}
        state: directory
        
#实例
[root@m01 ~]# vim mkdir.yml
- hosts: web_group
  tasks:
    - name: Create Backup DIR
      file:
        path: /backup/{{ ansible_fqdn }}_{{ ansible_default_ipv4['address'] }}_{{ ansible_date_time.date }}    #ansible_fqdn:主机名
        state: directory

[root@m01 ~]# ansible-playbook mkdir.yml
[root@web01 backup]# ls
web01_10.0.0.7_2024-03-27
[root@web02 backup]# ls
web02_10.0.0.8_2024-03-27
[root@ubuntu ~]# cat facts-v1.yaml 
--- #get facts
- hosts: rocky
 gather_facts: yes
 tasks:
   - name: show-facts
     debug: msg={{ ansible_facts }}
   - name: show-facts-hostname
     debug: msg={{ ansible_hostname }}
   - name: show-facts-ipv4-A
     debug: msg={{ ansible_facts["eth0"]["ipv4"]["address"] }}--{{ 
ansible_facts.eth0.ipv4.address }}
   - name: show-facts-ipv4-B
     debug: msg={{ ansible_eth0["ipv4"]["address"] }}--{{ 
ansible_eth0.ipv4.address }}
   - name: show-facts-ipv4-C
     debug: msg={{ ansible_default_ipv4["address"] }}--{{ 
ansible_default_ipv4.address }}

#分组内的主机网卡名称要保持一致
[root@ubuntu ~]# ansible-playbook facts-v1.yaml

facts 中所有可用变量请参考官方文档
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_vars_facts.html

 

4.在Inventory主机清单中进行变量定义

#1.配置主机清单
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
web01 ansible_ssh_pass='admin123'
web02 ansible_ssh_pass='admin123'

[db_group]
db01 ansible_ssh_pass='admin123'
db02 ansible_ssh_pass='admin123'
db03 ansible_ssh_pass='admin123'

[web_group:vars]    #对web_group组定义变量
web_server=nginx

#[all:vars] all表示对所有都生效
#var1=all-var1
------------------------------------------ #2.调用变量 [root@m01 base]# vim install.yml - hosts: web_group tasks: - name: Create WEB Dir file: path: /tmp/{{ web_server }} state: directory #检查结果 [root@m01 base]# ansible-playbook install.yml [root@web01 tmp]# ls nginx ------------------------------------------ #3.对整合组定义变量 [root@m01 ~]# vim /etc/ansible/hosts [web_group] web01 ansible_ssh_pass='admin123' web02 ansible_ssh_pass='admin123' [db_group] db01 ansible_ssh_pass='admin123' db02 ansible_ssh_pass='admin123' db03 ansible_ssh_pass='admin123' [web_group:vars] web_server=nginx #优先级高于整合组的优先级 [nfs_client:children] #设置整合组 db_group web_group [nfs_client:vars] #对整合组定义变量 web_server=http ------------------------------------------ #4.调用变量 [root@m01 base]# vim mkdir.yml - hosts: nfs_client tasks: - name: Create Backup DIR file: path: /tmp/{{ web_server }} state: directory ------------------------------------------ #查看创建目录 [root@m01 base]# ansible 'all' -m shell -a 'ls /tmp' #注意: 主机组定义的变量优先级比整合组调用的变量优先级高 先读取整合组的变量,后读取组的变量,则组的变量将覆盖整合组的变量

 

5.通过host_vars和group_vars定义变量

之前的几种变量定义都不是很好用,比较好用的是在Ansible项目目录下创建两个变量目录:
host_vars
group_vars
切记,目录名字一定要一致,不能做任何修改(ansible会到yml同级目录下去找这个名字,不需要调用)

1)主机组定义变量

#创建组变量的目录,不能改名字
[root@m01 base]# mkdir group_vars

#目录下的名字要与主机清单里面组名相同
[root@m01 base]# vim group_vars/web_group
web_server: http

#调用变量
[root@m01 base]# vi mkdir.yml
- hosts: web_group    # 会去yml同级目录下group_vars里找web_group
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory

2)主机定义变量

#创建主机变量的目录,不能改名字
[root@m01 base]# mkdir host_vars

#目录下的名字要与主机清单里面主机名相同
[root@m01 base]# vim host_vars/db01
web_server: host_vars

#调用变量
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
#注意:
    主机组定义的变量优先级比整合组调用的变量优先级高,主机定义的变量优先级比主机组定义的变量优先级高

 

6.通过命令行进行变量定义(使用--extra-vars或者-e设置变量)

[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
        
#命令行指定变量的值
[root@m01 base]# ansible-playbook mkdir.yml -e "web_server=commond"

#远端查看文件
[root@m01 base]# ansible 'all' -m shell -a 'ls /tmp'

#指定多个变量
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
        
    - name: Create db DIR
      file:
        path: /tmp/{{ db_server }}
        state: directory
        
[root@m01 base]# ansible-playbook mkdir.yml -e "web_server=commond" -e "db_server=mysql"
#多个变量一次定义
[root@ubuntu ~]# ansible-playbook -e "uname=tom age=18 gender=M" var1.yaml

#从文件中读取
[root@ubuntu ~]# cat var.txt 
uname: jerry
age: 20
gender: F

#文件前面要加 @
[root@ubuntu ~]# ansible-playbook -e "@/root/var.txt" var1.yaml 
[root@ubuntu ~]# ansible-playbook -e "@./var.txt" var1.yaml 

 

7.变量引用优先级测试

#配置playbook变量
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  vars:
    web_server: playbook_vars
  vars_files:
    - ./vars_file.yml
  tasks:
    - name: Create Backup DIR
      file:
        path: /opt/{{ web_server }}
        state: directory
        
#配置var_file变量
[root@m01 base]# vim var_file.yml
web_server: vars_files

#主机清单定义变量
[root@m01 base]# vim /etc/ansible/hosts
[web_group:vars]
web_server=inventory_vars

#host_vars定义变量
[root@m01 base]# vim host_vars/web01
web_server: host_vars

#group_vars定义变量
[root@m01 base]# vim group_var/web_group
web_server: group_vars

#命令行变量
[root@m01 base]# ansible-playbook mkdir.yml -e "web_server=command"

#测试后优先级结果:
命令行 > var_files > playbook_vars > host_vars > group_vars配置组变量 > group_vars配置整合组变量 > 主机清单定义组变量 > 主机清单定义整合组变量

 

8.层级定义变量 (很少这么用)

[root@m01 ~]# vim vars_file.yml
lamp:
  framework:
    web_package: httpd
    db_package: mariadb-server
    php_package: php
    
lnmp:
  framework:
    web_package: nginx
    db_package: mysql
    php_package: php
    
lnmt:
  framework:
    web_package: nginx
    db_package: mysql
    php_package: tomcat
    
#编辑playbook文件
[root@m01 ~]# vim test.yml
- hosts: web_group
  vars_files: ./vars_file.yml
  tasks:
    - name: Install LAMP httpd
      yum:
        name: "{{ lamp.framework.web_package }}"    #不能写lamp.framework,不认

    - name: Install LAMP mariadb-server
      yum:
        name: "{{ lamp.framework.db_package }}"
        
    - name: Install LAMP php
      yum:
        name: "{{ lamp.framework.php_package }}"
        
#官方推荐写法
[root@m01 ~]# vim test.yml
- hosts: web_group
  vars_files: ./vars_file.yml
  tasks:
    - name: Install LAMP httpd
      yum:
        name: "{{ lamp['framework']['web_package'] }}"

    - name: Install LAMP mariadb-server
      yum:
        name: "{{ lamp['framework']['db_package'] }}"
        
    - name: Install LAMP php
      yum:
        name: "{{ lamp['framework']['php_package'] }}"

 

三、变量注册

当ansible的模块在运行之后,其实都会返回一些result结果,就像是执行脚本,我们有的时候需要脚本给我们一些return返回值,我们才知道,
上一步是否可以执行成功,但是...默认情况下,ansible的result并不会显示出来,所以,我们可以把这些返回值'存储'到变量中,
这样我们就能通过'调用'对应的变量名,从而获取到这些result,这种将模块的返回值,写入到变量中的方法被称为变量注册

1.变量注册配置

#创建目录获取过程
[root@m01 ~]# vim test.yml
- hosts: web01
  tasks:
    - name: Create Dir
      file:
        path: /tmp/{{ ansible_fqdn }}
        state: directory
      register: get_mkdir_status    #register获取上面创建的过程放到自己定义的变量中

    - name: Get register
      debug:    #用于输出内容
        msg: "{{ get_mkdir_status }}"
        
[root@m01 ~]# ansible-playbook test.yml

#查看目录,执行得不到想要的结果
[root@m01 ~]# vim test.yml
- hosts: web01
  tasks:
    - name: List Dir /tmp
      shell: "ls -l /tmp"

#使用变量注册获取想要的结果
[root@m01 ~]# vim test.yml
- hosts: web01
  tasks:
    - name: List Dir /tmp
      shell: "ls -l /tmp"
      register: list_dir

    - name: Get list_dir
      debug:
        msg: "{{ list_dir }}"
        
#只输出我们想要的内容
- hosts: web01
  tasks:
    - name: List Dir /tmp
      shell: "ls -l /tmp"
      register: list_dir

    - name: Get list_dir
      debug:
        msg: "{{ list_dir.stdout_lines }}"
        #msg: "{{ list_dir['stdout_lines'] }}"    #官方写法也可以

2.变量注册一般使用场景(判断)

[root@m01 ~]# vim status.yml
- hosts: web01
  tasks:
    - name: Install Httpd Server
      yum:
        name: httpd

    - name: Check httpd Status
      shell: systemctl is-active httpd
      ignore_errors: yes    #忽略报错(如果不写,返回错误就结束了,不会往下走)
      register: check_httpd

    - name: Http Restart    #返回启动,就重启
      systemd:
        name: httpd
        state: restarted
      when: check_httpd.rc == 0

    - name: Http Start        #返回异常,就启动
      systemc:
        name: httpd
        state: started
      when: check_httpd.rc != 0

 

四、facts缓存

Ansible facts是在被管理主机上通过Ansible自动采集发现的变量。facts包含每台特定的主机信息。比如:
被控端的主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。 setup模块获取的信息都是因为 facts缓存

1.facts使用场景

1.通过facts缓存检查CPU,来生成对应的nginx配置文件
2.通过facts缓存检查主机名,生成不同的zabbix配置文件
3.通过facts缓存检索物理机的内存大小来生成不通的mysql配置文件

综上所述的Ansible facts类似于saltstack中的grains对于做自动化的小伙伴是非常有用的。

2.关闭facts

#如果使用ansible内置变量的话,不能关闭facts缓存
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  gather_facts: false    #跳过gather_facts步骤,速度变快,但是无法获取内置变量
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ ansible_fqdn }}
        state: directory
[root@m01 base]# ansible-playbook mkdir.yml #报错,无法获取ansible_fqdn变量

#如果不使用ansible内置变量的话,关闭facts会提高ansible管理其他机器的速度
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  gather_facts: false    #跳过gather_facts步骤,速度变快,但是无法获取内置变量
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory

3.一般配置

[root@m01 base]# vim redis.yml
bind {{ ansible_default_ipv4['address'] }}

[root@m01 base]# vim conf.yml
- hosts: all
  tasks:
    - name: Config Redis Conf
      template:    #识别内置变量要用template模块,copy模块无法识别
        src: ./redis.conf
        dest: /tmp/

#远端查看
[root@web01 tmp]# cat redis.conf
bind 10.0.0.7

本地缓存策略

 在 ansible-playbook 中,facts 信息收集默认是开启的,如果不需要,则要在 playbook 中显式指定, 关闭后执行性能更好

如果需要收集远程主机的信息,那么合理的配置 facts 信息的本地缓存策略,也能加速性能

[root@ubuntu ~]# cat /etc/ansible/ansible.cfg
[defaults]
gathering = smart|implicit|explicit #facts 策略,默认 smart,新版默认implicit
fact_caching_timeout = 86400 #本地缓存时长,默认86400S
fact_caching = memeory|jsonfile|redis #缓存类型,默认 memory,如果是jsonfile,则需要指定文件路径
fact_caching_connection = /path/to/cachedir #本地缓存路径
#smart 远程主机信息如果有本地缓存,则使用缓存,如果没有,就去抓取,再存到缓存中,下次就直接使用缓存信息 #implicit 不使用缓存,每次都抓取新的 #explicit 不收集主机信息,除非在playbook 中用 gather_facts: yes 显式指定 #fact_caching=memory,表示只在当前有效,下次还是要重新抓取,是默认值,所以如果需要缓存相关内容,需要指定 josnfile 或 redis #fact_caching=redis 时,fact_caching_connection=REDIS_IP:REDIS_PORT:REDIS_DB_NUMBER[:REDIS_PASSWORD] #fact_caching_connection=10.0.0.100:6379:0 #fact_caching_connection=10.0.0.100:6379:0:123456

配置 facts 信息本地缓存

[root@ubuntu ~]# cat /etc/ansible/ansible.cfg
gathering=smart
fact_caching=jsonfile
fact_caching_connection=/tmp/ansible-facts/
fact_caching_timeout=30

[root@ubuntu ~]# cat facts.yaml 
--- #get facts
- hosts: rocky
  tasks:
    - name: show-facts
      debug: msg={{ ansible_hostname }}

[root@ubuntu ~]# ansible-playbook facts.yaml

#缓存了当前主机的相关信息
[root@ubuntu ~]# tree /tmp/ansible-facts/
/tmp/ansible-facts/
├── 10.0.0.150
└── 10.0.0.213
0 directories, 2 files

 

posted @ 2024-03-29 18:03  战斗小人  阅读(178)  评论(0编辑  收藏  举报