Автоматизация профилей маршрутизации строится вокруг единого описания сетевого состояния: маршруты, шлюзы, интерфейсы, метрики, таблицы и правила хранятся в 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.
| Параметр | Пример | Что проверять |
|---|---|---|
| destination | 10.20.0.0/16 | Корректный CIDR и отсутствие нежелательного пересечения |
| gateway | 192.0.2.1 | Доступность через выбранный интерфейс |
| interface | ens18 | Наличие интерфейса на конкретном типе ОС или VM |
| metric | 100 | Приоритет среди маршрутов с одинаковым префиксом |
| table | 100 | Связь с правилами policy-based routing |
| priority | 100 | Порядок обработки правил 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_netDocker создаст 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 может выполнить такие шаги:
- Проверить YAML, HCL и шаблоны.
- Проверить схему профиля, CIDR, уникальность priority и отсутствие пересечений.
- Сформировать Terraform plan или Ansible diff.
- Применить изменение в staging.
- Проверить доступность целевых подсетей.
- Запустить canary на одном или двух узлах.
- Раскатить изменение на остальные узлы пакетами, например по 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.
- Выделите статические маршруты, шлюзы, метрики, таблицы и правила policy-based routing.
- Разделите настройки общего профиля, среды и конкретного хоста.
- Выберите владельца каждого слоя: systemd-networkd, NetworkManager, Ansible, Terraform или CNI.
- Проверьте профиль в VM, staging или отдельном сетевом namespace.
- Примените его к одному узлу, проверьте маршруты и обратную связность.
- Расширьте запуск на группу, сохраняя журнал и предыдущую версию для отката.
Такой порядок сокращает ручные операции и сохраняет контроль над сетевой конфигурацией. После статических маршрутов можно добавить policy-based routing, облачные таблицы, BGP или Kubernetes-политики, не меняя базовый процесс: описать, проверить, применить, измерить результат и при необходимости вернуть предыдущую версию.