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

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

server1 在组中它服务器,但我想使用。如果在剧本和 host_vars 中定义了,ansible_connection: local该如何做?ansible_connection

--
- hosts: it_servers
  vars:
    ansible_connection: aws_ssm
  roles:
    - nginx
    - mysql

我的主机变量/server1.yml文件

ansible_connection: local

答案1

问:如果在 Ansible 中的 host_vars 中设置了 playbook var,如何覆盖它?

答:看一下变量优先级. 优先级玩变量是 12。还有 10 种方法可以覆盖玩变量,但它们都不能让您有选择地覆盖单个主机的变量。

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

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

[aws1:vars]
ansible_connection=aws_ssm            # precedence 3.

有很多组合主机变量组变量来实现此场景。但是,如果你在玩变量(优先级 12)您不能再为单个主机覆盖它。


动态变量

可以动态声明变量。例如

ansible_connection: "{{ 'local'
                        if inventory_hostname == 'server1'
                        else
                        'aws_ssm' }}"

这在任何优先级下都有效。但是,由于惰性求值,它非常低效。每次引用时都会求值该变量。


“实例化”动态变量

如果您确实需要使用动态变量,请“实例化”它以避免重复评估。这是什么意思?例如,给定库存(在 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:

剧本

- 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

给出

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

连接按预期工作,但变量ansible_connection不包括在内主机变量. 使用模块设置事实并“实例化”变量,例如

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

给出

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

TASK [debug] *******************************************************
ok: [server1] => 
  msg:
  - local
  - ssh
  - ssh

答案2

您可以将其delegate_to: localhost用于该任务。

答案3

Ansible 确实应用了变量优先级,您可能会用到它。以下是从最低到最高的优先级顺序(最后列出的变量覆盖所有其他变量):

命令行值(例如,-u my_user,这些不是变量)

角色默认值(在 role/defaults/main.yml 中定义) 1

库存文件或脚本组变量 2

库存 group_vars/all 3

剧本 group_vars/all 3

库存组变量/* 3

剧本 group_vars/* 3

库存文件或脚本主机变量 2

库存主机变量/* 3

剧本 host_vars/* 3

主机事实/缓存的 set_facts 4

玩变量

播放 vars_prompt

播放 vars_files

角色变量(在 role/vars/main.yml 中定义)

块变量(仅适用于块中的任务)

任务变量(仅适用于任务)

包含变量

set_facts / 注册变量

role(和 include_role)参数

包括参数

额外变量(例如,-e“user=my_user”)(始终优先)

这里可以更好地解释这一点:https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

相关内容