如果在 Ansible 的 host_vars 中设置了剧本变量,我该如何覆盖它?

bay*_*man 5 ansible

server1 在组it_servers 中,但我想使用ansible_connection: local. 如果ansible_connection在 playbook 和 host_vars 中定义,如何做到这一点?

--
- hosts: it_servers
  vars:
    ansible_connection: aws_ssm
  roles:
    - nginx
    - mysql
Run Code Online (Sandbox Code Playgroud)

我的host_vars/server1.yml文件

ansible_connection: local
Run Code Online (Sandbox Code Playgroud)

Vla*_*tka 6

问:如果在 Ansible 的 host_vars 中设置了剧本变量,如何覆盖它?

答:看看变量优先级play vars的优先级是 12。如何覆盖play vars有 10 多种可能性,但它们都不会让您有选择地覆盖单个主机的变量。

ansible_connection: aws_ssm如果要为单个主机更改它,则必须从剧本中删除 的声明。连接声明的最佳位置是group_vars(优先级 3-7),而覆盖单个主机的 group_vars 的最佳位置是host_vars(优先级 8-10)。例如

shell> cat hosts
[aws1]
server1 ansible_connection=local      # precedence 8.
server2
server3

[aws1:vars]
ansible_connection=aws_ssm            # precedence 3.
Run Code Online (Sandbox Code Playgroud)

有很多host_varsgroup_vars 的组合来实现这个场景。但是,如果您在play vars(优先级 12)中设置了一个变量,您将无法再为单个主机覆盖它。


动态变量

可以动态声明变量。例如

ansible_connection: "{{ 'local'
                        if inventory_hostname == 'server1'
                        else
                        'aws_ssm' }}"
Run Code Online (Sandbox Code Playgroud)

这适用于任何优先级。但是,由于懒惰的评估,它非常低效。每次引用时都会评估该变量。


“实例化”动态变量

如果您确实需要使用动态变量“实例化”它以避免重复评估。这是什么意思?例如,给定清单(在 YAML 中以提高可读性)

shell> cat hosts
all:
  hosts:
    server1:
      ansible_host: localhost
      ansible_python_interpreter: /usr/bin/python3.8
    server2:
      ansible_host: 10.1.0.62
      ansible_user: admin
      ansible_python_interpreter: /usr/local/bin/python3.8
    server3:
      ansible_host: 10.1.0.63
      ansible_user: admin
      ansible_python_interpreter: /usr/local/bin/python3.8
  children:
    servers:
      hosts:
        server1:
        server2:
        server3:
Run Code Online (Sandbox Code Playgroud)

剧本

- hosts: servers
  vars:
    ansible_connection: "{{ 'local'
                            if inventory_hostname == 'server1'
                            else
                            'ssh' }}"
  tasks:
    - debug:
        msg: "{{ ansible_play_hosts|
                 map('extract', hostvars, 'ansible_connection') }}"
      run_once: true
    - debug:
        var: ansible_connection
Run Code Online (Sandbox Code Playgroud)

PLAY [servers] *****************************************************

TASK [Gathering Facts] *********************************************
ok: [server1]
ok: [server2]
ok: [server3]

TASK [debug] *******************************************************
ok: [server1] => 
  msg: '[AnsibleUndefined, AnsibleUndefined, AnsibleUndefined]'

TASK [debug] *******************************************************
ok: [server1] => 
  ansible_connection: local
ok: [server2] => 
  ansible_connection: ssh
ok: [server3] => 
  ansible_connection: ssh
Run Code Online (Sandbox Code Playgroud)

连接按预期工作,但变量ansible_connection不包含在hostvars 中。使用模块set_fact并“实例化”变量,例如

    - set_fact:
        ansible_connection: "{{ ansible_connection }}"
    - debug:
        msg: "{{ ansible_play_hosts|
                 map('extract', hostvars, 'ansible_connection') }}"
      run_once: true
Run Code Online (Sandbox Code Playgroud)

TASK [set_fact] ****************************************************
ok: [server1]
ok: [server2]
ok: [server3]

TASK [debug] *******************************************************
ok: [server1] => 
  msg:
  - local
  - ssh
  - ssh
Run Code Online (Sandbox Code Playgroud)