На чем было опробовано:
- Ansible 2.9.18
- Hyper-V на Windows 10 Pro.
- Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
- Node 1: CentOS Linux release 7.9.2009 (Core).
- Node 2: CentOS Linux release 7.9.2009 (Core).
- Node 3: CentOS Linux release 7.9.2009 (Core).
- Node 4: CentOS Linux release 7.9.2009 (Core).
1. Задача.
К примеру, нам требуется с помощью внедрения custom facts для Ansible организовать сбор версий контейнеров, запущенных на серверах, а так же сбор версий некоторого программного обеспечения на серверах, которое имеет файл с указанием версии в своём каталоге /ecp/po/version.txt
.
Собранная информация должна формироваться в json-формат.
Дополнительно требуется рассмотреть средства визуализации информации в удобном виде (opensource web-приложения).
2. Решение задачи.
Решение будет состоять из нескольких этапов:
- загрузка и выполнение скрипта на узлах с целью получить json файлы;
- выгрузка файлов json с узлов;
- склеивание узловых файлов json в один сводный файл;
- просмотр сводного файла.
В системе Ansible есть возможность собирать системную информацию, которая собирается в виде фактов с помощью встроенного модуля setup.
Со сбором стандартных переменных по умолчанию всё предельно ясно, но что делать, если мы хотим сформировать наши собственные переменные на всех хостах, чтобы в дальнейшем использовать их в нашем коде?
Для этого существует возможность добавления Custom facts, что делается следующим образом:
- на любом хосте, контролируемом Ansible, создаётся каталог
/etc/ansible/facts.d
; - внутри каталога размещаются один либо несколько файлов с расширением
*.fact
, напримерcustom.fact
; - файлы возвращают данные в формате json.
Создаем инвентарь test-servers.inventory
на 4 тестовых сервера:
# mcedit /ansible/test-servers.inventory
С таким содержимым:
[test_servers]
server1 ansible_ssh_host=192.168.0.39 ansible_ssh_user=root
server2 ansible_ssh_host=192.168.0.30 ansible_ssh_user=root
server3 ansible_ssh_host=192.168.0.31 ansible_ssh_user=root
emachines ansible_ssh_host=192.168.0.12 ansible_ssh_user=root
Создаем специальный custom.fact
файл для загрузки на узлы, который, по сути, является скриптом для выполнения некоторого комплекса действий на удалённом узле.
По замыслу будут собираться некоторые переменные и заворачиваться в разметку json.
#!/bin/bash
file_po="/etc/po/version.txt"
host_name=$(hostname)
ecp_ver=$(awk -F: '/rel_ver/{print $2}' $file_po)
docker_info=$(docker ps --format ' {{json .Names}}: {{json .Image}}, ' | paste -sd'\n' | sed '$ s/.$//')
jp="/$host_name.json"
echo "{" > $jp
echo "\"Информация об узлах\": {" >> $jp
echo "\"$host_name\": {" >> $jp
if test -f "$file_po"; then
echo "\"Софт\": {" >> $jp
echo "\"Версия чего-то\": \"$ecp_ver\"" >> $jp
echo "}" >> $jp
echo "," >> $jp
fi
echo "\"Докеры на узле\": {" >> $jp
echo "$docker_info" >> $jp
echo "}" >> $jp
echo "}" >> $jp
echo "}" >> $jp
echo "}" >> $jp
Создаём специальный playbook custom-facts-fetch.yml
, содержащий сценарий /ansible/files/custom.fact
для узла, возвращающий некоторый файл json на Ansible master сервер с каждого узла:
---
- name: "Cбор Ansible custom facts"
hosts: all
tasks:
- name: "Удаление предыдущей версии Ansible custom facts файлов на узле"
file:
state: "absent"
path: "/etc/ansible/facts.d/"
- name: "Создание Ansible custom fact каталога"
file:
path: "/etc/ansible/facts.d"
state: "directory"
mode: 0766
- name: "Загрузка на узлы Ansible custom fact файлов"
copy:
src: "/ansible/files/custom.fact"
dest: "/etc/ansible/facts.d/custom.fact"
mode: +x
- name: "Объявление служебной переменной для Ansible custom fact"
debug: "var=ansible_local"
notify:
- reload facts
- name: "Перезагрузка facts"
setup: "filter=ansible_local"
- name: "Подготовка списка файлов *.json для выгрузки с узла"
find:
paths: "/"
recurse: "no"
patterns: "*.json"
register: "files_to_copy"
- name: "Выгрузка файлов *.json с узла на Ansible master сервер"
fetch:
src: "{{ item.path }}"
dest: "/ansible/json"
with_items: "{{ files_to_copy.files }}"
Напишем скрипт custom-facts-fetch-PLAY.sh
для запуска playbook на целевом inventory:
#!/bin/bash.
ansible-playbook /ansible/custom-facts-fetch.yml -i /ansible/test-servers.inventory
Сделаем файл скрипта исполняемым:
# chmod +x custom-facts-fetch-PLAY.sh
И запустим его.
Ответ:
После успешной отработки playbook на сервере Ansible master появится каталог /ansible/json
с подкаталогами ‘имя_узла
‘:
В каждом из которых будет находиться json файл вида имя_узла.json
:
Содержимое json файла первого узла emachines
:
Содержимое json файла второго узла server1
:
Содержимое json файла третьего узла server2
:
Содержимое json файла четвертого узла server3
:
Получилось несколько файлов json, по файлу с каждого целевого узла.
Сколько узлов мы задействовали для Ansible custom facts, столько и json файлов и будет.
В первом файле emachines.hamsterden.loc.json
не имеется фрагмент с названием «Версия чего-то
‘, по втором файле cos7client1.hamsterden.loc.json
такой фрагмент имеется, а так как в custom.fact
реализована проверка на фактическое наличия файла /ecp/po/version.txt
.
К примеру, наличие файла /ecp/po/version.txt
бывает только у серверов типа «web-server». Так как скрипт «сам учитывает» тип сервера, то можно смело применять custom.fact
на все целевые серверы и файл json всегда будет генерироваться корректно для каждого типа серверов.
Для создание сводного json файла по всем файлам со всех узлам, воспользуемся утилитой jq.
Ссылка на официальный сайт утилиты: https://stedolan.github.io/jq/.
Установка утилиты:
# yum install jq -y
План работ с файлами:
file1.json + file3.json + file3.json + file4.json = final_result_po.json
Создадим make-final-json-file.sh
скрипт:
# mcedit /ansible/make-final-json-file.sh
#!/bin/bash
#создание каталогов для обработки файлов
mkdir -p /ansible/json/temp
mkdir -p /ansible/json-ready
#каталог куда Ansible кладет скачанные json файлы с узлов
ja="/ansible/json"
#временный каталог куда Ansible складывает все json файлы из всех каталогов узлов перед сведением информации в единый файл json
jrt="/ansible/json/temp"
#каталог куда Ansible помещает сводный json файл со всей добытой информацией по узлам
jr="/ansible/json-ready"
#обработка файлов и удаление временных промежуточных результатов
cp -i $(find /$ja -iname "*.json") $jrt
cd $jrt
jq -s '.[0] * .[1] * .[2] * .[3]' *.json > "$jrt"/temp.json
cat "$jrt"/temp.json | sed 's/{}/\"нет докеров\"/' > "$jr"/final_result_po.json
#удаление временных каталогов и файлов
rm -rf $jrt
rm -rf $ja
Сделаем файл скрипта исполняемым:
# chmod +x /ansible/make-final-json-file.sh
Результатом работы скрипта будет сводный json файл всех четырёх final_result_po.json
в каталоге /ansible/json_ready
на Ansible master сервере:
Текстовый файл:
{
"Информация об узлах": {
"cos7client1.hamsterden.loc": {
"Софт": {
"Версия чего-то": "9.11.2"
},
"Докеры на узле": {
"wordpress-compose_nginx_1": "nginx:latest",
"wordpress-compose_wordpress_1": "wordpress:php7.4-fpm-alpine",
"wordpress-compose_pma_1": "phpmyadmin/phpmyadmin",
"wordpress-compose_mysql_1": "mariadb"
}
},
"cos7client2.hamsterden.loc": {
"Софт": {
"Версия чего-то": "10.2.1"
},
"Докеры на узле": "нет докеров"
},
"cos7client3.hamsterden.loc": {
"Софт": {
"Версия чего-то": "9.3.4"
},
"Докеры на узле": "нет докеров"
},
"emachines.hamsterden.loc": {
"Докеры на узле": {
"onlyoffice": "onlyoffice/documentserver",
"funny_heisenberg": "onlyoffice/documentserver"
}
}
}
}
Если открыть final_result_po.json
файл в браузере Mozilla Firefox, то информация будет корректно визуализирована в удобно читаемом виде:
Задача выполнена!
X. Оригиналы источников информации.
- golinuxcloud.com «Working with Ansible facts | Create custom facts with examples».
- github.com «Ansible local fact example».
- medium.com «Custom facts for Ansible».
- otus.ru «Ansible: формируем переменные на всех хостах с Custom facts».
- mydailytutorials.com «Working with Ansible facts – retrieving facts».
- adyxax.org «Ansible custom factsAnsible custom facts».
- Источник: https://hamsterden.ru/ansible-collecting-arbitrary-information-on-all-hosts-with-custom-facts/
Was this helpful?
1 / 0