Автоматизация профилей маршрутизации: как упростить настройку и поддержку | AdminWiki

Автоматизация профилей маршрутизации: как упростить настройку и поддержку

05 сентября 2026 12 мин. чтения

Автоматизация профилей маршрутизации строится вокруг единого описания сетевого состояния: маршруты, шлюзы, интерфейсы, метрики, таблицы и правила хранятся в Git, проходят проверку и применяются подходящим инструментом. Для Linux это systemd-networkd, NetworkManager или скрипты с iproute2, для облачных сетей Terraform, для группы серверов Ansible, для Kubernetes CNI-плагин и манифесты NetworkPolicy.

Профиль маршрутизации представляет собой версионируемый набор правил, который определяет путь трафика для хоста, виртуальной машины, контейнерной сети или отдельного класса запросов. В профиль входят статические маршруты, маршрут по умолчанию, шлюзы, интерфейсы, метрики, дополнительные таблицы и правила policy-based routing. Секреты для BGP, VPN и других сервисов хранятся отдельно от репозитория.

На сервере профиль применяет сетевой менеджер или systemd unit. В Docker маршруты создаются при подключении контейнера к пользовательской сети. В Kubernetes связность между узлами и подами настраивает CNI, а NetworkPolicy ограничивает разрешенный трафик. В облаке нужно синхронизировать два слоя: таблицу маршрутов виртуальной сети и таблицу маршрутов внутри гостевой ОС.

Зачем автоматизировать профили маршрутизации

Профиль маршрутизации не считается отдельным объектом в iproute2. Это управляемое описание ожидаемой сетевой конфигурации. Такой подход отделяет намерение от конкретной команды: вместо ручного набора ip route add администратор меняет параметры профиля и запускает проверенный процесс применения.

Ручная настройка быстро становится источником расхождений. На одном сервере маршрут добавили через ens18, на другом интерфейс называется eth0. На третьем забыли метрику, а на четвертом повторная команда создала конфликтующее правило. Ошибка в шлюзе может оборвать SSH-сессию и нарушить связь с внутренними подсетями.

Допустим, на 36 серверах нужно изменить по два маршрута. Если ручная проверка и применение занимают 10 минут на хост, суммарная операция требует около 6 часов работы. Плейбук с переменными, проверкой и последовательным запуском сокращает рутину, а журнал выполнения показывает, на каком узле возникла проблема.

  • Единый источник конфигурации. Все изменения проходят через один репозиторий и имеют историю.
  • Воспроизводимость. Новый сервер получает тот же профиль при совпадении роли, среды и сетевых параметров.
  • Масштабирование. Одно изменение можно применить к группе узлов с ограничением параллельности.
  • Контроль риска. До запуска проверяются CIDR, шлюз, метрики, приоритеты правил и пересечения подсетей.
  • Быстрый откат. Предыдущая версия профиля остается доступной в Git и в артефактах CI/CD.

Для общего подхода к автоматизации серверных задач полезно использовать готовые примеры автоматизации инфраструктуры, а маршрутизацию вынести в отдельный профиль с четким владельцем.

Что централизовать: ключевые параметры маршрутизации

Централизованное хранилище должно содержать параметры, которые повторяются на нескольких хостах или требуют согласованного изменения. Обычно это Git-репозиторий с YAML, JSON, HCL или шаблонами конфигурации. Переменные среды и параметры командной строки подходят для окружения и точечных переопределений, но их порядок должен быть заранее описан.

Практичная схема имеет четыре слоя: базовый профиль, настройки среды, переменные группы хостов и параметры конкретного узла. Если список маршрутов объединяется через append, один и тот же маршрут может появиться дважды. Для таких списков безопаснее явно определить замену или проверять уникальность ключа destination, table, gateway и interface.

ПараметрПримерЧто проверять
destination10.20.0.0/16Корректный CIDR и отсутствие нежелательного пересечения
gateway192.0.2.1Доступность через выбранный интерфейс
interfaceens18Наличие интерфейса на конкретном типе ОС или VM
metric100Приоритет среди маршрутов с одинаковым префиксом
table100Связь с правилами policy-based routing
priority100Порядок обработки правил ip rule
BGP или OSPFСосед, ASN, сетьВерсию демона, владельца настройки и способ хранения секретов

Статические маршруты и шлюзы

Профиль статических маршрутов обычно содержит маршрут по умолчанию, пути к внутренним подсетям и специальные маршруты для VPN-туннелей. Для каждого правила задаются destination, gateway, interface и metric. Названия интерфейсов и адреса лучше хранить в переменных хоста, если образы виртуальных машин отличаются.

routes:
  - destination: 10.20.0.0/16
    gateway: 192.0.2.1
    interface: ens18
    metric: 100
  - destination: 10.30.0.0/16
    gateway: 192.0.2.1
    interface: ens18
    metric: 110

Маршрут с более длинным префиксом выбирается раньше общего маршрута. Метрика сравнивает маршруты с одинаковым назначением и влияет на выбор предпочтительного пути. Несколько default route допустимы только при понятной схеме отказоустойчивости и проверенных метриках.

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

Policy-based routing и таблицы маршрутизации

Policy-based routing выбирает таблицу по источнику, назначению, метке пакета или другим условиям. В Linux правила хранятся через ip rule, а маршруты для каждой политики через ip route с параметром table. Меньшее значение priority обрабатывается раньше большего, поэтому приоритеты должны быть уникальными и документированными.

routing_tables:
  corp: 100

rules:
  - priority: 100
    from: 10.30.0.0/24
    table: corp

routes:
  - table: corp
    destination: 10.40.0.0/16
    gateway: 192.0.2.1
    interface: ens18
    metric: 100

Перед добавлением правила подготовьте маршруты в целевой таблице и проверьте их через ip route get. При откате сначала удаляйте правило, которое направляет трафик в проблемную таблицу, затем очищайте ее маршруты. Имена таблиц и их номера храните рядом с профилем, чтобы оператор не сопоставлял значения вручную.

Если сеть использует BGP или OSPF, централизуйте список соседей, ASN, анонсируемые сети, таймеры и параметры выбора пути. Конфигурации динамической маршрутизации лучше отделять от статических маршрутов на уровне ролей и шаблонов. Так проще определить, какой компонент имеет право менять конкретный маршрут.

Автоматизация на серверах Linux

Сначала выберите одного владельца сетевой конфигурации. systemd-networkd, NetworkManager, netplan и собственный скрипт могут перезаписывать состояние друг друга. На одном интерфейсе не следует одновременно задавать постоянные маршруты через NetworkManager и systemd-networkd.

Использование systemd-networkd

systemd-networkd описывает сеть декларативными файлами .network. Пример ниже предполагает статический адрес на интерфейсе ens18 и маршрут к подсети 10.20.0.0/16 через шлюз 192.0.2.1.

[Match]
Name=ens18

[Network]
Address=192.0.2.10/24

[Route]
Destination=10.20.0.0/16
Gateway=192.0.2.1
Metric=100

Сохраните профиль, например, в /etc/systemd/network/10-static-route.network. После проверки конфигурации перечитайте файлы и перенастройте интерфейс:

sudo networkctl reload
sudo networkctl reconfigure ens18
ip route show dev ens18
ip route get 10.20.1.10

При старте системы systemd-networkd применит маршрут вместе с сетевым профилем. Параметр GatewayOnLink=yes нужен в ситуации, когда шлюз не определяется как адрес непосредственно подключенной сети. Используйте его только после проверки топологии, иначе система может принять ошибочный шлюз.

Для Linux-команд, netplan и systemd-networkd пригодится пошаговое руководство по маршрутизации в Linux. Синтаксис отдельных параметров зависит от версии systemd и выбранного сетевого менеджера.

Скрипты и утилиты командной строки

Скрипт с ip route подходит для временной настройки, аварийного восстановления или среды без подходящего сетевого менеджера. Для повторного запуска используйте replace, а не безусловный add. Это предотвращает ошибку при существующем маршруте и поддерживает идемпотентное поведение.

#!/usr/bin/env bash
set -euo pipefail

dev=ens18
route=10.20.0.0/16
gateway=192.0.2.1
metric=100

ip link show dev ${dev} >/dev/null
ip route replace ${route} via ${gateway} dev ${dev} metric ${metric}
ip route get 10.20.1.10

Для постоянного применения запускайте скрипт через systemd unit после появления сети:

[Unit]
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/apply-routes
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

После установки unit включите его через systemctl enable --now имя-сервиса.service. Cron подходит для периодической проверки, но хуже контролирует порядок запуска, блокировки и журналирование. Если скрипт все же запускается из cron, добавьте lock-файл, таймаут и уведомление об ошибке.

Команды с ip route add оставляйте для разовой диагностики. Профиль, который должен переживать перезагрузку, храните в конфигурации systemd-networkd, NetworkManager или другом постоянном источнике.

Для виртуальной машины проверяйте два уровня. Внутри гостевой ОС должна существовать запись в таблице Linux, а в таблице маршрутов VPC или виртуальной сети должен быть обратный путь. Изменение только одного уровня часто дает одностороннюю связность.

Автоматизация в контейнерных средах

Контейнерная маршрутизация отличается от настройки физического сервера. Docker и Kubernetes создают сетевые пространства, виртуальные интерфейсы, bridge, overlay или маршруты между узлами. Ручное изменение таблицы маршрутов хоста может быть перезаписано при перезапуске контейнерного рантайма или CNI.

Docker: сети и маршрутизация

Для приложений создавайте пользовательские сети с заранее зарезервированными подсетями. Пример bridge-сети:

docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  app_net

Docker создаст bridge и добавит связанные маршруты на хосте. Подсеть контейнеров не должна пересекаться с офисной сетью, VPN, подсетями дата-центра и адресным пространством других Docker-сетей. Перед запуском проверьте результат командой docker network inspect app_net.

Конфигурацию сети храните рядом с Compose-файлом или другим описанием приложения. Драйвер bridge подходит для одного хоста. overlay требует согласованной многосерверной схемы и не заменяет маршрутизацию между физическими сетями.

Kubernetes: CNI и NetworkPolicy

CNI-плагин отвечает за адреса подов, виртуальные интерфейсы и связность между узлами. Calico может распространять pod-маршруты через BGP, Flannel часто использует VXLAN, Cilium применяет eBPF-механизмы. Фактическое поведение зависит от настроек кластера и режима работы выбранного CNI.

NetworkPolicy задает разрешенный трафик на уровне L3/L4. Политика фильтрует соединения, но сама по себе не добавляет маршрут в таблицу ядра. Если поды не видят друг друга, сначала проверяйте CNI, адреса и маршруты, затем NetworkPolicy.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-api
  namespace: frontend
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          team: backend
    ports:
    - protocol: TCP
      port: 8080

Эта политика разрешает вход на поды с меткой app: api из namespace с меткой team: backend через TCP-порт 8080. Чтобы запретить остальные входящие соединения, добавьте отдельную default-deny политику и явно опишите нужный egress. Перед применением проверьте, что нужные namespace действительно имеют указанную метку.

Инфраструктура как код для маршрутизации

IaC разделяет описание желаемого состояния и команды его применения. Git хранит профиль, CI проверяет изменения, а инструмент меняет конкретный слой: Ansible настраивает гостевую ОС, Terraform облачные ресурсы, GitOps-контроллер Kubernetes-манифесты.

Ansible для управления маршрутами

Для серверов удобнее шаблонизировать постоянный конфигурационный файл, чем каждый раз выполнять команду ip route. Шаблон остается идемпотентным, а handler применяет изменения только после обновления файла.

- name: Deploy route profile
  hosts: linux_routes
  become: true
  vars:
    route_interface: ens18
    route_destination: 10.20.0.0/16
    route_gateway: 192.0.2.1
    route_metric: 100
  tasks:
    - name: Write networkd profile
      ansible.builtin.template:
        src: 10-static-route.network.j2
        dest: /etc/systemd/network/10-static-route.network
        mode: '0644'
      notify: Reconfigure network
  handlers:
    - name: Reconfigure network
      ansible.builtin.command:
        cmd: networkctl reconfigure {{ route_interface }}

Содержимое 10-static-route.network.j2:

[Match]
Name={{ route_interface }}

[Route]
Destination={{ route_destination }}
Gateway={{ route_gateway }}
Metric={{ route_metric }}

Перед production-запуском используйте ansible-playbook --check --diff, ограничьте первую операцию одним хостом через --limit, затем увеличивайте группу. Если серверы используют NetworkManager, замените handler на применение профиля через nmcli. Готовые плейбуки и структуру dev/prod можно взять из материала про централизованную настройку маршрутов с Ansible.

Terraform для облачных маршрутов

Terraform управляет маршрутами в VPC, VNet и других облачных сетях. Пример для AWS описывает таблицу маршрутов приватной подсети и путь к корпоративной сети через Transit Gateway:

resource "aws_route_table" "private" {
  vpc_id = var.vpc_id

  route {
    cidr_block         = var.corp_cidr
    transit_gateway_id = var.transit_gateway_id
  }
}

resource "aws_route_table_association" "private" {
  subnet_id      = var.subnet_id
  route_table_id = aws_route_table.private.id
}

Перед применением выполните terraform fmt -check, terraform validate и terraform plan. В качестве цели маршрута могут использоваться NAT Gateway, Transit Gateway, сетевой интерфейс или другой поддерживаемый ресурс. Названия ресурсов и допустимые поля зависят от провайдера.

Terraform не заменяет настройку маршрута внутри Linux-гостя. Если приложение в VM обращается к корпоративной подсети, проверьте cloud route table, security rules, гостевой ip route и обратный путь.

GitOps и CI/CD

GitOps подходит для Kubernetes и других декларативных слоев. Pipeline при каждом merge в main может выполнить такие шаги:

  1. Проверить YAML, HCL и шаблоны.
  2. Проверить схему профиля, CIDR, уникальность priority и отсутствие пересечений.
  3. Сформировать Terraform plan или Ansible diff.
  4. Применить изменение в staging.
  5. Проверить доступность целевых подсетей.
  6. Запустить canary на одном или двух узлах.
  7. Раскатить изменение на остальные узлы пакетами, например по 10 процентов.

ArgoCD может синхронизировать Kubernetes-манифесты после проверки в Git. Для серверных профилей аналогичную схему строят на CI-задаче с Ansible. У каждого слоя должен быть один источник истины: Terraform не должен менять ресурс, который одновременно редактирует оператор вручную или другой pipeline.

Готовые сценарии работы с Ansible, Terraform, Bash и Python собраны в практическом гайде по автоматизации для DevOps и сисадминов.

Обеспечение безопасности и контроль изменений

Валидация и тестирование

Проверяйте профиль до изменения сетевого состояния. Минимальный набор правил включает корректность CIDR, отсутствие пересекающихся подсетей, принадлежность шлюза нужному интерфейсу, уникальность приоритетов и допустимый диапазон метрик. Для policy-based routing отдельно проверяйте, что каждая rule ссылается на существующую таблицу.

JSON Schema помогает отклонять неполные профили еще при загрузке. Например, поле gateway можно сделать обязательным для маршрутов через шлюз, а interface обязательным для локального next hop. Для списков маршрутов задайте уникальный составной ключ, чтобы повторная запись не прошла проверку.

Инструменты проверки:

  • ansible-playbook --check --diff показывает изменения без применения.
  • terraform validate проверяет структуру конфигурации, а terraform plan показывает план изменения облачной сети.
  • ip route get 10.20.1.10 показывает выбранный путь для конкретного адреса.
  • ip rule show и ip route show table 100 помогают проверить policy-based routing.
  • traceroute -n или mtr -n показывают, где пропадает трафик.
  • journalctl -u systemd-networkd помогает найти ошибки загрузки профиля.

Сначала тестируйте профиль в отдельной VM или сетевом namespace. Для staging можно поднять несколько VDS и проверить маршруты на изолированной площадке, например в Timeweb Cloud. Docker удобен для проверки шаблонов и сервисных зависимостей, но не всегда воспроизводит реальную сетевую схему хоста.

Производственная проверка должна включать выбранный маршрут, обратный путь, DNS при его использовании и доступность целевого TCP-порта. ICMP-проверка не заменяет тест соединения: межсетевой экран может блокировать ping при рабочем TCP-трафике.

Откат и аудит

Храните в Git базовый профиль, переменные среды, шаблоны и правила слияния. Каждый merge должен содержать описание причины, список затронутых узлов и результат проверки. CI сохраняет plan, diff и журнал применения как артефакты.

Безопасный откат состоит из трех действий: вернуть предыдущую версию профиля, применить ее к canary-хосту, проверить связность и продолжить откат группы. Для удаленных серверов заранее подготовьте консоль провайдера или другой out-of-band-доступ. SSH не должен оставаться единственным способом восстановления после изменения default route.

Конфигурацию обновляйте без перезапуска сервиса только тогда, когда конкретный компонент поддерживает reload или reconfigure. Для systemd-networkd используйте networkctl reconfigure, для NetworkManager повторно активируйте соединение с учетом возможного краткого разрыва. Перед массовым применением проверьте поведение на одном узле.

Секреты для VPN, BGP и API не храните в YAML, Terraform state без защиты или открытых переменных репозитория. Передавайте их через защищенное хранилище секретов, переменные окружения CI или Vault. Доступ к pipeline ограничьте ролями, а применение production-профиля защитите ручным подтверждением.

Типовые ошибки и лучшие практики

ПроблемаПричинаИсправление
Маршрут появился, но трафик не проходитШлюз недоступен через выбранный интерфейс или отсутствует обратный путьПроверить ip route get, адрес интерфейса, cloud route table и обратный маршрут
Пакеты идут через неправильный каналКонфликт метрик или более приоритетное правило ip ruleПроверить ip rule show, таблицы и порядок priority
После повторного запуска появляются ошибкиСкрипт использует ip route add и не проверяет существующее состояниеИспользовать ip route replace или идемпотентный модуль
Маршрут исчезает после перезагрузкиИзменение внесено только в runtime-таблицуЗаписать профиль в systemd-networkd, NetworkManager или другой постоянный источник
Настройки постоянно перезаписываютсяОдин интерфейс одновременно контролируют два сетевых менеджераНазначить одного владельца и отключить конкурирующий механизм
Контейнеры связаны, но доступ запрещенNetworkPolicy блокирует трафик, хотя маршруты CNI исправныПроверить labels, policyTypes, ingress и egress отдельно от таблиц маршрутизации
Массовое применение вызывает простойИзменение отправлено на все узлы без canary и проверкиИспользовать staging, serial-запуск, health check и готовый откат
В профиле раскрыты ключи доступаСекреты записали в Git или открытый state-файлПеренести секреты в защищенное хранилище и проверить историю репозитория

Главная практическая договоренность должна звучать однозначно: кто управляет маршрутом и где лежит его окончательное описание. Для гостевой ОС это может быть Ansible и systemd-networkd, для облачной сети Terraform, для pod-сети CNI. Когда два инструмента считают себя владельцами одного параметра, автоматизация создает новые расхождения.

Заключение

Начните с инвентаризации: сохраните выводы ip route show, ip rule show, список интерфейсов и текущие cloud route tables. Затем опишите один тип маршрутов в YAML или другом выбранном формате, добавьте проверку схемы и разместите профиль в Git.

  1. Выделите статические маршруты, шлюзы, метрики, таблицы и правила policy-based routing.
  2. Разделите настройки общего профиля, среды и конкретного хоста.
  3. Выберите владельца каждого слоя: systemd-networkd, NetworkManager, Ansible, Terraform или CNI.
  4. Проверьте профиль в VM, staging или отдельном сетевом namespace.
  5. Примените его к одному узлу, проверьте маршруты и обратную связность.
  6. Расширьте запуск на группу, сохраняя журнал и предыдущую версию для отката.

Такой порядок сокращает ручные операции и сохраняет контроль над сетевой конфигурацией. После статических маршрутов можно добавить policy-based routing, облачные таблицы, BGP или Kubernetes-политики, не меняя базовый процесс: описать, проверить, применить, измерить результат и при необходимости вернуть предыдущую версию.

Поделиться:
Сохранить гайд? В закладки браузера