以 root 身份使用密码连接到新服务器的简单 ansible 示例

Simple ansible example that connects to new server as root with password

我想提供一个新的 vps。通常这样做的方式:1) 尝试以非根用户身份手动登录,以及 2) 如果失败则执行配置。

但是我无法连接。 我什至不能以 root 身份登录。(我可以从 shell ssh,所以密码是正确的。)

主持人:

 [server]
 42.42.42.42

playbook.yml:

---
- hosts: all
  vars:
    ROOT_PASSWORD: foo
  gather_facts: no
  tasks:
    - name: set root password
      set_fact: ansible_password={{ ROOT_PASSWORD }}
    - name: try login with password
      local_action: "command ssh -q -o BatchMode=yes -o ConnectTimeout=3 root@{{ inventory_hostname }} 'echo ok'"
      ignore_errors: true
      changed_when: false
    # more stuff here...

我尝试了以下方法,但都无法连接:

  1. 我将密码存储在上面的变量中

  2. 我使用 ansible-playbook -k playbook.yml

  3. 提示输入密码
  4. 我把密码移到了库存文件

    [服务器]
    42.42.42.42 ansible_user=root ansible_password=foo

  5. 我添加了 ssh 标志 -o PreferredAuthentications=password 以强制密码验证

但是上面的none连接。我总是得到错误

root@42.42.42.42: Permission denied (publickey,password).

如果我删除 -o BatchMode=yes 然后它会提示我输入密码,然后连接。但这会阻止自动化,我们的想法是在没有用户干预的情况下执行此操作。

我做错了什么?

这是一个新的 vps,还没有任何设置 - 所以我正在寻找 使用 root 和密码连接的剧本的最简单示例。

你很接近。变量是 ansible_ssh_password,而不是 ansible_ssh_pass。名称中带有 _ssh 的变量是旧名称,因此您可以改用 ansible_useransible_password

如果我有这样的库存:

[server]
example ansible_host=192.168.122.148 ansible_user=root ansible_password=secret

然后我可以运行这个命令成功:

$ ansible all -i hosts -m ping
example | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

如果上面的临时命令工作正常,那么 playbook 也应该工作正常。例如,仍然假设上述库存,我可以使用以下剧本:

---
- hosts: all
  gather_facts: false
  tasks:
    - ping:

我可以这样称呼它:

$ ansible-playbook playbook.yml -i hosts
PLAY [all] ***************************************************************************

TASK [ping] **************************************************************************
ok: [example]

PLAY RECAP ***************************************************************************
example                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

...一切正常。

尝试使用 --ask-become-pass

ansible-playbook -k playbook.yml --ask-become-pass

这样就不是硬编码了。

此外,在剧本中您可以调用:

---
- hosts: all
  become: true
  gather_facts: no

到目前为止我看到的所有 SO 答案和博客文章都建议按照我展示的方式进行操作。

但是在这上面花了很多时间之后,我不相信它可以那样工作,所以我不明白为什么总是推荐它。我注意到 ansible 已经多次更改 API,也许这种方法已经过时了!

所以我想出了一个替代方案,使用 sshpass:

主机:

 [server]
 42.42.42.42

playbook.yml:

---
- hosts: all
  vars:
    ROOT_PASSWORD: foo
  gather_facts: no
  tasks:

    - name: try login with password (using out-of-band ssh connection)
      local_action: command sshpass -p {{ ROOT_PASSWORD }} ssh -q -o ConnectTimeout=3 root@{{ inventory_hostname }} 'echo ok'
      ignore_errors: true
      register: exists_user

    - name: ping if above succeeded (using in-band ssh connection)
      remote_user: root
      block:
      - name: set root ssh password
        set_fact:
          ansible_password: "{{ ROOT_PASSWORD }}"
      - name: ping
        ping:
          data: pong
      when: exists_user is success

这只是一个微小的概念证明。

实际用例是尝试与非 root 用户连接,如果失败,则配置服务器。以上就是这样一个剧本的起点。

与@larsks 的优秀替代方案不同,它不假设 python 安装在远程,并在 sshpass.

的协助下执行带外 ssh 连接测试