Почему динамический BGP вместо статических маршрутов?
Ручное прописывание статических маршрутов между кластером Kubernetes и корпоративной сетью — это анахронизм, который тормозит развитие и создает операционные риски. Динамический BGP (Border Gateway Protocol) решает эту проблему, автоматизируя обмен маршрутами между сетевым оборудованием и узлами кластера. Вместо того чтобы вручную добавлять каждый новый сетевой префикс подов или сервисов в таблицы маршрутизации, вы настраиваете BGP-сессию один раз, и дальше Calico самостоятельно объявляет все изменения.
Рассмотрим на практике, чем отличается статический подход от динамического:
| Критерий | Статические маршруты | Динамический BGP с Calico |
|---|---|---|
| Масштабирование | При добавлении нового узла или изменении IP-пула необходимо вручную обновлять конфигурацию на всех маршрутизаторах. | Новые узлы и сети подов автоматически объявляются через BGP. Маршрутизатор получает обновления без вмешательства администратора. |
| Отказоустойчивость | При выходе узла из строя его статические маршруты продолжают «висеть» в таблице, что может приводить к blackhole трафика. | BGP-сессия с нерабочим узлом разрывается, и его маршруты автоматически удаляются из таблицы маршрутизации. |
| Риск человеческой ошибки | Высокий. Ошибка в префиксе или next-hop при ручном вводе может заблокировать доступ к целому сегменту сети. | Минимальный. Конфигурация выполняется декларативно через YAML-манифесты в Kubernetes, что снижает вероятность опечаток. |
| Поддержка гибридных сред | Крайне сложна. Интеграция с облачными VPN или несколькими ЦОД требует создания сложных скриптов синхронизации. | BGP является стандартом де-факто для межсетевого взаимодействия. Настройка пиринга с облачными маршрутизаторами (AWS Direct Connect, GCP Cloud Router) происходит по той же схеме. |
Calico, как один из самых популярных CNI (Container Network Interface) для Kubernetes, имеет встроенную поддержку BGP. Каждый узел кластера, на котором работает демон calico-node, выступает в роли BGP-спикера. Это означает, что вам не нужно разворачивать отдельные BGP-демоны (вроде Bird или FRR) — вся необходимая функциональность уже есть «из коробки».
BGP становится не просто удобным, а необходимым решением в сценариях, когда:
- Кластер динамически масштабируется (узлы добавляются и удаляются).
- Используются несколько пулов IP-адресов для подов (например, разделение на frontend и backend сети).
- Требуется бесшовная интеграция Kubernetes-сервисов типа LoadBalancer (например, через MetalLB) в существующую сетевую инфраструктуру.
- Строится гибридная инфраструктура, где часть сервисов работает в Kubernetes, а часть — на физических серверах или в другом кластере.
Подготовка инфраструктуры и проверка совместимости
Перед началом настройки критически важно убедиться в совместимости всех компонентов. Несоответствие версий или неправильно спланированные IP-пулы приведут к тому, что BGP-сессия либо не установится, либо будет работать некорректно.
Требования к версиям:
- Kubernetes: 1.24+. Рекомендуется 1.26+ для полной поддержки последних возможностей Calico.
- Calico: v3.26+. Для данной статьи используется режим BGP Full-Mesh (по умолчанию) или BGP с указанием пиров (Node-specific). Убедитесь, что Calico установлен с включенной опцией BGP. При установке через манифест это обычно параметр
calico_backend: bird. - Сетевое оборудование:
- MikroTik RouterOS: v6.45+ (рекомендуется v7.x).
- Cisco IOS/XE: 16.9+ (для поддержки современных BGP-атрибутов).
- Ubiquiti EdgeRouter: firmware v2.0+.
Планирование IP-адресации:
Конфликт IP-адресов — самая частая причина неработоспособности. Выделите для Calico IPAM пулы, которые не пересекаются с адресным пространством вашей корпоративной сети. Например, если ваша LAN — это 10.0.0.0/16, для подов можно использовать 192.168.0.0/16 или уникальный диапазон из RFC 1918.
Проверьте текущую конфигурацию Calico:
# Проверка узлов и их IP-адресов
calicoctl get nodes -o wide
# Проверка настроенных IP-пулов
calicoctl get ippool -o yaml
Убедитесь, что между узлами Kubernetes и физическим маршрутизатором есть IP-связность. Запустите ping с узла на IP-адрес интерфейса маршрутизатора, который будет использоваться для BGP-пиринга.
Ключевые параметры BGP и их согласование с маршрутизатором
Для успешного установления BGP-сессии параметры на обеих сторонах должны быть согласованы.
- AS Number (Autonomous System Number):
- Для кластера Kubernetes используйте приватный AS номер из диапазона 64512–65534 (стандарт RFC 6996). Например,
64512. - Для физического маршрутизатора используйте его реальный AS номер, если он участвует в глобальной маршрутизации (публичный AS), или также приватный, если это внутренняя сеть.
- Для кластера Kubernetes используйте приватный AS номер из диапазона 64512–65534 (стандарт RFC 6996). Например,
- Таймеры Keepalive и Hold Time:
- Keepalive — интервал отправки keepalive-сообщений для проверки активности пира. Стандартное значение — 30 секунд.
- Hold Time — время, после которого пир считается недоступным, если не получено ни keepalive, ни update-сообщение. Стандартное значение — 90 секунд.
- Важно: Hold Time на обеих сторонах должен быть одинаковым или Hold Time маршрутизатора должен быть больше, чем Hold Time Calico. Рекомендуется оставлять значения по умолчанию (
keepaliveTime: 30s, holdTime: 90sв Calico).
Особенности по вендорам:
- MikroTik RouterOS часто использует упрощенную конфигурацию BGP. Убедитесь, что в настройках пира включена опция
multihop, если узел Kubernetes находится за несколькими прыжками. - Cisco IOS/XE требует точного указания remote-as. Для приватного AS кластера может потребоваться команда
neighbor <IP> local-as <AS> no-prepend replace-as. - Ubiquiti EdgeRouter (на основе Vyatta) имеет синтаксис, близкий к Cisco, но с особенностями в GUI. Для стабильной работы рекомендуется настройка через CLI.
Практическая реализация: настройка BGP-сессий с маршрутизатором
Базовая архитектура: каждый узел Kubernetes с Calico устанавливает отдельную BGP-сессию с физическим маршрутизатором (модель «каждый с каждым»). Это обеспечивает отказоустойчивость — при падении одного узла сессии с остальными остаются активными. Альтернативная модель — использование Route Reflector или выделенного BGP-роутера (например, через MetalLB), но она сложнее в начальной настройке.
Мы настроим пиринг со всеми узлами кластера. Для этого нужно выполнить два ключевых действия: создать конфигурацию BGP в Kubernetes и настроить пира на физическом маршрутизаторе.
Конфигурация Calico: создание BGPConfiguration и BGPPeer
В Calico настройка BGP осуществляется через два основных кастомных ресурса: BGPConfiguration (глобальные параметры) и BGPPeer (определение удаленных пиров).
1. BGPConfiguration — задаем глобальные параметры, такие как AS номер кластера и логгирование.
# bgp-configuration.yaml
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info # Уровень логирования
nodeToNodeMeshEnabled: false # Отключаем full-mesh между узлами, так как будем использовать внешний пиринг
asNumber: 64512 # Приватный AS номер для всего кластера
Примените конфигурацию:
calicoctl apply -f bgp-configuration.yaml
2. BGPPeer — создаем ресурс, который описывает наш физический маршрутизатор как BGP-пира. Предположим, IP-адрес маршрутизатора — 10.0.100.1, а его AS номер — 65001.
# bgp-peer-router.yaml
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: physical-router
spec:
peerIP: 10.0.100.1 # IP-адрес физического маршрутизатора
asNumber: 65001 # AS номер маршрутизатора
nodeSelector: "all()" # Применяем это правило ко всем узлам кластера
calicoctl apply -f bgp-peer-router.yaml
После применения манифестов Calico на каждом узле попытается установить BGP-сессию с указанным IP-адресом. Проверить статус можно командой:
calicoctl node status
Теперь необходимо настроить ответную часть на маршрутизаторе.
Настройка маршрутизатора MikroTik (RouterOS)
Подключаемся к MikroTik через WinBox или SSH и выполняем команды в терминале.
# Включаем BGP и создаем экземпляр
/routing bgp instance
add name=kubernetes as=65001 router-id=10.0.100.1
# Добавляем пира (первый узел Kubernetes с IP 10.0.100.10)
/routing bgp peer
add name=calico-node-1 instance=kubernetes remote-address=10.0.100.10 remote-as=64512 \
ttl=default multihop=yes update-source=10.0.100.1
# Повторяем команду для каждого узла в кластере, меняя remote-address.
# Для автоматизации можно использовать скрипт или список адресов.
Пояснения:
multihop=yes— позволяет устанавливать сессию, даже если узел не находится в непосредственно подключенной сети.update-source— указывает, с какого интерфейса/IP устанавливать соединение.
Проверить состояние сессий:
/routing bgp peer print
Настройка маршрутизатора Cisco (IOS/XE)
Конфигурация выполняется в режиме глобальной конфигурации.
router bgp 65001
bgp router-id 10.0.100.1
bgp log-neighbor-changes
!
! Сосед - первый узел Kubernetes
neighbor 10.0.100.10 remote-as 64512
neighbor 10.0.100.10 description calico-node-1
neighbor 10.0.100.10 ebgp-multihop 255
neighbor 10.0.100.10 update-source Vlan100 ! Или конкретный интерфейс
!
! Аналогично добавляем соседей для остальных узлов.
!
address-family ipv4
neighbor 10.0.100.10 activate
neighbor 10.0.100.10 soft-reconfiguration inbound
neighbor 10.0.100.10 route-map ACCEPT-CALICO in
neighbor 10.0.100.10 route-map SET-LOCAL-PREF out
exit-address-family
!
! Маршрутная карта для базового фильтра (см. раздел безопасности)
ip prefix-list CALICO-POOLS seq 5 permit 192.168.0.0/16 le 24
!
route-map ACCEPT-CALICO permit 10
match ip address prefix-list CALICO-POOLS
Настройка маршрутизатора Ubiquiti (EdgeRouter)
Настройку можно выполнить через веб-интерфейс (Dashboard) или CLI. Через CLI (режим конфигурации):
configure
set protocols bgp 65001 parameters router-id 10.0.100.1
set protocols bgp 65001 neighbor 10.0.100.10 remote-as 64512
set protocols bgp 65001 neighbor 10.0.100.10 description calico-node-1
set protocols bgp 65001 neighbor 10.0.100.10 ebgp-multihop 255
set protocols bgp 65001 neighbor 10.0.100.10 update-source 10.0.100.1
# Повторить для других узлов
commit
save
В веб-интерфейсе настройка находится в разделе Routing > BGP. Нужно создать новый экземпляр BGP и добавить соседей, указав их IP и AS.
Безопасность BGP-пиринга: защита от утечки маршрутов
Открытая BGP-сессия без защиты — это риск. Злоумышленник, получивший доступ к сети, может внедрить ложные маршруты или перехватить трафик. Для защиты используются три основных метода: аутентификация сессии, фильтрация префиксов и ограничение списка пиров.
1. Фильтрация префиксов на маршрутизаторе. Это самый важный шаг. Маршрутизатор должен принимать только те префиксы, которые принадлежат пулам Calico IPAM. Пример для Cisco (продолжение конфигурации выше):
! Создаем prefix-list, разрешающий только наши пулы Calico
ip prefix-list ALLOW-CALICO seq 10 permit 192.168.0.0/16 ge 24 le 28
! Применяем его как inbound фильтр для всех BGP-соседей из Kubernetes
route-map FILTER-CALICO-IN permit 10
match ip address prefix-list ALLOW-CALICO
!
router bgp 65001
address-family ipv4
neighbor 10.0.100.10 route-map FILTER-CALICO-IN in
2. Ограничение списка BGP-пиров. На маршрутизаторе нужно явно указать IP-адреса только тех узлов, которые входят в кластер. Не используйте широковещательные адреса или диапазоны.
3. Ограничение исходящих анонсов с маршрутизатора в кластер. Кластеру Kubernetes обычно не нужно знать маршруты всей корпоративной сети. Настройте outbound-фильтр на маршрутизаторе, чтобы он не отправлял (или отправлял минимально необходимый набор) маршрутов в Calico.
Настройка аутентификации MD5 в Calico и на маршрутизаторах
BGP MD5-аутентификация добавляет криптографическую проверку источника каждого TCP-сегмента в сессии. Пароль должен быть одинаковым на обеих сторонах.
В Calico аутентификация настраивается в ресурсе BGPPeer:
# bgp-peer-router-secure.yaml
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: physical-router-secure
spec:
peerIP: 10.0.100.1
asNumber: 65001
nodeSelector: "all()"
password:
secretKeyRef:
name: bgp-secret # Имя Kubernetes Secret
key: password # Ключ в Secret
Предварительно нужно создать Secret с паролем:
kubectl create secret generic bgp-secret --from-literal=password='YourStrong!BGPp@ssw0rd'
На маршрутизаторе MikroTik:
/routing bgp peer
set [find name="calico-node-1"] password="YourStrong!BGPp@ssw0rd"
На маршрутизаторе Cisco:
router bgp 65001
neighbor 10.0.100.10 password YourStrong!BGPp@ssw0rd
На маршрутизаторе Ubiquiti (CLI):
set protocols bgp 65001 neighbor 10.0.100.10 password YourStrong!BGPp@ssw0rd
После настройки аутентификации сессия BGP не установится, если пароли не совпадают.
Обеспечение отказоустойчивости и балансировки нагрузки
Базовая настройка уже обеспечивает отказоустойчивость на уровне узлов: если один узел падает, его BGP-сессия разрывается, и трафик не направляется на недоступный адрес. Однако для production-сред этого недостаточно.
1. Резервирование BGP-сессий с несколькими маршрутизаторами (Multi-hop). Вы можете настроить пиринг не напрямую с edge-маршрутизатором, а с парой внутренних BGP-роутеров, которые, в свою очередь, анонсируют маршруты дальше. В Calico это делается созданием нескольких ресурсов BGPPeer с разными peerIP. Узлы будут пытаться установить сессии с обоими, обеспечивая резервирование на уровне сетевого пути.
2. Балансировка нагрузки через ECMP (Equal-Cost Multi-Path). Если несколько узлов Kubernetes анонсируют один и тот же префикс (например, IP-адрес сервиса типа LoadBalancer), и эти маршруты имеют одинаковую метрику (вес), маршрутизатор будет распределять входящий трафик между всеми этими узлами. Это встроенная функция BGP.
В Calico ECMP включается в глобальной конфигурации:
# bgp-configuration-ecmp.yaml
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
asNumber: 64512
serviceClusterIPs:
- cidr: 10.96.0.0/12 # Укажите ваш CIDR сервисов Kubernetes
serviceExternalIPs:
- cidr: 192.168.100.0/24 # Укажите пул для ExternalIP/LoadBalancer
nodeToNodeMeshEnabled: false
listenPort: 179
logSeverityScreen: Info
ecmpEnabled: true # Включаем ECMP
3. Graceful Restart. Эта функция позволяет BGP-пиру (маршрутизатору) временно сохранять маршруты, полученные от узла, пока тот перезапускается (например, при обновлении calico-node). Это предотвращает кратковременные потери трафика. Поддержка Graceful Restart зависит от версии Calico и маршрутизатора. В Calico v3.26+ она включается автоматически при поддержке со стороны пира.
4. Распределение IP-пулов между узлами. Не назначайте весь большой IP-пул одному узлу. Используйте аннотации или политики Calico IPAM, чтобы распределять блоки адресов. Это предотвратит ситуацию, когда падение одного узла делает недоступными все поды с его IP.
Мониторинг и диагностика работоспособности BGP-сессий
После настройки необходимо убедиться, что сессии установлены и маршруты передаются корректно.
1. Проверка со стороны Calico:
# Статус BGP на конкретном узле
calicoctl node status --node=<node-name>
# Список всех BGP-пиров
calicoctl get bgppeers
# Детальная информация о пире
calicoctl get bgppeer physical-router -o yaml
2. Проверка со стороны маршрутизатора:
- MikroTik:
/routing bgp peer print detail. Обращайте внимание на статусestablished. - Cisco:
show bgp ipv4 unicast summaryиshow bgp ipv4 unicast neighbors <IP> advertised-routes. - Ubiquiti:
show ip bgp summary(в режиме оператора).
3. Проверка таблицы маршрутизации: На маршрутизаторе убедитесь, что префиксы из кластера появились в таблице маршрутизации. Например, на Cisco: show ip route bgp.
Типовые проблемы и решения:
- Сессия в состоянии
Active/Connect, но неEstablished.- Причина: Несовпадение AS номеров, блокировка TCP-порта 179 межсетевым экраном, отсутствие IP-связности.
- Решение: Проверьте конфигурацию AS, откройте порт 179 в обе стороны, проверьте
ping.
- Сессия установлена, но маршруты не видны.
- Причина: Неправильные фильтры на маршрутизаторе, отсутствие активных сетей для анонса на узлах Calico (нет подов).
- Решение: Проверьте
calicoctl get ippool -o wide, убедитесь, что пулы имеют флагdisabled: false. Проверьте логи Calico на узле:journalctl -u calico-node.
Интеграция с Prometheus/Grafana: Calico экспортирует метрики BGP, включая состояние сессий и количество полученных/переданных префиксов. Для сбора этих метрик настройте ServiceMonitor или прямой scrape эндпоинта :9091/metrics на каждом calico-node. В Grafana можно создать дашборд для визуализации состояния всех BGP-сессий в кластере.
Для глубокой диагностики сложных проблем с кастомными ресурсами в Kubernetes, включая анализ их состояния и логики контроллеров, обратитесь к нашему полному руководству: Полная диагностика Custom Resources в Kubernetes: от простых ошибок до глубокой отладки.
Оптимизация: управление предпочтением маршрутов с BGP-атрибутами
Когда инфраструктура растет и появляется несколько путей до одного и того же сервиса, возникает необходимость управлять выбором маршрута. BGP предоставляет для этого мощные атрибуты.
- Local Preference (LOCAL_PREF): Атрибут, влияющий на исходящую маршрутизацию в пределах вашего AS. Более высокое значение LOCAL_PREF означает более предпочтительный маршрут. Вы можете настроить на маршрутизаторе, чтобы маршруты от определенных узлов Kubernetes (например, расположенных в основном ЦОД) имели больший LOCAL_PREF, чем маршруты от узлов в резервном ЦОД.
- AS Path Prepending: Искусственное увеличение длины AS_PATH для того, чтобы сделать маршрут менее предпочтительным. Например, если вы хотите, чтобы трафик к сервису в основном шел через ЦОД A, а через ЦОД B только для резерва, вы можете настроить Calico на узлах в ЦОД B добавлять ваш AS номер несколько раз в анонсируемый маршрут.
- BGP Communities: Это метки, которые можно прикреплять к маршрутам. Они не влияют на выбор пути напрямую, но позволяют маршрутизаторам фильтровать или модифицировать маршруты на основе этих меток. Например, вы можете пометить все маршруты из Kubernetes определенным community (
64512:100), а затем на корпоративных маршрутизаторах настроить политику, которая на основе этой метки задает определенный LOCAL_PREF или фильтрует маршруты при передаче внешним провайдерам.
Пример настройки Community в Calico: Атрибуты можно задать для IP-пула через аннотации.
# ippool-with-community.yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: external-pool
annotations:
projectcalico.org/BGPCommunity: "64512:100" # Указываем community
spec:
cidr: 192.168.100.0/24
blockSize: 26
nodeSelector: "all()"
vxlanMode: Never
ipipMode: Never
natOutgoing: true
На стороне маршрутизатора (пример для Cisco) нужно настроить route-map, которая будет «читать» это community и применять нужные действия:
route-map SET-PREF-FROM-COMMUNITY permit 10
match community KUBE-COMMUNITY
set local-preference 200
!
ip community-list standard KUBE-COMMUNITY permit 64512:100
Правильное использование атрибутов BGP позволяет построить интеллектуальную, саморегулирующуюся сетевую инфраструктуру, где трафик автоматически направляется по оптимальным путям с учетом бизнес-логики.
Для принятия обоснованных решений о том, как хранить подобные расширенные конфигурации в кластере — в виде гибких ConfigMap или строго типизированных Custom Resource Definitions (CRD) — рекомендуем ознакомиться с нашим подробным сравнением: CRD vs ConfigMap: практическое руководство по выбору инструмента для конфигурации в Kubernetes.