解决方案 1:回答问题

解决方案 1:回答问题

我是 ansible 的新手,正在尝试自动化一些步骤。

此任务第一次运行很顺利。

# Copy Root ssh keys within all devices
- hosts: etall
  tasks:
    - name: ssh keygen
      command: ssh-keygen -t rsa -f /root/.ssh/id_rsa -q -P ""

第二次收集事实后就挂了。设置ANSIBLE_DEBUG=1显示步骤挂起在:

16584 1554867575.39541: _low_level_execute_command(): executing: /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1554867574.524454-229535370546451/AnsiballZ_command.py && sleep 0'

在客户端计算机上进行跟踪时:

/usr/bin/python -m trace --trace /root/.ansible/tmp/ansible-tmp-1554873279.0459487-106888464136363/AnsiballZ_command.py

<---output snippet---->
AnsiballZ_command.py(16):     import base64
 --- modulename: trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)
Traceback (most recent call last):
  File "/usr/lib64/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib64/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/lib64/python2.7/trace.py", line 819, in <module>
    main()
  File "/usr/lib64/python2.7/trace.py", line 807, in main
    t.runctx(code, globs, globs)
  File "/usr/lib64/python2.7/trace.py", line 513, in runctx
    exec cmd in globals, locals
  File "/root/.ansible/tmp/ansible-tmp-1554873279.0459487-106888464136363/AnsiballZ_command.py", line 113, in <module>
    _ansiballz_main()
  File "/root/.ansible/tmp/ansible-tmp-1554873279.0459487-106888464136363/AnsiballZ_command.py", line 16, in _ansiballz_main
    import base64
ImportError: No module named base64

import base64可以/usr/bin/python

首次运行时这不是问题。在客户端机器上重新安装操作系统后也可以正常工作。

版本:

ansible 2.7.6
  config file = /user/user1/plays/ansible.cfg
  configured module search path = ['/user/user1/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /user/user1/p363/lib/python3.6/site-packages/ansible-2.7.6-py3.6.egg/ansible
  executable location = /user/user1/p363/bin/ansible
  python version = 3.6.3 (default, Jul  8 2018, 21:13:48) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]

客户端机器中的 Python 版本是 2.7.5

配置

ansible-config dump --only-changed
DEFAULT_FORKS(/user/user1/plays/ansible.cfg) = 1
DEFAULT_HOST_LIST(/user/user1/plays/ansible.cfg) = ['/user/user1/plays/hosts.ini']
DEFAULT_LOG_PATH(/user/user1/plays/ansible.cfg) = /user/user1/plays/ansible.log
DEFAULT_ROLES_PATH(/user/user1/plays/ansible.cfg) = ['/user/user1/plays/hosts']
RETRY_FILES_ENABLED(/user/user1/plays/ansible.cfg) = False

环境: ansible 主控

$ cat /etc/os-release
NAME="Red Hat Enterprise Linux Workstation"
VERSION="7.5 (Maipo)"
ID="rhel"
ID_LIKE="fedora"
VARIANT="Workstation"
VARIANT_ID="workstation"
VERSION_ID="7.5"
PRETTY_NAME="Red Hat Enterprise Linux"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:redhat:enterprise_linux:7.5:GA:workstation"
HOME_URL="https://www.redhat.com/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
REDHAT_BUGZILLA_PRODUCT_VERSION=7.5
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="7.5"

ansible 客户端

# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

剧本:

# Copy Root ssh keys within all machines
- hosts: etall
  tasks:
    - name: ssh keygen
      command: ssh-keygen -t rsa -f /root/.ssh/id_rsa -q -P "" 

    - name: Fetch keyfile
      fetch:
        src: "~/.ssh/id_rsa.pub"
        dest: "buffer/{{ ansible_hostname }}-id_rsa.pub"
        flat: yes

    - name: Copy keyfile to destination
      authorized_key:
        user: root
        state: present
        key: "{{ lookup('file','buffer/{{ item }}-id_rsa.pub') }}"
      when: item != ansible_hostname
      with_items:
        - "{{ groups['etall'] }}"

    - name: ssh keyscan
      shell: ssh-keyscan {{ item }} >> /root/.ssh/known_hosts
      when: item != ansible_hostname
      with_items:
        - "{{ groups['etall'] }}"

收集事实后的详细输出片段:

TASK [ssh keygen] *************************************************************************************************************************************************************************************************
task path: /user/user1/plays/auth_keys.yml:4
<linux-user5> ESTABLISH SSH CONNECTION FOR USER: root
<linux-user5> SSH: EXEC sshpass -d11 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/user/user1/.ansible/cp/0969431db6 linux-user5 '/bin/sh -c '"'"'echo ~root && sleep 0'"'"''
<linux-user5> (0, b'/root\n', b'')
<linux-user5> ESTABLISH SSH CONNECTION FOR USER: root
<linux-user5> SSH: EXEC sshpass -d11 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/user/user1/.ansible/cp/0969431db6 linux-user5 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890 `" && echo ansible-tmp-1554878730.6050982-46540706020890="` echo /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890 `" ) && sleep 0'"'"''
<linux-user5> (0, b'ansible-tmp-1554878730.6050982-46540706020890=/root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890\n', b'')
Using module file /user/user1/p363/lib/python3.6/site-packages/ansible-2.7.6-py3.6.egg/ansible/modules/commands/command.py
<linux-user5> PUT /user/user1/.ansible/tmp/ansible-local-312468ua784d6/tmp9l2vw34v TO /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890/AnsiballZ_command.py
<linux-user5> SSH: EXEC sshpass -d11 sftp -o BatchMode=no -b - -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/user/user1/.ansible/cp/0969431db6 '[linux-user5]'
<linux-user5> (0, b'sftp> put /user/user1/.ansible/tmp/ansible-local-312468ua784d6/tmp9l2vw34v /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890/AnsiballZ_command.py\n', b'')
<linux-user5> ESTABLISH SSH CONNECTION FOR USER: root
<linux-user5> SSH: EXEC sshpass -d11 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/user/user1/.ansible/cp/0969431db6 linux-user5 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890/ /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890/AnsiballZ_command.py && sleep 0'"'"''
<linux-user5> (0, b'', b'')
<linux-user5> ESTABLISH SSH CONNECTION FOR USER: root
<linux-user5> SSH: EXEC sshpass -d11 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/user/user1/.ansible/cp/0969431db6 -tt linux-user5 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1554878730.6050982-46540706020890/AnsiballZ_command.py && sleep 0'"'"''

收集事实后挂起。

第一次运行就顺利完成了。在客户端机器上重新安装操作系统后也成功了。

答案1

您是否尝试过手动运行ssh-keygen两次命令?

第一次运行:

user@host:~$ ssh-keygen -t rsa -f /tmp/id_rsa -q -P ""
user@host:~$

第二次运行:

user@host:~$ ssh-keygen -t rsa -f /tmp/id_rsa -q -P ""
/tmp/id_rsa already exists.
Overwrite (y/n)? 

你的命令只是永远等待着一个永远不会到来的答案。

解决方案 1:回答问题

您可以使用expect模块来回答交互式提示(如果你事先知道的话)

- name: ssh keygen
  expect:
    command: ssh-keygen -t rsa -f /root/.ssh/id_rsa -q -P ""
    responses:
      Overwrite \(y/n\)\?: y

虽然这在每次运行时都有效,这是一个糟糕的解决方案,因为它不是幂等的:每次运行剧本时,服务器都会发生变化,尽管你的库存或变量没有任何变化

解决方案2:仅在需要时生成。

更好的方法是仅当密钥不存在或需要刷新时才创建密钥。有几种方法可以做到这一点,这在很大程度上取决于您的需求、您的愿望、服务器园区的大小……

对于相对较小的公园,您可以在本地生成密钥并将其存储在您的库存中(使用ansible-vault混淆私钥)。然后只需将文件复制到服务器即可。如果文件已经存在且内容相同,则不会进行任何更改。

如果公园更大,钥匙可以存放在 Hashicorp Vault、Cyber​​ark 等处……

如果您仍想在每台服务器上创建密钥,以下是我以同样的方式执行的操作:

- name: remove key files if refresh was asked
  file:
    path: "/root/.ssh/id_rsa{{ item }}"
    state: absent
  loop:
    - ""
    - ".pub"
  when: refresh_keys | default(false) | bool

- name: check if key exists
  stat:
    path: /root/.ssh/id_rsa
  register: ssh_key_file

- name: generate keys if needed
  command: ssh-keygen -t rsa -f /root/.ssh/id_rsa -q -P ""
  when: not (ssh_key_file.stat.exists)
  changed_when: true

现在,如果您正常运行剧本,则仅当密钥尚不存在时才会创建密钥。如果您想刷新已有密钥的服务器上的密钥,可以将额外的变量传递给剧本

ansible-playbook /your/inventory.ini your_playbook.yml -e refresh_keys=true

相关内容