Floxy

Floxy позволяет распределять трафик от экспортера flow по нескольким коллекторам, указывая правила пересылки для каждого экспортера отдельно.

Это позволяет решать задачи:

  • обхода ограничения количества получателей flow на экспортере;
  • распределения на коллекторы от разных вендоров;
  • распределения нагрузки по нескольким коллекторам одного вендора;
  • единой настройки получателей на экспортерах.

Floxy принимает пакеты UDP и пересылает их на коллекторы по правилам, сохраняя у пакета адрес и порт отправителя.

Правила

Каждое правило задает от какого экспортера каким коллекторам пересылать пакеты. Экспортеры и коллекторы задаются как адреса и порты.

Правила могут быть заданы через API или файл конфигурации.

Структура файла конфигурации такая же, как у сообщения ProxyRules в GRPC API.

Формат файла — protobuf text. Пример:

# Пакеты от 127.0.0.1:2345 будут пересылаться 127.0.0.1:1234 и [::1]:3456.
rules: {
    exporter: {endpoint: {host: "127.0.0.1" port: 2345}}
    collectors: {endpoint: {host: "127.0.0.1" port: 1234}}
    collectors: {endpoint: {host: "::1"       port: 3456}}
}
# Пакеты с любого другого порта 127.0.0.1 будут пересылаться на 127.0.0.1:4567.
rules: {
    exporter: {endpoint: {host: "127.0.0.1"}}
    collectors: {endpoint: {host: "127.0.0.1" port: 4567}}
}
# Пакеты от [::1]:5678 будут пересылаться [::1]:6789,
# а также на [::2] и тот порт, на который пришел пакет.
rules: {
    exporter: {endpoint: {host: "::1" port: 5678}}
    collectors: {endpoint: {host: "::1" port: 6789}}
    collectors: {endpoint: {host: "::2"}}
}
# Пакеты, не соответствующие ни одному правилу,
# будут пересылаться на 127.0.0.1:7890 (IPv4) и [::1]:8901 (IPv4 и IPv6).
default_collectors: {endpoint: {host: "127.0.0.1" port: 7890}}
default_collectors: {endpoint: {host: "::1"       port: 8901}}

Порядок правил и коллекторов по умолчанию не имеет значения. Правила, где указан порт экспортера, имеют приоритет над правилами, где порт экспортера не указан. Порядок коллекторов в правиле не имеет значения.

Пересылка IPv6-пакетов IPv4-коллектору не поддерживается, потому что при этом невозможно сохранить адрес отправителя у пакета.

Настройка правил локально

При запуске Floxy читает начальный набор правил из файла, указанного в переменной среды COLLECTOR_FLOXY_RULES_PATH сервиса collector. Формат файла — protobuf text. Это позволяет избежать промежутка времени, когда пересылка уже запущена, а правила еще не заданы через API.

По сигналу SIGUSR1 текущие правила заменяются на правила из того же файла.

docker-compose kill -s USR1 collector

По сигналу SIGUSR2 текущие правила записываются в тот же файл.

docker-compose kill -s USR2 collector

Это позволяет динамически менять конфигурацию без API.

Настройки работы

Настройки задаются через переменные окружения сервиса collector. Чтобы их изменение вступило в силу, нужно перезапустить коллектор.

Функциональность Floxy доступна, если задана переменная среды COLLECTOR_FLOXY_ADDRESS (в логах контейнера collector будут сообщения, что она запущена).

  • COLLECTOR_FLOXY_ADDRESS (по умолчанию не задано, формат host:port): адрес и порт, на которые принимается трафик для пересылки. При указании адреса IPv6 также работает и пересылка трафика IPv4.

  • COLLECTOR_FLOXY_PACKET_BUFFER_SIZE (от 1496 до 65535, по умолчанию 1496): максимальный размер данных в пакете (UDP payload). Должен быть увеличен, если используются Ethernet jumbo frames или большие фрагментированные IP-пакеты. Если придут данные большего размера, Floxy обрежет их и перешлет обрезанными.

  • COLLECTOR_FLOXY_RULES_PATH (по умолчанию не задано): путь внутри контейнера сollector к файлу для загрузки начальных правил и сохранения правил по сигналу.

  • COLLECTOR_FLOXY_THREAD_COUNT: количество потоков, пересылающих трафик. По умолчанию выбирается как число ядер, доступных сервису collector. Может регулироваться параметром cpuset этого сервиса.

GRPC API

API работает на том же адресе и порту, что и API коллектора (по умолчанию 8853, регулируется COLLECTOR_BACKEND_METRICS_PORT в .env).

Точное описание находится в floxy.proto.

Все вызовы, изменяющие правила, сохраняют их во внутренней базе данных. При перезапуске Collector восстанавливаются последние настройки, заданные через API. Эти настройки заменят загруженные из файла, если он был.

  • Settings.ListProxyRules: возвращает конфигурацию всех правил.

  • Settings.ReplaceProxyRules: принимает новую конфигурацию правил и заменяет ею текущую.

  • Settings.UpdateProxyRules: принимает конфигурацию правил и добавляет к текущей. Если уже было правило с тем же экспортером, у него заменяется список коллекторов на список из нового правила.

  • Settings.DeleteProxyRules: удаляет правила с указанными экспортерами.

  • Metrics.GetProxyStats: возвращает статистику либо по правилам для указанных экспортеров, либо по всем правилам, если указан пустой список.

  • Settings.GetBuildInfo: возвращает информацию о сборке системы.

  • Settings.GetSystemStatus: возвращает состояние системы, в частности, подсистемы Floxy (proxy).

    Значения состояний (state):

    • OK: подсистема работает и готова к использованию.
    • Configuring: подсистема временно не работает, так как находится в процессе настройки.
    • NotConfigured: подсистема работает, но не удалось восстановить сохраненные настройки. Описание ошибки в error, для её устранения нужно изменить настройки.
    • Offline: подсистема недоступна, решение требует действий на сервере.

Пример статистики (сообщение ProxyStats в API):

rules: {
    exporter: {
        endpoint: {host: "127.0.0.1" port: 2345}
        input: {packets: 1 bytes: 160}
    }
    collectors: {
        collectors: {
            endpoint: {host: "127.0.0.1" port: 1234}
            output: {packets: 1 bytes: 160}
        }
        collectors: {
            endpoint: {host: "::1" port: 3456}
            output: {packets: 0 bytes: 0}
        }
    }
}
rules: {
    exporter: {
        endpoint: {host: "127.0.0.1"}
        input: {packets: 1 bytes: 160}
    }
    collectors: {
        endpoint: {host: "127.0.0.1" port: 4567}
        output: {packets: 1 bytes: 160}
    }
}
rules: {
    exporter: {
        endpoint: {host: "::1" port: 5678}
        input: {packets: 0 bytes: 0}
    }
    collectors: {
        endpoint: {host: "::1" port: 6789}
        output: {packets: 0 bytes: 0}
    }
    collectors: {
        endpoint: {host: "::2"}
        output: {packets: 0 bytes: 0}
    }
}
default_collectors: {
    endpoint: {host: "127.0.0.1" port: 7890}
    output: {packets: 3 bytes: 480}
}
default_collectors: {
    endpoint: {host: "::1" port: 8901}
    output: {packets: 5 bytes: 800}
}
mismatched: {packets: 5 bytes: 800}

Все счетчики накопительные. Байты (bytes) считаются по UDP payload.

  • rules.exporter.input: принятые пакеты от экспортера. Счетчик растет в том числе тогда, когда не задано коллекторов.

  • rules.exporter.collectors.output: пакеты, которые пересланы от экспортера соответствующему коллектору.

    • Если пакет невозможно было отправить, например, не нашлось подходящего интерфейса по правилам маршрутизации, пакет не учитывается в этом счетчике.
    • Если отправляемый пакет сброшен ядром ОС из-за перегрузки, он все равно учитывается в этом счетчике.
    • Если коллектор был добавлен не при создании, а при обновлении правила, счетчик будет меньше rules.exporter.input.
  • default_collectors.output: пакеты, отправленные каждому из коллекторов по умолчанию.

    • Включаются в выдачу при запросе статистики для всех правил.
    • IPv4-коллекторам не пересылается трафик IPv6, их счетчики могут быть меньше.
    • Если одни коллекторы по умолчанию добавлены позже других, их счетчики могут быть меньше.
  • mismatched: пакеты, которые не подходили под запрошенные правила.

    • Если статистика запрошена для всех правил, это пакеты, не попавшие ни под одно правило.
    • Если статистика запрошена для части правил, это пакеты, не попавшие ни под одно правило + пакеты, попавшие под правила, для которых статистика не запрошена.

При обновлении правил сохраняется статистика экспортеров и коллекторов, которые есть и в старой, и в новой версии правил.

Во всех запросах можно указать GRPC-заголовок collector-address-format=binary, чтобы в ответе у Endpoint заполнялось поле octets (бинарное представление адреса), а не host (текстовое представление адреса, по умолчанию или ...=text). В теле запроса и в файлах настроек можно использовать любое из этих полей.

Отказоустойчивость

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

Для этого на loopback-интерфейсах обоих Floxy задается одинаковый IP-адрес — IPfloxy. С обоих серверов, на которых работают Floxy, устанавливаются BGP-сессии с вышестоящим оборудованием, и в анонсе сообщается, что IPfloxy доступен через их nexthop. На всех источниках настраивается отправка flow на IPfloxy.

В этом случае сетевое оборудование будет самостоятельно выполнять балансировку трафика между двумя устройствами.

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

Установка и настройка gobgp

Если требуется анонсирование префиксов по BGP, то возможно использование gobgp из нашего docker-реестра. Для запуска:

  1. Скачайте docker-compose.gobgp.yml в /srv/collector.

    cd /srv/collector
    wget https://docs.mitigator.ru/collector/v24.07/dist/docker-compose.gobgp.yml
  2. Отредактируйте COMPOSE_FILE в .env:

    COMPOSE_FILE=docker-compose.yml:docker-compose.vpn.yml:docker-compose.gobgp.yml
  3. Добавьте в .env переменную MITIGATOR_VERSION=v23.08.0. Здесь v23.08.0 — версия MITIGATOR.

  4. Создайте файл конфигурации gobgpd.yml.

  5. Задайте настройки в gobgpd.yml согласно документации.

    Пример:

    global:
        config:
            as: 64512
            router-id: 192.168.255.1
    neighbors:
        - config:
            neighbor-address: 10.0.255.1
            peer-as: 65001
        - config:
            neighbor-address: 10.0.255.2
            peer-as: 65002
  6. Запустите gobgp.

    docker-compose up -d
  7. Дальнейшая настройка и управление gobgp согласно документации.

  8. Для применения изменений в gobgpd.yml выполните команду:

    docker-compose kill -s HUP gobgp