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文件 #注意:变量命名,应该由字母、数字、下划线组成,必须以字母开头
- name: Install LNMP yum: name: "{{ packages }}" vars: packages: - nginx - php - mariadb-server
[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 }}"
[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 }}"
刚才我们学到在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 }}"
[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
#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' #注意: 主机组定义的变量优先级比整合组调用的变量优先级高 先读取整合组的变量,后读取组的变量,则组的变量将覆盖整合组的变量
之前的几种变量定义都不是很好用,比较好用的是在Ansible项目目录下创建两个变量目录:
host_vars
group_vars
切记,目录名字一定要一致,不能做任何修改(ansible会到yml同级目录下去找这个名字,不需要调用)
#创建组变量的目录,不能改名字 [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
#创建主机变量的目录,不能改名字 [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
#注意: 主机组定义的变量优先级比整合组调用的变量优先级高,主机定义的变量优先级比主机组定义的变量优先级高
[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
#配置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配置整合组变量 > 主机清单定义组变量 > 主机清单定义整合组变量
[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,这种将模块的返回值,写入到变量中的方法被称为变量注册
#创建目录获取过程 [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'] }}" #官方写法也可以
[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
Ansible facts是在被管理主机上通过Ansible自动采集发现的变量。facts包含每台特定的主机信息。比如:
被控端的主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。
setup模块获取的信息都是因为 facts缓存
1.通过facts缓存检查CPU,来生成对应的nginx配置文件 2.通过facts缓存检查主机名,生成不同的zabbix配置文件 3.通过facts缓存检索物理机的内存大小来生成不通的mysql配置文件 综上所述的Ansible facts类似于saltstack中的grains对于做自动化的小伙伴是非常有用的。
#如果使用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
[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