Введение
В этой лабораторной работе вы освоите основные навыки развертывания и управления файлами в системе Red Hat Enterprise Linux (RHEL) с использованием Ansible. Вы получите практический опыт работы с наиболее распространенными и мощными модулями Ansible, предназначенными для файловых операций, начиная от простого развертывания файлов и заканчивая более сложными манипуляциями с содержимым и управлением состоянием.
Вы начнете с использования модуля ansible.builtin.copy для передачи статического файла и установки его атрибутов. Далее вы модифицируете содержимое файлов с помощью lineinfile и blockinfile, а также сгенерируете пользовательское сообщение дня (MOTD) с помощью модуля ansible.builtin.template. Лабораторная работа также охватывает создание символических ссылок, проверку состояний файлов с помощью stat, получение логов с помощью fetch и очистку управляемых файлов, предоставляя всесторонний обзор возможностей Ansible по управлению файлами.
Копирование статического файла и установка атрибутов с помощью модуля ansible.builtin.copy
На этом шаге вы научитесь использовать один из наиболее фундаментальных модулей Ansible: ansible.builtin.copy. Этот модуль используется для передачи файлов с вашего управляющего узла (виртуальной машины LabEx) в указанное место на управляемых хостах. В нашем случае управляемым хостом будет сам localhost. Помимо простого копирования, модуль copy позволяет точно контролировать атрибуты файла, такие как владелец, группа и права доступа, что крайне важно для правильной настройки системы.
Сначала настроим среду нашего проекта. Вся наша работа будет проводиться в каталоге ~/project.
Перейдите в каталог проекта и создайте подкаталог для наших исходных файлов. Это распространенная практика для поддержания порядка в проекте.
Установите пакет
ansible-core.sudo dnf install -y ansible-coreЗатем перейдите в каталог проекта и создайте подкаталог для наших исходных файлов.
cd ~/project mkdir filesДалее создайте простой текстовый файл, который мы будем копировать. Мы используем команду
catс "here document" для создания файлаinfo.txtв каталогеfiles.cat << EOF > ~/project/files/info.txt This file was deployed by Ansible. It contains important system information. EOFТеперь создайте файл инвентаря Ansible. Инвентарь сообщает Ansible, какие хосты необходимо управлять. Для этой лабораторной работы мы будем управлять локальной машиной. Создайте файл с именем
inventory.ini.cat << EOF > ~/project/inventory.ini localhost ansible_connection=local EOFВ этом инвентаре
localhost— это хост, на который мы нацелены. Переменнаяansible_connection=localуказывает Ansible выполнять задачи непосредственно на управляющем узле, без использования SSH.Создайте свой первый плейбук Ansible. Этот плейбук будет содержать инструкции по копированию файла. Используйте
nanoилиcatдля создания файла с именемcopy_file.yml.nano ~/project/copy_file.ymlДобавьте следующее содержимое в файл. Этот плейбук определяет одну задачу: скопировать
info.txtв каталог/tmp/и установить его атрибуты.--- - name: Deploy a static file to localhost hosts: localhost tasks: - name: Copy info.txt and set attributes ansible.builtin.copy: src: files/info.txt dest: /tmp/info.txt owner: labex group: labex mode: "0640"Давайте разберем параметры в задаче
copy:src: files/info.txt: Путь к исходному файлу на управляющем узле, относительно расположения плейбука.dest: /tmp/info.txt: Абсолютный путь, по которому файл будет размещен на управляемом хосте.owner: labex: Устанавливает владельцем файла пользователяlabex.group: labex: Устанавливает группой файла группуlabex.mode: '0640': Устанавливает права доступа к файлу.0640означает, что владелец может читать/писать, группа может читать, а остальные не имеют разрешений.
Выполните плейбук с помощью команды
ansible-playbook. Флаг-iуказывает наш файл инвентаря.ansible-playbook -i inventory.ini copy_file.ymlВы должны увидеть вывод, указывающий на успешное выполнение плейбука, примерно следующий:
PLAY [Deploy a static file to localhost] *************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Copy info.txt and set attributes] **************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Наконец, проверьте, что файл был скопирован правильно и имеет нужные атрибуты. Используйте команду
ls -lдля проверки прав доступа, владельца и группы.ls -l /tmp/info.txtВывод должен показать, что
labexявляется владельцем и группой, а права доступа установлены как-rw-r-----.-rw-r----- 1 labex labex 72 Jul 10 14:30 /tmp/info.txtВы также можете просмотреть содержимое файла, чтобы убедиться, что он был скопирован полностью.
cat /tmp/info.txtThis file was deployed by Ansible. It contains important system information.
Вы успешно использовали модуль ansible.builtin.copy для развертывания файла и настройки его атрибутов в вашей локальной системе.
Изменение содержимого файла с помощью lineinfile и blockinfile
На этом шаге вы научитесь изменять существующие файлы на управляемом хосте, не заменяя файл целиком. Ansible предоставляет мощные модули для этой цели: ansible.builtin.lineinfile для управления отдельными строками и ansible.builtin.blockinfile для управления многострочными блоками текста. Они чрезвычайно полезны для таких задач, как изменение настроек конфигурации или добавление записей в файлы журналов.
Мы продолжим работать с файлом info.txt, который вы создали на предыдущем шаге и который находится по пути /tmp/info.txt.
Сначала убедитесь, что вы находитесь в каталоге проекта.
cd ~/projectСоздайте новый плейбук с именем
modify_file.yml. Этот плейбук будет содержать две задачи: одну для добавления одной строки и другую для добавления блока текста в наш существующий файл.nano ~/project/modify_file.ymlДобавьте следующее содержимое в ваш плейбук
modify_file.yml. Этот плейбук нацелен наlocalhostи используетlineinfileиblockinfileдля добавления содержимого в/tmp/info.txt.--- - name: Modify an existing file hosts: localhost tasks: - name: Add a single line of text to a file ansible.builtin.lineinfile: path: /tmp/info.txt line: This line was added by the lineinfile module. state: present - name: Add a block of text to an existing file ansible.builtin.blockinfile: path: /tmp/info.txt block: | ## BEGIN ANSIBLE MANAGED BLOCK This block of text consists of two lines. They have been added by the blockinfile module. ## END ANSIBLE MANAGED BLOCK state: presentДавайте рассмотрим используемые модули:
ansible.builtin.lineinfile: Этот модуль гарантирует наличие определенной строки в файле. Если строка уже существует, Ansible ничего не делает, что делает задачу идемпотентной.path: Файл для изменения.line: Строка текста, которая должна присутствовать в файле.state: present: Гарантирует наличие строки. Вы можете использоватьstate: absentдля ее удаления.
ansible.builtin.blockinfile: Этот модуль управляет блоком текста, окруженным маркерами строк (например,## BEGIN ANSIBLE MANAGED BLOCK). Это идеально подходит для управления разделами конфигурации.path: Файл для изменения.block: Многострочная строка для вставки.|— это синтаксис YAML для литерального блока, сохраняющий переносы строк.state: present: Гарантирует наличие блока.
Выполните плейбук с помощью команды
ansible-playbookи вашего файлаinventory.ini.ansible-playbook -i inventory.ini modify_file.ymlВывод покажет, что обе задачи внесли изменения в файл.
PLAY [Modify an existing file] ************************************************* TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Add a single line of text to a file] ************************************* changed: [localhost] TASK [Add a block of text to an existing file] ********************************* changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Наконец, проверьте изменения, просмотрев содержимое
/tmp/info.txt.cat /tmp/info.txtВы должны увидеть исходное содержимое, за которым следует новая строка и новый блок текста.
This file was deployed by Ansible. It contains important system information. This line was added by the lineinfile module. ## BEGIN ANSIBLE MANAGED BLOCK This block of text consists of two lines. They have been added by the blockinfile module. ## END ANSIBLE MANAGED BLOCKЕсли вы запустите плейбук снова, Ansible сообщит
ok=3иchanged=0, потому что содержимое уже присутствует, демонстрируя идемпотентность этих модулей.
Генерация пользовательского MOTD с помощью модуля ansible.builtin.template
На этом шаге вы перейдете от копирования статических файлов к генерации динамических файлов с использованием модуля ansible.builtin.template. Этот модуль использует движок шаблонов Jinja2 для создания файлов, настроенных с помощью переменных и системной информации, известной как "факты" (facts), которые Ansible собирает с ваших управляемых хостов. Мы создадим динамическое сообщение дня (MOTD), которое будет отображать специфичную для системы информацию.
Сначала убедитесь, что вы находитесь в каталоге
~/project, и создайте выделенный подкаталог для ваших шаблонов. Стандартной лучшей практикой Ansible является хранение шаблонов Jinja2 в каталогеtemplates.cd ~/project mkdir templatesДалее создайте файл шаблона Jinja2. Этот файл,
motd.j2, будет содержать структуру нашего MOTD с заполнителями для динамических данных. Расширение.j2является распространенным соглашением для шаблонов Jinja2.nano ~/project/templates/motd.j2Добавьте следующее содержимое в файл. Обратите внимание на синтаксис
{{ ... }}, который обозначает заполнитель для переменной или факта.################################################################# ## Welcome to {{ ansible_facts['fqdn'] }} # ## This is a {{ ansible_facts['distribution'] }} system. ## System managed by Ansible. # ## For support, contact: {{ admin_email }} #################################################################В этом шаблоне:
{{ ansible_facts['fqdn'] }}будет заменено полным доменным именем хоста (Fully Qualified Domain Name).{{ ansible_facts['distribution'] }}будет заменено названием дистрибутива Linux (например, RedHat).{{ admin_email }}— это пользовательская переменная, которую мы определим в нашем плейбуке.
Теперь создайте новый плейбук с именем
template_motd.yml. Этот плейбук будет использовать шаблон для генерации файла/etc/motd.nano ~/project/template_motd.ymlДобавьте следующее содержимое. Этот плейбук требует повышенных привилегий (
become: true) для записи в каталог/etc. Он также определяет пользовательскую переменнуюadmin_email.--- - name: Deploy a custom MOTD from a template hosts: localhost become: true vars: admin_email: admin@labex.io tasks: - name: Generate /etc/motd from template ansible.builtin.template: src: templates/motd.j2 dest: /etc/motd owner: root group: root mode: "0644"Ключевые параметры в этом плейбуке:
become: true: Это указывает Ansible использоватьsudoдля выполнения задачи, что необходимо для записи в/etc/motd.vars: В этом разделе мы определяем пользовательские переменные, такие какadmin_email.ansible.builtin.template: Модуль, который обрабатывает шаблон Jinja2.srcуказывает на наш файл.j2, аdest— это целевой файл на управляемом хосте.
Выполните плейбук.
ansible-playbook -i inventory.ini template_motd.ymlВывод должен подтвердить успешное выполнение задачи.
PLAY [Deploy a custom MOTD from a template] ************************************ TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Generate /etc/motd from template] **************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Проверьте результат. Проверьте содержимое вновь сгенерированного файла
/etc/motd.cat /etc/motdВы увидите отрендеренный вывод с замененными плейсхолдерами Jinja2 фактическими системными фактами и пользовательской переменной, которую вы определили.
fqdnбудет соответствовать имени хоста вашей лабораторной среды.################################################################# ## Welcome to host.labex.io # ## This is a RedHat system. ## System managed by Ansible. # ## For support, contact: admin@labex.io #################################################################
Теперь вы успешно использовали шаблон для создания настроенного файла, что является ключевым навыком в автоматизации инфраструктуры.
Развертывание вспомогательных файлов и создание символической ссылки с помощью copy и file
На этом шаге вы объедините свои знания модуля copy с новым, универсальным модулем: ansible.builtin.file. В то время как copy используется для передачи содержимого, file используется для управления состоянием файлов, каталогов и символических ссылок на управляемом хосте. Вы будете использовать его для создания каталогов, установки разрешений и, что наиболее важно для этого упражнения, создания символических ссылок.
Наш сценарий заключается в настройке сообщений перед входом в систему, отображаемых системой. Во многих системах Linux /etc/issue отображается локальным пользователям терминала, а /etc/issue.net отображается удаленным пользователям (например, через SSH). Мы развернем один файл issue, а затем создадим символическую ссылку, чтобы /etc/issue.net указывал на /etc/issue, гарантируя, что они всегда будут отображать одно и то же сообщение.
Сначала убедитесь, что вы находитесь в каталоге
~/project, и создайте исходный файл для нашего сообщения issue. Мы поместим этот файл в подкаталогfiles, который вы создали ранее.cd ~/project cat << EOF > ~/project/files/issue Authorized access only. All connections are logged and monitored. EOFСоздайте новый плейбук с именем
deploy_issue.yml. Этот плейбук будет содержать две задачи: одну для копирования файлаissueи другую для создания символической ссылки.nano ~/project/deploy_issue.ymlДобавьте следующее содержимое в ваш плейбук
deploy_issue.yml. Этот плейбук требует повышенных привилегий (become: true) для управления файлами в каталоге/etc/.--- - name: Configure system issue files hosts: localhost become: true tasks: - name: Copy custom /etc/issue file ansible.builtin.copy: src: files/issue dest: /etc/issue owner: root group: root mode: "0644" - name: Ensure /etc/issue.net is a symlink to /etc/issue ansible.builtin.file: src: /etc/issue dest: /etc/issue.net state: link force: yesДавайте проанализируем новую задачу
ansible.builtin.file:src: /etc/issue: Когдаstateустановлен вlink,srcуказывает файл, на который должна указывать символическая ссылка.dest: /etc/issue.net: Это путь, по которому будет создана сама символическая ссылка.state: link: Этот важный параметр указывает модулюfileсоздать символическую ссылку, а не обычный файл или каталог.force: yes: Это полезная опция, которая обеспечивает идемпотентность. Если/etc/issue.netуже существует как обычный файл, Ansible удалит его и создаст ссылку. Безforce: yesплейбук завершится ошибкой в такой ситуации.
Выполните плейбук.
ansible-playbook -i inventory.ini deploy_issue.ymlВывод покажет, что обе задачи успешно внесли изменения.
PLAY [Configure system issue files] ******************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Copy custom /etc/issue file] ********************************************* changed: [localhost] TASK [Ensure /etc/issue.net is a symlink to /etc/issue] ************************ changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Проверьте результат с помощью команды
ls -l. Эта команда предоставляет подробный список, который четко показывает символические ссылки.ls -l /etc/issue /etc/issue.netВывод должен показать, что
/etc/issueявляется обычным файлом, а/etc/issue.net— символической ссылкой, указывающей на него. Букваlв начале разрешений для/etc/issue.netуказывает, что это ссылка.-rw-r--r--. 1 root root 65 Jul 10 15:00 /etc/issue lrwxrwxrwx. 1 root root 10 Jul 10 15:00 /etc/issue.net -> /etc/issue
Теперь вы успешно развернули файл конфигурации и использовали модуль ansible.builtin.file для создания символической ссылки, что является распространенным и мощным шаблоном для управления конфигурациями системы.
Проверка состояния файла с помощью stat и получение логов с помощью fetch
На этом шаге вы познакомитесь с двумя важными модулями для сбора данных: ansible.builtin.stat и ansible.builtin.fetch. Модуль stat используется для проверки состояния файла или каталога на управляемом хосте — например, для определения его существования, разрешений или времени последнего изменения. Он ничего не меняет, что делает его идеальным для проверок и условной логики. Модуль fetch делает противоположное copy: он извлекает файлы с управляемого хоста и сохраняет их на вашем управляющем узле, что идеально подходит для резервного копирования конфигураций или сбора лог-файлов для анализа.
Мы создадим плейбук, который сначала проверит существование файла /etc/motd, созданного ранее, а затем получит файл журнала пакетного менеджера DNF (/var/log/dnf.log) в локальный каталог на вашей виртуальной машине LabEx.
Сначала убедитесь, что вы находитесь в каталоге
~/project, и создайте новый подкаталог для хранения файлов, которые вы будете получать.cd ~/project mkdir fetched_logsСоздайте новый плейбук с именем
check_and_fetch.yml. Этот плейбук будет содержать задачи для проверки файла и получения лога.nano ~/project/check_and_fetch.ymlДобавьте следующее содержимое в ваш плейбук
check_and_fetch.yml. Этот плейбук используетstatдля получения сведений о файле,registerдля сохранения этих сведений в переменной,debugдля отображения переменной иfetchдля получения лог-файла.--- - name: Check file status and fetch logs hosts: localhost become: true tasks: - name: Check if /etc/motd exists ansible.builtin.stat: path: /etc/motd register: motd_status - name: Display stat results ansible.builtin.debug: var: motd_status.stat - name: Fetch the dnf log file from managed host ansible.builtin.fetch: src: /var/log/dnf.log dest: fetched_logs/ flat: yesДавайте разберем ключевые концепции:
register: motd_status: Это важная функция Ansible. Она берет весь вывод задачи и сохраняет его в новой переменной с именемmotd_status.ansible.builtin.debug: Этот модуль используется для вывода значений во время выполнения плейбука. Здесь мы выводим объектstatиз нашей зарегистрированной переменной (motd_status.stat), чтобы увидеть свойства файла.ansible.builtin.fetch: Этот модуль извлекает файл с управляемого хоста.src: Путь к файлу, который нужно получить с управляемого хоста.dest: Каталог на управляющем узле (вашей виртуальной машине LabEx), куда будет сохранен файл.flat: yes: По умолчаниюfetchсоздает структуру подкаталогов, соответствующую хосту и пути источника.flat: yesупрощает это, копируя файл непосредственно в каталогdestбез дополнительных подкаталогов.
Выполните плейбук. Поскольку мы читаем системный лог-файл, используется
become: trueдля получения необходимых разрешений.ansible-playbook -i inventory.ini check_and_fetch.ymlВывод покажет результаты проверки
statв задаче отладки, за которыми последует задачаfetch.PLAY [Check file status and fetch logs] **************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Check if /etc/motd exists] *********************************************** ok: [localhost] TASK [Display stat results] **************************************************** ok: [localhost] => { "motd_status.stat": { "exists": true, "gid": 0, "isreg": true, "mode": "0644", "path": "/etc/motd", ... } } TASK [Fetch the dnf log file from managed host] ******************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Проверьте, был ли лог-файл успешно получен. Выведите содержимое каталога
fetched_logs.ls -l ~/project/fetched_logs/Вы должны увидеть файл
dnf.log, который теперь хранится локально на вашем управляющем узле.total 4 -rw-r--r--. 1 labex labex 1234 Jul 10 15:30 dnf.log
Теперь вы узнали, как проверять свойства файлов без внесения изменений и как извлекать важные файлы с ваших управляемых систем обратно на ваш управляющий узел.
Очистка управляемых файлов на хосте с помощью модуля file
На последнем этапе вы узнаете, как использовать модуль ansible.builtin.file для обеспечения отсутствия файлов и каталогов в системе. Важной частью управления конфигурацией является не только создание и изменение ресурсов, но и их последующая очистка. Установив параметр state в значение absent, вы можете указать Ansible удалить файлы, символические ссылки или даже целые каталоги.
В завершение этой лабораторной работы мы напишем один плейбук "очистки", который удалит все артефакты, созданные нами на предыдущих шагах: /tmp/info.txt, /etc/motd, /etc/issue и символическую ссылку /etc/issue.net.
Сначала убедитесь, что вы находитесь в каталоге
~/project.cd ~/projectСоздайте новый плейбук с именем
cleanup.yml. Этот плейбук будет содержать все задачи, необходимые для отмены наших изменений.nano ~/project/cleanup.ymlДобавьте следующее содержимое в ваш плейбук
cleanup.yml. Этот плейбук использует список задач, каждая из которых нацелена на один из созданных нами файлов. Обратите внимание, чтоbecome: trueустановлен на уровне плейбука, поэтому все задачи будут выполняться с повышенными привилегиями.--- - name: Clean up managed files from the system hosts: localhost become: true tasks: - name: Remove the temporary info file ansible.builtin.file: path: /tmp/info.txt state: absent - name: Remove the custom MOTD file ansible.builtin.file: path: /etc/motd state: absent - name: Remove the custom issue file ansible.builtin.file: path: /etc/issue state: absent - name: Remove the issue.net symbolic link ansible.builtin.file: path: /etc/issue.net state: absentКлючевым моментом этого плейбука является параметр
state: absentв каждой задаче. Он указывает модулюfileубедиться, что элемент по указанномуpathотсутствует. Если файл найден, он будет удален. Если файла уже нет, ничего не произойдет, сохраняя идемпотентность.Выполните плейбук очистки.
ansible-playbook -i inventory.ini cleanup.ymlВывод покажет, что каждая задача успешно внесла изменение, удалив файл.
PLAY [Clean up managed files from the system] ********************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Remove the temporary info file] ****************************************** changed: [localhost] TASK [Remove the custom MOTD file] ********************************************* changed: [localhost] TASK [Remove the custom issue file] ******************************************** changed: [localhost] TASK [Remove the issue.net symbolic link] ************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Проверьте, были ли файлы удалены. Вы можете использовать команду
lsдля проверки их наличия. Команда сообщит, что не может получить к ним доступ, потому что они отсутствуют.ls /tmp/info.txt /etc/motd /etc/issue /etc/issue.netОжидаемый вывод — серия ошибок, подтверждающих успешность очистки.
ls: cannot access '/tmp/info.txt': No such file or directory ls: cannot access '/etc/motd': No such file or directory ls: cannot access '/etc/issue': No such file or directory ls: cannot access '/etc/issue.net': No such file or directory
Теперь вы успешно использовали Ansible для удаления файлов и очистки системы, завершив полный жизненный цикл управления файлами от создания до удаления.
Резюме
В этой лабораторной работе вы изучили основы управления файлами в системах RHEL с использованием Ansible. Вы начали с использования модуля ansible.builtin.copy для передачи статического файла на управляемый хост, одновременно устанавливая определенное владение и права доступа. Затем вы изучили, как изменять существующие файлы, гарантируя наличие определенной строки с помощью lineinfile и управляя многострочными блоками текста с помощью blockinfile. Ключевым навыком, который вы освоили, было создание динамического содержимого файлов с использованием модуля ansible.builtin.template и синтаксиса Jinja2 для создания настраиваемого сообщения дня (MOTD), заполненного системными фактами.
Кроме того, вы отработали развертывание вспомогательных файлов и создание символических ссылок с помощью модуля ansible.builtin.file. Чтобы убедиться в успешности ваших развертываний, вы использовали модуль stat для проверки состояния и атрибутов файлов, а также модуль fetch для извлечения файлов, таких как журналы, с управляемого хоста обратно на управляющий узел. Наконец, вы научились выполнять операции очистки, используя модуль file с параметром state: absent для удаления файлов и каталогов, созданных в ходе лабораторной работы, обеспечивая чистое состояние на управляемом хосте.


