1. Предисловие

Развертывание ИТ-инфраструктуры с нуля — задача интересная и трудозатратная. Особенно, когда речь не о постепенном развитии (как это часто случается при поступательно-линейном росте бизнеса и, соответственно, его потребностей), а о куда более сжатых сроках, например, при открытии филиала или обособленного подразделения (другой вариант — необходимость в короткие сроки развернуть инфраструктуру для тестирования), где важную роль играет организация сети.

Конечно, первоначальная установка и настройка — это всегда полевая работа: монтаж СКС, сетевого оборудования и серверов; конфигурирование DHCP и организация удалённого доступа; иногда — заведение VLAN-ов.

2. Описание задачи

Итак, представим, что первичная настройка сети проведена: монтаж СКС осуществлён, DHCP выдал всем устройствам IP-адреса, удалённый доступ до сети филиала (или обособленного подразделения) в наличии, на одни сервера заведены 2 (или более) физических соединения для организации BOND-ов, на другие поданы транковые соединения с несколькими VLAN-ами и т.д.

Список IP-адресов серверов сведён в таблицу и доступ по SSH в наличии. Если размер списка невелик (например, до 3-5 единиц), то ручная настройка покажется неплохим вариантом, хоть и отнимет какое-то время.

А если список содержит, например, 10 (или более) хостов, на части из которых необходима уникальная сетевая конфигурация (разделение trunk-соединения на vlan-ы, виртуальные bridge-ы, etc)? Тут уж временные затраты существенно возрастают.

Но нет необходимости тратить время на рутину, если готовое решение есть и ожидает вас ниже (со ссылкой на guthub-репозиторий в конце публикации).

3. Стек технологий

1) Ansible. Весьма популярен (хотя кому-то ближе Puppet, Chef или Salt). Применяется для доставки контента/команд на целевые хост-системы.

2) Командная оболочка Bash. Присутствует во всех linux-системах. В рамках решения используется как для создания оболочки над Ansible, так и для отложенного выполнения операций (если конкретнее — отката сетевых настроек по таймеру) на целевых хостах.

3) Perl 5. Отличный инструмент в умелых руках. С помощью этого ЯП написан функционал генерации ifcfg-файлов на основе текстового конфига (т.е. Perl задействован только на ansible-хосте).

4) Network-scripts. Хоть и не включён в минимальный вариант установки ОС семейства RHEL8, но является проверенным средством настройки сетевой подсистемы.

4. Концепция приложения

Приложение «conf_int_ipv4_via_network_scripts» (ansible-приложение) представляет собой набор perl/bash-скриптов и файлов конфигурации (inventory-file, etc). Хотя и является составной частью репозитория «ansible_helpers», но имеет автономный характер.

5. Описание приложения

5.1. Структура директорий

1. Корневой раздел (условно обозначим «../»). Содержит все основные скрипты поддиректории.

2. Директория с дополнительными конфигами («../additional_configs»). Содержит дополнительные файлы конфигурации, с помощью которых возможно задать содержание resolv.conf (указать NS-сервера), таймаут отката конфигурации и опцию удаления неиспользуемых ifcfg-файлов на стороне целевых хостов.

3. Директория с playbook-ами («../playbooks), которая в свою очередь имеет свои подразделы:

3.1) dyn_ifcfg_playbooks. Тут динамически генерируеются уникальные для каждого хоста плейбуки, ifcfg-файлы и настройки dns (resolv.conf).

3.2) ifcfg_backup_from_remote. Содержит резервные копии сетевых настроек с привязкой к дате («history»), текущую конфигурацию до изменения («now») и полную информацию о сетевых интерфейсах («network_data»).

3.3) ifcfg_tmplt. Как следует из названия, хранит шаблоны ifcfg-конфигураций, на основе которых формируются уникальные для каждого inventory-хоста настройки сети.

3.4) scripts_for_local. Хранит скрипты для исполнения на ansible-хосте. В данном случае подразумевается скрипт преобразования сырых данных в файлы c информацией о сетевых интерфейсах (размещаются в директории «../ifcfg_backup_from_remote/network_data»).

3.5) scripts_for_remote. Скрипты для исполнения на удалённых хостах. В данном случае он один — rollback_ifcfg_changes.sh (скрипт отката к предыдущим настройкам сетевой подсистемы).

6) tasks. Используемые в плейбуках файлы задач.

4. «../run_history». Логи запуска/исполнения сценариев приложения.

5.2. Файлы конфигурации

1. «../conf_network_scripts_hosts» — inventory-файл приложения.

2. «../config» – основной файл конфигурации приложения. Также имеется файл «config_examples» с примерами настроек. Для получения имён сетевых интерфейсов и соответствующих им MAC-адресов, требуемых при заполнении файла «config», необходимо запустить скрипт «just_run_ifcfg_backup.sh» и ознакомиться с файлом «../playbooks/ifcfg_backup_from_remote/network_data/inv_hosts_interfaces_info.txt».

3. «../additional_configs/config_del_not_configured_ifcfg» - задаёт действие относительно тех ifcfg-файлов, которые не сконфигурированы в «../config». Если в «config_del_not_configured_ifcfg» вписать адрес хоста, то ansible-приложение удалит на remote-хосте все ifcfg-файлы, выключит соответствующие интерфейсы («ifdown») и удалит линки (через «ip link delete»), но только те, которые относятся к bond/bridge и vlan-интерфейсам (например, eth0.100). Настройка будет полезна в случая, когда, например, требуется переименовать какое-либо bond/bridge-соединение.

4. «../additional_configs/config_temporary_apply_ifcfg» - тут возможно задать таймаут (как общий, так и для различных inventory-хостов индивидуально) отката к предыдущим настройкам.

5. «../additional_configs/dns_settings». Предоставляет возможность выставить настройки dns индивидуально для каждого inventory-хоста.

5.3. Скрипты и их назначение

1. «install_network_scripts_and_configure_network.sh» - производит бэкап ifcfg-файлов, устанавливает «network-scripts» (если функционал не установлен ранее), проверяет статус сервиса «network.service» (если не запущен, то стартует), исполняет скрипт «generate_dynamic_ifcfg.pl» и применяет изменения сетевых настроек (заданных в файле «config») на удалённых хостах (если, конечно, настройки корректны).

2. «just_install_network_scripts.sh» устанавливает «network-scripts» (если функционал не установлен ранее).

3. «just_run_ifcfg_backup.sh» - производит бэкап ifcfg-файлов.

4. «check_network_scripts_serv_is_started.sh» - проверяет статус сервиса «network.service» (если не запущен, то стартует).

5. «check_ifcfg_without_apply.sh» - проверяет корректность сетевых настроек (файл «config»).

6. «apply_temporary_ifcfg.sh» - временно применяет сетевые настройки. Таймаут отката задается в конфиге «../additional_configs/config_temporary_apply_ifcfg».

7. «apply_immediately_ifcfg.sh» - немедленно применяет новые сетевые настройки, если, конечно, они изменились с момента предыдущего запуска (в т.ч. если были внесены какие-либо изменения вручную на удалённых хостах).

6. Постскриптум

Ссылка на репозиторий

В README-файле перечислены как уже готовые приложения, так и те, статус которых варьируется от «в процессе» до «есть в планах».

Спокойного кодинга всем причастным!

Комментарии (8)


  1. wizard_s
    20.11.2022 22:22
    +3

    Ansible, Perl, Bash - почему нельзя сделать на чем-то одном? У вас уже есть ansible, который может и конфиги рендерить как угодно и дергать systemd. Дальше при таком подходе обычно появляются матрешки типа "bash запускает ansible, который рендерит bash, который дергает systemd". А потом приходит новый сотрудник и хватается за голову в попытке понять, что там происходит.

    Ой, матрешка уже есть...

    		print DYN_YML "- name: copy script 'rollback_ifcfg_changes.sh' to remote\n";
    		print DYN_YML "  ansible.builtin.copy:\n";
    		print DYN_YML "    src: \"{{playbook_dir}}/../scripts_for_remote/rollback_ifcfg_changes.sh\"\n";
    		print DYN_YML "    dest: \"~/rollback_ifcfg_changes.sh\"\n";
        		print DYN_YML "    mode: '0700'\n";
    		print DYN_YML "\n";
    		print DYN_YML "######################################################\n";
    		print DYN_YML "\n";


    1. Vladimir_Chursin Автор
      20.11.2022 22:25
      -3

      Продемонстрируйте, пожалуйста, как с помощью одного ansible можно прописать уникальную конфигурацию сети для N элементов.


      1. wizard_s
        20.11.2022 22:32
        +1

        Вариантов много. Можно конфиги зашаблонизировать и включать отдельные блоки через if. Можно в конфиги макросы положить для генерации этих блоков по подставленным параметрам. Можно просто папки в templates наделать по отдельным хостам или группам хостов. Можно netplan воткнуть и весь конфиг описывать в ямле, ямлы складировать по хостам, внутри шаблоны опять же блоками через макросы сделать. Настройки положить в host/group_vars. Можно тем же способом systemd конфиги раскладывать:

            - name: Copy netplan config
              template:
                src: "roles/netplan/templates/etc/netplan/95-{{ inventory_hostname }}.yaml"
                dest: "/etc/netplan/95-{{ inventory_hostname }}.yaml"
        


        1. Vladimir_Chursin Автор
          20.11.2022 22:35
          -1

          1) Netplan - это не про RHEL, а про Ubuntu.
          2) А вот так, чтоб через один конфиг проводить настройки, есть варианты на чистом ansible?


          1. wizard_s
            20.11.2022 22:49

            Я не про конкретный ansible, netplan. У меня посыл в том, что поддерживать 4 сущности в едином инструменте - перебор. Если вы взялись за perl, у вас в нем есть экспертиза, там приличный кусок кода написан и он, наверное, полезен, зачем вам там еще bash и тем более зачем из перлового скрипта генерить yaml таски для ansible, которые будут запускаться питоном? Чтобы дополнительно еще отлаживать проблемы миграции между версиями ansible и еще версиями питона на разных машинах?


            1. Vladimir_Chursin Автор
              20.11.2022 22:53
              -1

              Perl используется только на хосте с ansible.
              Bash - для отката конфигурации. И я это в публикации описал.


          1. wizard_s
            21.11.2022 01:20
            +1

            Как один из вариантов на ansible (ну примесь шелла будет наверное) для хранения настроек можно взять yaml по типу конфига netplan или cloud-init. Они практически стандартные и в случае чего можно будет прямо напрямую в некоторые системы подсовывать. А для тех, где нетплана нет, сделать рендерер на ansible (собственно, чем netplan и занимается для бэкендов). Можно в один файл положить, можно разложить по отдельному файлу на хост.

            host:
              ethernets:
                eth1:
                  dhcp4: no
                eth2:
                  dhcp4: no
              bonds:
                bond0:
                  interfaces: [ eth1,eth2 ]
                  parameters:
                    mode: 802.3ad
                    lacp-rate: fast
                    mii-monitor-interval: 100
              vlans:
                vlan10:
                  id: 10
                  link: bond0
              bridges:
                br10:
                  interfaces: [ vlan10 ]
                  addresses: [ "1.2.3.4/24" ]
                  routes:
                    - to: a.b.c.d
                      via: "{{ common_gw_variable }}" а ее положить в group_vars/all
            
            в ansible раскладывать конфиги так
              - template: src=ifcfg-bond-template dest=ifcfg-bond-{{ item }}
                with_items: тут bonds/bridges/ethernets
            
            или в jinja шаблонах через for по листу или дикту
            
            для манипуляций с текущими интерфейсами и адресами есть факты хоста
            со всякими переменными типа ansible_eth0.ipv4.address
            и фильтры типа |ipaddr()

            А можно вообще поставить netbox и использовать его как источник данных, хоть для ansible, хоть для perl

            бэкап-возврат конфигурации можно делать по-разному, зависит от системы и желаний. Один из вариантов - переименовывать на хосте папку с конфигами целиком, класть новые конфиги, типовой скрипт по крону регулярно проверяет, не появилась ли метка на хосте (ее кладем в конце плейбука где-нибудь после проверки доступности сети), если не появилась - переименовываем обратно. Можно через симлинки придумать систему. Главное чтобы скрипт был максимально одинаковый и простой.

            Ну а если у вас все равно есть рендеринг в perl, то уж копирование файлов на нем без ansible сделать проблем не должно составить. Ansible большой, тяжелый и имхо если не использовать его возможности вроде переменных, шаблонов, макросов, фильтров, то лучше вообще на него не завязываться.


    1. Vladimir_Chursin Автор
      20.11.2022 22:26
      -3

      А также реализовать откат конфигурации по таймауту.