如何使用 Ansible 在两个托管节点之间复制文件?

问题描述 投票:0回答:9

我需要在两个远程节点之间复制文件:

  • 节点 A 是文件所在的受管节点
  • 节点 B 是应在其中复制文件的受管节点

请注意,我运行所有 Ansible 任务的控制节点不是上述节点。

我尝试过以下方法:

在 Ansible 的 shell 模块中使用

scp
命令

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

这种方法会一直持续下去,永远不会结束。

使用

fetch
copy
模块

- 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

这种方法会引发如下错误:

访问文件 /Users//.ansible/cp/ansible-ssh-machine2-22- 时出错,错误为:[Errno 102] 套接字上不支持操作:u'/Users//.ansible/cp/ansible- ssh-machine2-22-'

我怎样才能实现这个目标?

ansible
9个回答
132
投票

正如 @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
,因此文件从代理 (
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
上执行的,因此拉动是正确的选择。


111
投票

要复制远程到远程文件,您可以使用带有 synchronize

 关键字的 
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

此剧本可以从您的

machineC
运行。


4
投票

如果您需要通过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

3
投票

我能够使用 local_action to scp 将文件从机器 A 复制到机器 C,然后将文件复制到机器 B 来解决此问题。


3
投票

如果您想进行 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

3
投票

您也可以将

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
是其自身的文件。


1
投票

使用复制模块将文件从一台服务器传输到另一台服务器的简单方法

这是剧本

---
- 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}

0
投票

2021 年你应该安装包装器:

ansible-galaxy collection install ansible.posix

并使用

- name: Synchronize two directories on one remote host.
  ansible.posix.synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
  delegate_to: "{{ inventory_hostname }}"

了解更多:

https://docs.ansible.com/ansible/latest/collections/ansible/posix/synchronize_module.html

已检查:

ansible --version                          
ansible 2.10.5
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/daniel/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  executable location = /sbin/ansible
  python version = 3.9.1 (default, Dec 13 2020, 11:55:53) [GCC 10.2.0]

0
投票

将系统机密从机器 1 传输到机器 2 时,您可能无法在它们之间直接访问,因此涉及

delegate_to
的解决方案将失败。当您将私钥保存在 ansible 控制节点上并将公钥保存在 machine1 和 machine2 的 ansible 用户帐户上的
~/.ssh/authorized_keys
中时,就会发生这种情况。相反,您可以通过 ssh 将文件或目录从一台计算机传输到另一台计算机,使用无密码 sudo 进行远程权限升级:

-name "Copy /etc/secrets directory from machine1 and machine2"
  delegate_to: localhost
  shell: |
    ssh machine1 sudo tar -C / -cpf - etc/secrets | ssh machine2 sudo tar -C / -xpf -

例如,要使用 MUNGE 守护进程进行身份验证来设置 ad hoc 计算集群,您可以使用以下命令将凭证从头节点复制到工作节点。

setup_worker.yml

- name: "Install worker packages"
  apt:
    name: "{{ packages }}"
  vars:
    packages:
    - munge
    # ...and other worker packages...
  become: true
- name: "Copy MUNGE credentials from head to {{ host }}"
  delegate_to: localhost
  shell:
    ssh head.domain.name sudo tar -C / -cpf - etc/munge | ssh {{ ansible_facts["nodename"] }} sudo tar -C / -xpf -
  become: false
  when: ansible_facts["nodename"] != "head.domain.name"
- name: "Restart MUNGE"
  shell: |
    systemctl restart munge
  become: true

运行方式为

ansible-playbook -e host=machine1 setup_worker.yml
。 由于 ansible 用户没有特权,远程系统任务需要
become: true
。复制任务不需要提权,因为控制器仅用于设置管道;权限升级是通过 ssh 命令中的 sudo 进行的。变量
host
包含命令行上使用的主机模式,而不是正在初始化的工作程序。请改用
ansible_facts["nodename"]
,这将是当前工作线程的完全限定域名(假设工作线程已正确配置)。
when
子句阻止我们尝试将目录从头节点复制到自身上。

© www.soinside.com 2019 - 2024. All rights reserved.