Безопасная передача файлов: Использование модулей Ansible Copy и Fetch
Используйте ad-hoc команды Ansible copy и fetch для отправки файлов на управляемые узлы и получения журналов или конфигураций обратно на управляющий узел.
Безопасная передача файлов: использование модулей Ansible Copy и Fetch
Перемещение файлов — одна из первых практических задач Ansible, которая вам понадобится: отправить конфигурацию на серверы, собрать файл журнала или создать резервную копию удаленного файла перед изменениями. Модули copy и fetch четко обрабатывают эти два направления.
Это руководство использует ad-hoc команды, поэтому вы можете выполнять разовые передачи без написания полного playbook. Те же аргументы модулей работают и в playbook, когда задача должна быть повторяемой.
Предварительные требования
Перед выполнением примеров ниже убедитесь, что у вас есть следующее:
- Управляющий узел Ansible: Машина с установленным Ansible.
- Файл инвентаря: Рабочий файл инвентаря (например,
/etc/ansible/hosts), определяющий ваши управляемые узлы. - Подключение: Настроен доступ по SSH с использованием ключей к вашим удаленным хостам.
Все примеры предполагают, что целевая группа в инвентаре называется webservers.
Понимание Ad-Hoc команд для передачи файлов
Ad-hoc команды — это однострочные команды, выполняемые непосредственно из терминала, идеально подходящие для быстрых задач, не требующих постоянного playbook. Базовая структура:
ansible <группа-хостов> -m <имя-модуля> -a "ключ=значение ключ2=значение2 ..."
Для передачи файлов мы используем имена модулей -m copy или -m fetch, передавая необходимые аргументы с помощью флага -a.
Модуль copy: отправка файлов на удаленные узлы
Модуль copy используется для передачи файла, находящегося на управляющей машине Ansible, на один или несколько управляемых узлов. Это стандартный метод развертывания файлов конфигурации, скриптов или небольших ресурсов.
Ключевые аргументы для copy
Модуль copy требует два обязательных аргумента и принимает несколько необязательных для управления конфигурацией:
| Аргумент | Описание | Обязательный? | Пример значения |
|---|---|---|---|
src |
Локальный путь к файлу на управляющей машине Ansible. Абсолютные пути наиболее понятны для ad-hoc команд. | Да | /tmp/config.conf |
dest |
Путь, по которому файл будет размещен на удаленном управляемом узле. | Да | /etc/app/config.conf |
owner |
Имя пользователя, который должен владеть файлом на удаленном узле. | Нет | nginx |
group |
Имя группы, которая должна владеть файлом на удаленном узле. | Нет | www-data |
mode |
Права доступа (восьмеричные) для целевого файла. | Нет | 0644 |
backup |
Если yes, создает резервную копию перед перезаписью оригинала. |
Нет | yes |
Пример 1: Простое развертывание файла
Предположим, у вас есть локальный файл пользовательского сообщения дня (motd), и вы хотите отправить его на все веб-серверы.
# Локальный путь к файлу: /home/user/ansible/motd_banner
# Удаленный путь: /etc/motd
ansible webservers -m copy -a "src=/home/user/ansible/motd_banner dest=/etc/motd"
Пример 2: Установка прав доступа и владельца
Если вы развертываете защищенный файл конфигурации, необходимо указать владельца, группу и ограниченные права доступа (например, только владелец может читать/записывать).
# Развертывание файла конфигурации приложения, принадлежащего 'app_user', группа 'devops',
# с правами на чтение/запись только для владельца (0600).
ansible webservers -m copy -b -a "src=/tmp/app_settings.yaml dest=/etc/app/settings.yaml owner=app_user group=devops mode=0600"
Примечание о
-b: Флаг-b(или--become) необходим, когда удаленный путь назначения требует повышенных привилегий (например, запись в/etc).
Модуль fetch: получение файлов с удаленных узлов
Модуль fetch выполняет обратную операцию по сравнению с copy: он получает файл с управляемого узла обратно на управляющую машину Ansible. Это полезно для резервного копирования файлов конфигурации, получения журналов или сбора диагностической информации.
Ключевые аргументы для fetch
Модуль fetch требует исходный файл на удаленном узле и целевую директорию на управляющей машине.
| Аргумент | Описание | Обязательный? | Пример значения |
|---|---|---|---|
src |
Абсолютный путь к файлу на удаленном управляемом узле. | Да | /var/log/nginx/error.log |
dest |
Абсолютный путь к директории на управляющей машине, куда будут сохранены файлы. | Да | /tmp/backups/logs |
flat |
Если yes, результирующее имя файла не будет содержать структуру имени хоста (не рекомендуется при получении с нескольких хостов). |
Нет | no (по умолчанию) |
Критическое отличие: структура назначения
В отличие от модуля copy, модуль fetch автоматически создает структурированный путь поддиректории на основе имени удаленного хоста, чтобы предотвратить конфликты имен файлов при получении файлов с нескольких серверов.
Результирующий путь на управляющей машине будет выглядеть так:
<dest>/<hostname>/<src>
Например, получение /etc/nginx/nginx.conf с host1 в /tmp/backups приведет к:
/tmp/backups/host1/etc/nginx/nginx.conf
Пример 3: Получение резервных копий удаленной конфигурации
Чтобы получить текущий файл конфигурации со всех веб-серверов в локальную директорию резервного копирования:
# Получить nginx.conf со всех веб-серверов в локальную директорию /tmp/config_backups
ansible webservers -m fetch -a "src=/etc/nginx/nginx.conf dest=/tmp/config_backups"
После выполнения этой команды, если вы указали webserver1 и webserver2, ваша локальная структура директорий будет такой:
/tmp/config_backups/
├── webserver1
│ └── etc
│ └── nginx
│ └── nginx.conf
└── webserver2
└── etc
└── nginx
└── nginx.conf
Пример 4: Получение одного файла без структуры хоста (flat=yes)
Если вы абсолютно уверены, что получаете файл только с одного хоста, или вам нужно только содержимое файла (а не структура происхождения), вы можете использовать flat=yes. Это приведет к размещению файла непосредственно в целевой папке с именем исходного удаленного файла.
# Получить отчет о состоянии локального здоровья с одного хоста, сохранив его напрямую.
ansible webserver1 -m fetch -a "src=/tmp/health_status.txt dest=/tmp/reports flat=yes"
# Результирующий путь: /tmp/reports/health_status.txt
Предупреждение: Используйте
flat=yesтолько при работе с одним хостом или если вы намерены перезаписывать файл при последующих запусках, так как Ansible не будет предотвращать конфликты.
Лучшие практики и соображения безопасности
Небольшие ошибки при передаче файлов могут привести к инцидентам в production, особенно когда файлы попадают в /etc или содержат секреты.
Всегда устанавливайте права доступа с помощью copy
Никогда не отправляйте файл конфигурации без явного указания mode и owner. Если вы полагаетесь на umask удаленной системы по умолчанию, конфиденциальные файлы (например, ключи SSH или учетные данные базы данных) могут получить чрезмерно разрешительные права доступа.
# Плохая практика (режим определяется из umask)
- name: Развернуть небезопасный ключ
ansible.builtin.copy:
src: private.key
dest: /etc/app/private.key
# Хорошая практика (явное ограничение доступа)
- name: Развернуть безопасный ключ
ansible.builtin.copy:
src: private.key
dest: /etc/app/private.key
mode: '0600'
owner: root
Используйте backup=yes для критических изменений
При использовании copy для перезаписи существующего критического файла (например, /etc/sudoers) включите backup=yes. Ansible создаст резервную копию с отметкой времени на удаленном узле перед перезаписью файла, что обеспечит простой вариант отката.
Рассмотрите synchronize для больших передач
Хотя copy и fetch хорошо работают для быстрых операций и небольших файлов, используйте ansible.posix.synchronize для больших деревьев директорий или эффективных дельта-передач. Он оборачивает rsync, поэтому управляющий узел и целевая среда должны иметь соответствующий доступ к rsync и SSH.
Вывод
Используйте copy, когда источник находится на вашем управляющем узле, а назначение — на управляемом узле. Используйте fetch, когда источник находится на управляемом узле, и вы хотите сохранить файл локально.
| Модуль | Направление | Пример Ad-Hoc команды |
|---|---|---|
copy |
Управляющий узел -> Управляемый узел | ansible all -m copy -a "src=/local/file dest=/remote/path mode=0644" |
fetch |
Управляемый узел -> Управляющий узел | ansible all -m fetch -a "src=/remote/file dest=/local/dir" |
Для одного сервера flat=yes может сделать полученные файлы более удобными для чтения. Для группы серверов сохраняйте структуру директорий на основе имени хоста по умолчанию, чтобы журнал одного хоста не перезаписывал журнал другого.