Как копировать файлы между двумя узлами с помощью ansible

98

Мне нужно скопировать машину формы файла A на машину B, тогда как моя управляющая машина, с которой я запускаю все свои доступные задачи, - это машина C (локальная машина)

Я пробовал следующее:

Используйте команду scp в модуле оболочки ansible

hosts: machine2
user: user2
tasks:
  - name: Copy file from machine1 to machine2 
    shell: scp user1@machine1:/path-of-file/file1 /home/user2/file1

Этот подход продолжается и никогда не заканчивается.

использовать модули выборки и копирования

hosts: machine1
user: user1
tasks:
  - name: copy file from machine1 to local
    fetch: src=/path-of-file/file1 dest=/path-of-file/file1

hosts: machine2
user: user2
tasks:
  - name: copy file from local to machine2
    copy: src=/path-of-file/file1 dest=/path-of-file/file1

Этот подход вызывает у меня следующую ошибку:

error while accessing the file /Users/<myusername>/.ansible/cp/ansible-ssh-machine2-22-<myusername>, error was: [Errno 102] Operation not supported on socket: u'/Users/<myusername>/.ansible/cp/ansible-ssh-machine2-22-<myusername>'

Любые предложения будут полезны.

user3228188
источник
1. Это удобная функция для сохранения доступа к сети, когда управляющая машина может быть дальше; 2.Это должно быть исправлено согласно github.com/ansible/ansible/pull/16756 jctanner объединил коммит 0d94d39 в ansible: devel 23 сентября 2016 г.
AnneTheAgile

Ответы:

101

Для копирования удаленных файлов на удаленные вы можете использовать модуль синхронизации с delegate_to: source-serverключевым словом ' ':

- hosts: serverB
  tasks:    
   - name: Copy Remote-To-Remote (from serverA to serverB)
     synchronize: src=/copy/from_serverA dest=/copy/to_serverB
     delegate_to: serverA

Этот сценарий может запускаться с вашего компьютера C.

ant31
источник
хороший ответ! К сожалению, мне не удалось заставить его работать в среде Vagrant с несколькими виртуальными машинами. Похоже, Бродяга там делает что-то особенное.
therealmarv 05
Он использует rsync, он у вас установлен на виртуальной машине?
ant31 05
1
Начиная с Vagrant 1.7.x он использует разные закрытые ключи в зависимости от машины. См. Выпуск github.com/mitchellh/vagrant/issues/4967 Проблему Вставьте следующую строку в Vagrantfile, config.ssh.insert_key = falseчтобы заставить Vagrant использовать ОДИН insecure_key для доступа ко всем машинам. Но теперь у меня даже сообщение об ошибке не появляется (ждет вечно). Также ошибка github.com/ansible/ansible/issues/7250 говорит о невозможности копирования с удаленного на удаленный.
therealmarv 05
9
Это фактически копирует файлы с serverB на serverA. Если вы хотите скопировать их с serverA на serverB, используйте mode=push(или delegate_to: serverB, но не оба).
Мариус Гедминас
2
@MariusGedminas, вы правы, mode=pushследует использовать, но в этой ситуации delegate_to: serverBнельзя использовать, потому что это сделает serverBисточник и место назначения.
Страхинья Кустудич
95

Как уже указывал ant31, вы можете использовать synchronizeдля этого модуль. По умолчанию модуль передает файлы между управляющей машиной и текущим удаленным хостом ( inventory_host), однако это можно изменить с помощью параметра задачи delegate_to(важно отметить, что это параметр задачи , а не модуля).

Вы можете разместить задачу на любом ServerAили ServerB, но вы должны соответствующим образом скорректировать направление передачи (с помощью modeпараметра synchronize).

Ставим задачу на ServerB

- hosts: ServerB
  tasks:
    - name: Transfer file from ServerA to ServerB
      synchronize:
        src: /path/on/server_a
        dest: /path/on/server_b
      delegate_to: ServerA

При этом используется значение по умолчанию mode: push, поэтому файл передается от delegate ( ServerA) к текущему удаленному ( ServerB).

Это может показаться странным, поскольку задача помещена в ServerB(через hosts: ServerB). Однако следует иметь в виду, что задача на самом деле выполняется на делегированном хосте , которым в данном случае и является ServerA. Так что толкание (от ServerAк ServerB) - действительно правильное направление. Также помните, что мы не можем просто отказаться от делегирования вообще, поскольку это будет означать, что передача происходит между управляющей машиной и ServerB.

Ставим задачу на ServerA

- hosts: ServerA
  tasks:
    - name: Transfer file from ServerA to ServerB
      synchronize:
        src: /path/on/server_a
        dest: /path/on/server_b
        mode: pull
      delegate_to: ServerB

Используется mode: pullдля изменения направления передачи. Опять же, имейте в виду, что задача фактически выполняется наServerB , поэтому вытягивание - правильный выбор.

Флориан Брукер
источник
8
Это настолько хороший ответ, что он должен быть частью документации Ansible . Ни один из приведенных здесь примеров не объясняет это так ясно. Спасибо!
ssc
2
Я пробовал это разными способами, но безуспешно Warning: Identity file /Users/myuser/.ssh/id_servers not accessible.
orotemo
@orotemo: Без дополнительной информации я могу только догадываться, но это похоже на проблему в вашей настройке SSH. Пожалуйста, проверьте, настроили ли вы SSH или Ansible для использования файла идентификации, указанного в сообщении об ошибке, и существует ли этот файл и имеет ли соответствующие разрешения.
Флориан Брукер,
2
@WilliamTurrell Я обновил свой ответ, чтобы более подробно объяснить направление передачи. Модуль действительно немного сбивает с толку.
Флориан Брукер,
1
Спасибо. Для всех, у кого есть проблема @orotemo, вероятное решение состоит в том, что у вас нет доступа к открытому ключу только между серверами A и B, или, как я обнаружил, вы настроили его работать только в одном направлении - в неправильном. В отсутствие какой-либо пары ключей в вашем каталоге .ssh на сервере A, ansible пытается использовать домашний каталог вашего локального компьютера (который не будет существовать, если это, скажем, Mac, и может иметь другое имя учетной записи)
Уильям Туррелл
3

Если вам нужно синхронизировать файлы между двумя удаленными узлами через ansible, вы можете использовать это:

- name: synchronize between nodes
  environment:
    RSYNC_PASSWORD: "{{ input_user_password_if_needed }}"
  synchronize:
    src: rsync://user@remote_server:/module/
    dest: /destination/directory/
    // if needed
    rsync_opts:
       - "--include=what_needed"
       - "--exclude=**/**"
    mode: pull
    delegate_to: "{{ inventory_hostname }}"

когда remote_serverвам нужно запустить rsync в режиме демона. Простой пример:

pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsync.log
port = port

[module]
path = /path/to/needed/directory/
uid = nobody
gid = nobody
read only = yes
list = yes
auth users = user
secrets file = /path/to/secret/file
CrusaderX
источник
2

Я смог решить эту проблему, используя local_action в scp в файл с машиныA на machineC, а затем скопировав файл на machineB.

user3228188
источник
1

Простой способ использовать модуль копирования для передачи файла с одного сервера на другой.

Вот playbook

---
- hosts: machine1 {from here file will be transferred to another remote machine}
  tasks:
  - name: transfer data from machine1 to machine2

    copy:
     src=/path/of/machine1

     dest=/path/of/machine2

    delegate_to: machine2 {file/data receiver machine}
Алиаббас Котхавала
источник
Это всплыло сегодня во время сеанса, но никто из нас не смог воспроизвести это с помощью ansible 2.6.4. Помещение этой задачи в playbook с созданием файла сначала на machine1 и последующим перечислением каталога завершилось неудачно: «Не удалось найти или получить доступ к '/ tmp / source-49731914' на Ansible Controller». Создание пустого файла на хост-машине решило эту проблему, но скопировало host> machine2. Может, в какой-то версии были баги?
Stephan B
0

Если вы хотите выполнить rsync и использовать настраиваемый пользовательский и настраиваемый ключ ssh, вам необходимо записать этот ключ в параметрах rsync.

---
 - name: rsync
   hosts: serverA,serverB,serverC,serverD,serverE,serverF
   gather_facts: no
   vars:
     ansible_user: oracle
     ansible_ssh_private_key_file: ./mykey
     src_file: "/path/to/file.txt"
   tasks:
     - name: Copy Remote-To-Remote from serverA to server{B..F}
       synchronize:
           src:  "{{ src_file }}"
           dest: "{{ src_file }}"
           rsync_opts:
              - "-e ssh -i /remote/path/to/mykey"
       delegate_to: serverA
Саша Голиков
источник
0

Вы можете использовать deletgateс scpтоже:

- name: Copy file to another server
  become: true
  shell: "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null admin@{{ inventory_hostname }}:/tmp/file.yml /tmp/file.yml"
  delegate_to: other.example.com

Потому delegateчто команда выполняется на другом сервере, и это scpфайл сам себе.

Крис
источник