Route Health Injection

Как автоматически снимать BGP-анонс VIP-адреса с Application Delivery Controller, когда связанные с ним upstream недоступны.

В статье описан сценарий с BGP, но этот подход может использоваться и с другими протоколами динамической маршрутизации.

Что это

RHI (Route Health Injection) — механизм, который управляет анонсом маршрутов на основе состояния upstream в Application Delivery Controller.

Он нужен, чтобы наша система переставала получать трафик для VIP, если за ней нет доступных бэкендов. Когда upstream становятся недоступны, RHI удаляет VIP-адрес с интерфейса, за которым следит динамический маршрутизатор. После этого маршрут перестаёт анонсироваться. Когда upstream восстанавливаются, RHI возвращает VIP на интерфейс, и анонс снова появляется.

Когда пригодится

Предположим, ваш сервис обслуживают несколько дата-центров (ДЦ) в разных городах. В каждом стоит Application Delivery Controller, а запросы пользователей попадают в ближайший ДЦ через Anycast и BGP-анонсы одного и того же VIP-адреса.

Если в каком-то ДЦ все ваши бэкенды стали недоступны, RHI снимает анонс VIP с находящегося там Application Delivery Controller. Маршрутизаторы перенаправляют трафик в другие ДЦ, где сервис доступен. В результате пользователи не попадают на недоступный бэкенд и не получают связанные с этим ошибки.

Когда бэкенды восстановятся, RHI вернёт VIP в анонс из этого ДЦ.

Через что реализовано

RHI реализован через отдельный сервис RHI Service.

RHI Service работает как демон под управлением systemd и использует конфигурационный файл /etc/rhi/rhi.yaml. Основные компоненты:

Компонент За что отвечает

RHI Service

Опрос состояния upstream, принятие решения об анонсе или отзыве VIP, добавление и удаление адресов на интерфейсе

Application Delivery Controller

Предоставление данных о состоянии всех upstream на основе health check

rhi0

Интерфейс, с которого RHI удаляет/добавляет обратно VIP-адреса в зависимости от состояния upstream

BIRD

Динамический маршрутизатор, который анонсирует адреса с rhi0 через BGP

rhi0 — пример имени интерфейса. Фактическое имя задаётся в конфигурации параметром interface.

Как работает

Application Delivery Controller постоянно выполняет health check всех upstream. RHI Service использует эти данные:

  1. RHI Service с заданным интервалом обращается к API ADC (к эндпоинтам вида /v1/healthcheck/upstreams/<имя>) и узнаёт результаты health check.

  2. В результатах health check RHI Service видит, в каких upstream есть хотя бы одна нода в состоянии healthy.

  3. RHI Service смотрит конфигурацию vips и определяет, какие upstream связаны с каждым VIP.

  4. Для каждого VIP RHI Service определяет, можно считать его доступным или нет. Для этого применяет условие, заданное в condition. Есть два варианта:

    • all — VIP считается доступным, если в каждом связанном upstream есть хотя бы одна healthy -нода.

    • any — VIP считается доступным, если хотя бы в одном связанном upstream есть хотя бы одна healthy -нода.

  5. Если все VIP доступны, RHI Service ничего не делает. Если какой-то VIP недоступен, RHI Service удаляет его с интерфейса rhi0.

  6. BIRD отслеживает адреса на rhi0. Увидев, что VIP исчез с интерфейса, BIRD перестаёт анонсировать этот маршрут.

  7. RHI Service продолжает опрашивать API Application Delivery Controller. Если состояние upstream меняется, RHI снова пересчитывает доступность VIP. Когда VIP снова станет доступен, RHI Service добавит его на rhi0, а BIRD подхватит анонс.

rhi0 — пример имени интерфейса. Фактическое имя задаётся в конфигурации параметром interface.

Как настроить

Настройки RHI задаются в файле /etc/rhi/rhi.yaml. Их можно разделить на четыре типа:

  • глобальные настройки,

  • политика недоступности API Application Delivery Controller,

  • VIP и привязка к upstream,

  • условия анонса VIP.

Глобальные настройки

apisix_poll_interval: 3s
apisix_control_url: http://127.0.0.1:9090
apisix_timeout: 5s
interface: rhi0
main_log: /var/log/rhi/main.log
error_log: /var/log/rhi/error.log
Параметр Что задаёт

apisix_poll_interval

Временной интервал в секундах — как часто RHI будет опрашивать API ADC

apisix_control_url

Адрес API ADC, из которого RHI получает состояние health checks

apisix_timeout

Сколько времени RHI ждёт ответ от API ADC, прежде чем считать запрос неуспешным

interface

Интерфейс, с которого RHI удаляет и на который добавляет VIP-адреса

main_log

Файл основного журнала RHI

error_log

Файл журнала ошибок RHI

Политика при недоступности API ADC

failure_policy:
  control_api_unreachable: withdraw
  max_failed_polls: 3

Если API ADC не отвечает, RHI считает неуспешные опросы. После max_failed_polls подряд неудачных опросов применяется действие из control_api_unreachable:

Значение Что произойдёт

withdraw

RHI удалит с интерфейса все VIP-адреса, указанные в его конфигурации. BIRD прекратит их анонсировать.

announce

RHI не будет удалять VIP-адреса с интерфейса. Анонсирование продолжится, даже если API ADC недоступен.

VIP и привязка к upstream

vips:
  - address: 10.0.0.100
    description: "Production API"
    upstreams:
      - "/apisix/upstreams/api"

  - address: 10.0.0.101
    description: "Admin portal"
    upstreams:
      - "/apisix/upstreams/auth"
      - "/apisix/upstreams/admin"
    condition: all

  - address: 10.0.0.102
    description: "Legacy app"
    upstreams:
      - "/apisix/upstreams/legacy"
Параметр Что задаёт

address

VIP-адрес, которым RHI управляет на интерфейсе: добавляет его при доступности связанных upstream и удаляет при недоступности.

description

Описание VIP для администратора.

upstreams

Список upstream, связанных с этим VIP. По их состоянию RHI будет делать вывод о доступности/недоступности VIP.

condition

Правило, по которому RHI оценивает доступность VIP (возможные значения описаны в разделе Условия анонса VIP).

Один VIP может зависеть как от одного, так и от нескольких upstream сразу.

Условия анонса VIP

Параметр condition задаёт, как RHI оценивает доступность нескольких upstream.

Значение Что означает

all

VIP должен остаться в анонсе, если у каждого указанного upstream есть хотя бы одна нода в состоянии healthy. Используется по умолчанию.

any

VIP должен остаться в анонсе, если хотя бы у одного указанного upstream есть хотя бы одна нода в состоянии healthy.

Если condition не задан, используется all.

Что учесть перед настройкой

rhi0 в примерах — условное имя интерфейса. В рабочей конфигурации используйте имя интерфейса, на который должен смотреть BIRD.

BIRD должен быть настроен так, чтобы анонсировать адреса, добавленные на интерфейс rhi0.

Пример настройки

В этом примере RHI опрашивает API ADC каждые 3 секунды, управляет VIP-адресами на интерфейсе rhi0 и снимает анонсы, если API ADC остаётся недоступным после трёх попыток.

apisix_poll_interval: 3s
apisix_control_url: http://127.0.0.1:9090
apisix_timeout: 5s
interface: rhi0
main_log: /var/log/rhi/main.log
error_log: /var/log/rhi/error.log

failure_policy:
  control_api_unreachable: withdraw
  max_failed_polls: 3

vips:
  - address: 10.0.0.100
    description: "Production API"
    upstreams:
      - "/apisix/upstreams/api"

  - address: 10.0.0.101
    description: "Admin portal"
    upstreams:
      - "/apisix/upstreams/auth"
      - "/apisix/upstreams/admin"
    condition: all

  - address: 10.0.0.102
    description: "Public app"
    upstreams:
      - "/apisix/upstreams/app-primary"
      - "/apisix/upstreams/app-reserve"
    condition: any

Как будет работать эта конфигурация:

  • 10.0.0.100 — анонсируется, если у upstream /apisix/upstreams/api есть хотя бы одна healthy -нода;

  • 10.0.0.101 — анонсируется, если у /apisix/upstreams/auth и /apisix/upstreams/admin есть хотя бы по одной healthy -ноде;

  • 10.0.0.102 — анонсируется, если хотя бы один из upstream /apisix/upstreams/app-primary или /apisix/upstreams/app-reserve имеет healthy -ноду.