Гид по технологиям

Управление серверами с Rex — лучшие практики

4 min read DevOps Обновлено 07 Nov 2025
Управление серверами с Rex — лучшие практики
Управление серверами с Rex — лучшие практики

Описание и назначение

(R)?ex — инструмент оркестрации и управления конфигурацией серверов. С его помощью вы управляете набором машин из единой точки: настраиваете пакеты, загружаете конфигурации, деплоите ПО. Задачи описываются в центральном Rexfile или в модулях на чистом Perl и выполняются по SSH.

Коротко: Rex похож на Make, но для администрирования серверов. Официальный сайт: http://rexify.org/.

Важно: в руководстве использован Subversion и Ubuntu 12.04 в качестве примера. Для современных дистрибутивов может потребоваться адаптация путей и команд (systemd vs init, пути к конфигурации Apache/MySQL и т. п.).

Предисловие

В примерах ниже я использую Subversion для хранения задач (Tasks). Можно применять любую SCM-систему, поддерживающую аналоги механизма externals в Subversion. Я использую рабочую станцию и несколько серверов:

  • Subversion server — svn01
  • Database Server — db01
  • Web Server — web01
  • Workstation — wks01

Я опущу префикс sudo в большинстве команд; используйте sudo там, где это требуется.

Цели примера: показать структуру репозиториев, модулей и шаблонов для двух проектов: website и database, при этом общие задачи (common) используются обеими командами.

Подготовка хранилищ кода

Для начала установите на Subversion-сервере необходимые пакеты. Выполните на svn01:

svn01# apt-get install libapache2-svn subversion apache2-mpm-prefork

Отредактируйте файл /etc/apache2/mods-enabled/dav_svn.conf, заменив его содержимое на следующий фрагмент:


  DAV svn
  SVNParentPath /var/lib/svn
  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile /etc/apache2/dav_svn.passwd
  
    Require valid-user
  

Создайте каталог /var/lib/svn и репозитории:

svn01# mkdir /var/lib/svn  
svn01# cd /var/lib/svn  
svn01 /var/lib/svn# svnadmin create common  
svn01 /var/lib/svn# svnadmin create service  
svn01 /var/lib/svn# svnadmin create database  
svn01 /var/lib/svn# svnadmin create website  
svn01 /var/lib/svn# chown -R www-data: .

Настройте пользователей для доступа через Apache:

svn01# htpasswd -c /etc/apache2/dav_svn.passwd your-user-name

Перезапустите Apache:

svn01# service apache2 restart

Поздравляю — Subversion-сервер готов. Переходим на рабочую станцию и делаем checkout репозиториев.

Написание задач (Tasks)

На рабочей станции выполняем:

wks01# svn co http://svn01/svn/common Common  
wks01# svn co http://svn01/svn/service Service  
wks01# svn co http://svn01/svn/database  
wks01# svn co http://svn01/svn/website

Создадим общую задачу для установки и настройки NTP. Перейдите в каталог Common и создайте файл NTP.pm:

wks01# cd Common
# Common/NTP.pm
package Common::NTP;
use Rex -base;
task prepare => sub {
   install "ntp";
   file "/etc/ntp.conf",
      source => "files/ntp.conf",
      on_change => sub {
         service ntp => "restart";
      };
};
1;

Этот модуль регистрирует задачу prepare в пространстве имён NTP. Она устанавливает пакет ntp и загружает конфигурацию /etc/ntp.conf; при изменении файла перезапускается сервис ntp.

Создайте каталог для файлов конфигурации и добавьте ntp.conf:

bash Common# mkdir files

Содержимое files/ntp.conf (простой пример):

# /etc/ntp.conf, managed with rex
driftfile /var/lib/ntp/ntp.drift
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
server 0.ubuntu.pool.ntp.org
server 1.ubuntu.pool.ntp.org
server 2.ubuntu.pool.ntp.org
server 3.ubuntu.pool.ntp.org
# Use Ubuntu's ntp server as a fallback.
server ntp.ubuntu.com
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery
# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1
restrict ::1

Добавим файлы в репозиторий:

wks01 Common# svn add NTP.pm files  
wks01 Common# svn ci -m "added NTP task"

Теперь переходим к репозиторию service и создаём модули для Apache и MySQL.

wks01 Common# cd ../Service  
wks01 Service# touch Apache.pm MySQL.pm

Добавьте в Apache.pm следующий код:

package Service::Apache;
use Rex -base;
task prepare => sub {
   install "apache2";
};
task configure => sub {
   my $param = shift;
   file "/etc/apache2/apache2.conf",
      owner => "root",
      mode => 644,
      content => template("templates/apache2/apache2.conf.tpl", %{ $param });
   file "/etc/apache2/conf.d/security",
      owner => "root",
      mode => 644,
      content => template("templates/apache2/conf.d/security.tpl", %{ $param });
};
1;

Создайте шаблоны:

wks01 Service# mkdir -p templates/apache2/conf.d

Содержимое templates/apache2/apache2.conf.tpl (сокращённый, без комментариев):

LockFile /var/run/apache2/accept.lock
PidFile /var/run/apache2.pid
Timeout <%= is_defined($::timeout, "300") %>
KeepAlive <%= is_defined($::keepalive, "On") %>
MaxKeepAliveRequests <%= is_defined($::max_keepalive_requests, "100") %>
KeepAliveTimeout <%= is_defined($::keepalive_timeout, "5") %>

    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0


    StartServers          2
    MinSpareThreads      25
    MaxSpareThreads      75 
    ThreadLimit          64
    ThreadsPerChild      25
    MaxClients          150
    MaxRequestsPerChild   0


    StartServers          2
    MinSpareThreads      25
    MaxSpareThreads      75 
    ThreadLimit          64
    ThreadsPerChild      25
    MaxClients          150
    MaxRequestsPerChild   0

User <%= is_defined($::user, "www-data") %>
Group <%= is_defined($::group, "www-data") %>

AccessFileName .htaccess

    Order allow,deny
    Deny from all
    Satisfy all

DefaultType None

HostnameLookups <%= is_defined($::hostname_lookups, "Off") %>
ErrorLog <%= is_defined($::error_log, "/var/log/apache2/error.log") %>
LogLevel <%= is_defined($::log_level, "warn") %>
Include mods-enabled/*.load
Include mods-enabled/*.conf
Include httpd.conf
Include ports.conf
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

Include conf.d/
Include sites-enabled/

Шаблон templates/apache2/conf.d/security.tpl:

ServerTokens <%= is_defined($::server_tokens, "Prod") %>
ServerSignature <%= is_defined($::server_signature, "Off") %>
TraceEnable <%= is_defined($::trace_enable, "Off") %>

Модуль MySQL (Service/MySQL.pm):

package Service::MySQL;
use Rex -base;
task prepare => sub {
   install "mysql-server";
};
task configure => sub {
   my $param = shift;
   file "/etc/mysql/my.cnf",
      owner => "root",
      mode => 644,
      content => template("templates/mysql/my.cnf.tpl", %{ $param });
};
1;

Шаблон templates/mysql/my.cnf.tpl:

[mysqld]
user     = <%= is_defined($::user, "mysql") %>
pid-file = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port     = <%= is_defined($::port, "3306") %>
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir   = /usr/share/mysql
skip-external-locking
bind-address      = <%= $::eth0_ip %>
key_buffer     = <%= is_defined($::key_buffer, "16M") %>
max_allowed_packet   = <%= is_defined($::max_allowed_packet, "16M") %>
thread_stack      = <%= is_defined($::thread_stack, "192K") %>
thread_cache_size       = <%= is_defined($::thread_cache_size, "8") %>
myisam-recover         = BACKUP
query_cache_limit = <%= is_defined($::query_cache_limit, "1M") %>
query_cache_size        = <%= is_defined($::query_cache_size, "16M") %>
expire_logs_days  = <%= is_defined($::expire_logs_days, "10") %>
max_binlog_size         = <%= is_defined($::max_binlog_size, "100M") %>

[mysqldump]
quick
quote-names
max_allowed_packet   = <%= is_defined($::max_allowed_packet, "16M") %>
[mysql]
[isamchk]
key_buffer     = <%= is_defined($::key_buffer, "16M") %>
!includedir /etc/mysql/conf.d/

Добавляем файлы и отправляем в репозиторий:

wks01 Service# svn add *  
wks01 Service# svn ci -m "inital commit of apache and mysql service"

Поздравляю — у вас появились первые общие модули, которые можно повторно использовать в проектах website и database. Далее вы можете создавать проектные модули, подключать общие (common) задачи и ограничивать права команд.

Модель мышления и рекомендации

  • Разделяйте роли: общие задачи (мониторинг, NTP, логирование) в common; сервисы (apache, mysql) — в service; проектная логика — в отдельных репозиториях website/database. Это упрощает делегирование и ревизию.
  • Модуль — атомарная единица управления: каждая задача должна делать одну вещь (установка пакета, загрузка файла, перезапуск сервиса).
  • Идем от идемпотентности: описывайте конечное состояние, а не последовательность команд. Rex и шаблоны помогают поддерживать идемпотентность.

Чек-листы по ролям

Системный администратор:

  • Настроить и протестировать доступ к SVN (htpasswd, права Apache).
  • Обеспечить доступ SSH от Rex-клиента к целевым хостам.
  • Проверить шаблоны конфигураций на тестовом сервере.
  • Настроить мониторинг перезапуска сервисов при изменении конфигураций.

Администратор БД:

  • Протестировать шаблон my.cnf с реальными параметрами сети (bind-address).
  • Убедиться, что резервные копии (backup) и права доступа настроены отдельно от Rex.
  • Проверить совместимость версий MySQL и параметров в my.cnf.

Когда подход может не подойти

  • Малые инфраструктуры (1–2 сервера) где централизованное управление усложнит процесс.
  • Сценарии с закрытыми примитивными окружениями без SSH-доступа.
  • Если требуется трансакционная постановка изменений с откатом на уровне БД — Rex управляет конфигурацией, но откат сложных схем данных потребует отдельного процесса.

Советы по совместимости и миграции

  • Ubuntu 12.04 используется здесь для примера; в современных дистрибутивах могут отличаться:
    • Директивы и пути Apache (mods-enabled, conf.d, systemd unit file).
    • Инициализация сервисов: systemd вместо init/upstart — используйте service/systemctl в Rex-скриптах подходящим образом.
  • Проверяйте шаблоны на тестовой среде перед массовым применением.

Критерии приёмки

  • Задача Rex выполняется без ошибок на тестовом хосте.
  • После запуска конфигурационные файлы соответствуют шаблонам.
  • Сервис перезапускается при изменении конфигурации.
  • Репозитории доступны и имеют корректные права доступа.

Decision flow (когда применять Rex)

flowchart TD
  A[Есть >2 сервера?] -->|да| B[Нужно централизованное управление?]
  A -->|нет| Z[Возможно, Rex избыточен]
  B -->|да| C[Есть SSH-доступ к хостам?]
  B -->|нет| Z
  C -->|да| D[Подходит Rex]
  C -->|нет| Z

Критические замечания по безопасности

  • Храните доступы к Subversion и ключи SSH с ограниченным доступом.
  • В шаблонах избегайте включать пароли или секреты в виде открытого текста; используйте секретное хранилище или шифрование.

Краткое резюме

Rex даёт простую и гибкую модель для управления конфигурацией через модули на Perl. Разделение на common/service/project облегчает поддержку и делегирование работ. Тестируйте шаблоны и учитывайте отличия современных дистрибутивов (systemd, пути конфигураций).

Заметки: при переносе на современную инфраструктуру проверьте systemd-юниты и пути к конфигурационным директориям Apache/MySQL.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Herodotus: механизм и защита Android‑трояна
Кибербезопасность

Herodotus: механизм и защита Android‑трояна

Включить новое меню «Пуск» в Windows 11
Windows руководство

Включить новое меню «Пуск» в Windows 11

Панель полей сводной таблицы в Excel — руководство
Excel

Панель полей сводной таблицы в Excel — руководство

Включить новое меню «Пуск» в Windows 11
Windows 11

Включить новое меню «Пуск» в Windows 11

Дубликаты Диспетчера задач в Windows 11 — как исправить
Windows

Дубликаты Диспетчера задач в Windows 11 — как исправить

История просмотров Reels в Instagram — как найти
Instagram

История просмотров Reels в Instagram — как найти