【问题标题】:Best way to get the IP address of the Ansible control machine获取Ansible控制机IP地址的最佳方法
【发布时间】:2016-01-01 22:20:31
【问题描述】:

我正在使用 Ansible 和 ufw 在我的服务器上设置防火墙。作为ufw 规则的一部分,我希望允许来自 Ansible 控制机器的 SSH,但不允许来自其他任何地方。我的问题是 - 获取控制机器本身的 IP 地址以便我可以将其放入规则中的最佳方法是什么?

我知道我可以使用 facts 来获取我正在运行 playbook 的机器的 IP 地址,但我没有看到任何简单的方法可以为运行 ansible 的机器自动获取它。

如果可能的话,我想避免添加一个新变量来表示它,因为如果它可以自动发现会很好,但如果这是唯一已知的最佳方法,那么我会这样做。

编辑:我发现 this duplicate question 与我的相同,但它也没有得到答复,因此请稍候。

【问题讨论】:

    标签: ansible ansible-facts


    【解决方案1】:
    {{ ansible_env['SSH_CLIENT'].split() | first }}
    

    有效,但您必须从默认用户收集有关连接变量的事实,所以要八点:

    • 在剧本级别设置 «gather_facts: yes» 和 not «become: yes»
    • 更可靠:运行 «setup» 任务(没有 «become: yes» 和在此 «ansible_env» 用法之前 - 在 «pre_tasks» 部分更好)。

    如果你用 «become» 运行 «gather/setup»,您稍后会得到 «一个或多个未定义的变量:'dict object' has no attribute 'SSH_CLIENT'»(这是因为 sudoed «setup» 只能捕获少量变量集)。

    【讨论】:

    • 使用become: no 运行“收集/设置”的关键是让它发挥作用。谢谢!
    【解决方案2】:

    最简单的方法是添加本地连接

    ---
     - name: get my public IP
       ipify_facts: api_url=http://api.ipify.org
       connection: local
    
     - firewalld: rich_rule='rule family=ipv4 source address={{ ipify_public_ip }} accept' permanent=no state=enabled timeout=300
       become: true
    

    【讨论】:

    • 谢谢,用这个方法为fail2ban创建了一个例外。
    【解决方案3】:

    我刚刚破解了这个解决方案,它奏效了。这是您要找的东西吗?

    - debug var="{{hostvars[inventory_hostname]['ansible_env']['SSH_CLIENT'].split(' ')[0]}}"
    

    【讨论】:

    • 我认为这会得到远程主机的IP而不是控制机器的IP。你有没有看到其他的?
    • @Cory 你的问题不清楚,我误解了。更新了解决方案。看看它是否有效。
    • 这似乎不起作用。我收到以下错误:One or more undefined variables: 'dict object' has no attribute 'SSH_CLIENT'。这是在 Ansible 1.9 上。
    • @Cory 你能发布你的剧本吗?
    • 这是我尝试使用此语法失败的版本:gist.github.com/czue/6365bd98d9f35e395d9c
    【解决方案4】:

    在不同的答案中描述的“ipify_facts”方法应该可以工作,如果:

    1. 您的控制主机只有一个接口,或者如果它有多个接口并且用于到达 ipify api_url 的接口与到达您的远程主机的接口相同,-and-
    2. 您的控制主机有一个公共 IP(根本没有使用 NAT),或者您的控制主机在 NAT 内部,但远程主机在外部。

    如果不满足上述任一条件(即,如果您的控制主机有多个接口和/或您的控制主机和远程主机都在 NAT 之后并使用私有地址),那么另一个(尽管稍微复杂一点)的方法是在 Ansible 中复制以下内容:

    $ ip route get 203.0.113.4
    203.0.113.4 via 172.26.232.1 dev enp0s3  src 172.26.232.125
                      cache
    $
    

    这将向您显示用于到达特定目的地 (203.0.113.4) 的接口和源地址 (172.26.232.125)。

    在 Ansible 中实现这一点的一种方法是:

    ---
    - name: Obtain local IP address
      local_action: shell ip route get {{ inventory_hostname }} | awk '{ for (x=1;x<=NF;x++) if ($x=="src") print $(x+1) }'
      register: local_address
      changed_when: false
    
    - name: Print my local address
      debug: msg="Source address towards {{ inventory_hostname }} is {{ local_address.stdout }}"
    

    输出:

    $ ansible-playbook test.yml  -i inventory.txt
    
    PLAY [test] ********************************************************************
    
    TASK [Obtain local IP address] *************************************************
    ok: [203.0.113.4 -> localhost]
    
    TASK [Print my local address] **************************************************
    ok: [203.0.113.4] => {
        "msg": "Source address towards 203.0.113.4 is 172.26.232.125"
    }
    

    如果您有多个可通过不同接口访问的远程主机,这也应该有效。

    如果您的 inventory_hostname 是 DNS 主机名而不是数字 IP 地址,则需要在“shell”操作中执行额外的步骤。

    【讨论】:

      【解决方案5】:
      {{ ansible_env['SSH_CLIENT'].split()[0] }}
      

      【讨论】:

      • 这似乎不起作用。我收到以下错误:One or more undefined variables: 'dict object' has no attribute 'SSH_CLIENT'。这是在 Ansible 1.9 上。
      • 任务是在远程主机上运行还是在本地运行?如果远程,您使用什么交通工具?使用 OpenSSH 时应包含SSH_CLIENT
      • 我相信它在远程主机上运行并且正在使用 SSH(我将如何确认?)。可能我遇到了this issue
      • 错误报告似乎仅限于模板?您可以尝试在这样的调试任务中输出它吗?:- debug: message="{{ ansible_env['SSH_CLIENT'].split()[0] }}"- 不过,我和我的团队从 1.6 到 1.9.4 一直以这种方式在模板中使用它。
      【解决方案6】:
      {{ ansible_env['SSH_CLIENT'].split() | first }}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-10
        • 2010-09-30
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        相关资源
        最近更新 更多