Ansible: Сбор произвольной информации на хостах с помощью Ansible custom facts. Вывод информации в формате *.json.

На чем было опробовано:




  1. Ansible 2.9.18
  2. Hyper-V на Windows 10 Pro.
  3. Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
  4. Node 1: CentOS Linux release 7.9.2009 (Core).
  5. Node 2: CentOS Linux release 7.9.2009 (Core).
  6. Node 3: CentOS Linux release 7.9.2009 (Core).
  7. Node 4: CentOS Linux release 7.9.2009 (Core).








1. Задача.




К примеру, нам требуется с помощью внедрения custom facts для Ansible организовать сбор версий контейнеров, запущенных на серверах, а так же сбор версий некоторого программного обеспечения на серверах, которое имеет файл с указанием версии в своём каталоге /ecp/po/version.txt.




Собранная информация должна формироваться в json-формат.




Дополнительно требуется рассмотреть средства визуализации информации в удобном виде (opensource web-приложения).




2. Решение задачи.




Решение будет состоять из нескольких этапов:







В системе Ansible есть возможность собирать системную информацию, которая собирается в виде фактов с помощью встроенного модуля setup.




Со сбором стандартных переменных по умолчанию всё предельно ясно, но что делать, если мы хотим сформировать наши собственные переменные на всех хостах, чтобы в дальнейшем использовать их в нашем коде?




Для этого существует возможность добавления Custom facts, что делается следующим образом:







Создаем инвентарь 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. Оригиналы источников информации.




  1. golinuxcloud.com «Working with Ansible facts | Create custom facts with examples».
  2. github.com «Ansible local fact example».
  3. medium.com «Custom facts for Ansible».
  4. otus.ru «Ansible: формируем переменные на всех хостах с Custom facts».
  5. mydailytutorials.com «Working with Ansible facts – retrieving facts».
  6. adyxax.org «Ansible custom factsAnsible custom facts».
  7. Источник: https://hamsterden.ru/ansible-collecting-arbitrary-information-on-all-hosts-with-custom-facts/






2021-09-01T15:48:22
Software