Floxy

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

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

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

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

Правила

Каждое правило задает от какого экспортера каким коллекторам пересылать пакеты. Экспортеры и коллекторы задаются как адреса и порты. Структуру правил описывает сообщение ProxyRules в gRPC API. Пример правил в формате protobuf text:

# Пакеты от 192.0.2.1:1000 будут пересылаться 192.0.2.11:1001 и [2001:db8::12]:1002.
rules: {
    exporter: {endpoint: {host: "192.0.2.1" port: 1000}}
    outputs: {
        collectors: {endpoint: {host: "192.0.2.11"   port: 1001}}
    }
    outputs: {
        collectors: {endpoint: {host: "2001:db8::12" port: 1002}}
    }
}
# Пакеты с любого другого порта 192.0.2.1 будут пересылаться на 192.0.2.21:2001.
rules: {
    exporter: {endpoint: {host: "192.0.2.1"}}
    outputs: {
        collectors: {endpoint: {host: "192.0.2.21" port: 2001}}
    }
}
# Пакеты от [2001:db8::3]:3000 будут пересылаться [2001:db8::31]:3001,
# а также на [2001:db8::32] и тот порт, на который пришел пакет.
rules: {
    exporter: {endpoint: {host: "2001:db8::3" port: 3000}}
    outputs: {
        collectors: {endpoint: {host: "2001:db8::31" port: 3001}}
    }
    outputs: {
        collectors: {endpoint: {host: "2001:db8::32"}}
    }
}
# Пакеты от 192.0.2.4:4000 будут пересылаться:
# - на 192.0.2.41:4001 и 192.0.2.42:4002 с равномерной балансировкой между ними;
# - на 192.0.2.43:4003 все без исключения.
rules: {
    exporter: {endpoint: {host: "192.0.2.4" port: 4000}}
    outputs: {
        collectors: {endpoint: {host: "192.0.2.41" port: 4001}}
        collectors: {endpoint: {host: "192.0.2.42" port: 4002}}
    }
    outputs: {
        collectors: {endpoint: {host: "192.0.2.43" port: 4003}}
    }
}
# Пакеты, не соответствующие ни одному правилу,
# будут пересылаться на 192.0.2.51:5001 (IPv4) и [2001:db8::52]:5002 (IPv4 и IPv6),
# равномерно распределяясь между ними,
# а также на 192.0.2.53 (IPv4) с сохранением порта, на который пришел пакет.
default_outputs: {
    collectors: {endpoint: {host: "192.0.2.51"   port: 5001}}
    collectors: {endpoint: {host: "2001:db8::52" port: 5002}}
}
default_outputs: {
    collectors: {endpoint: {host: "192.0.2.53"}}
}

Порядок правил (rules), выходов (outputs, default_outputs) и коллекторов (collectors) не имеет значения. Правила, где указан порт экспортера, имеют приоритет над правилами, где порт экспортера не указан.

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

Системные настройки

Системные настройки задаются через переменные окружения сервиса 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_THREAD_COUNT: количество потоков, пересылающих трафик. По умолчанию выбирается как число ядер, доступных сервису collector. Может регулироваться параметром cpuset этого сервиса.

Управление правилами (gRPC API)

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

Для каждой версии Collector vXX.YY.Z публикуется образ docker.mitigator.ru/collector/grpcurl:vXX.YY.Z с утилитой grpcurl и файлами *.proto, описывающими API указанной версии. Ниже приведены примеры её использования. Запрос и ответ могут задаваться и выводиться в формате JSON с ключом -format json или в формате protobuf text с ключом -format text. Полную справку можно получить, запустив контейнер с ключом -help.

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

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

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

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

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

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

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

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

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

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

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

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

Если правила записаны в floxy-rules.txtpb, как в примере выше, то следующая команда заменяет текущие правила на правила из файла:

BACKEND_ID=$(docker-compose ps -q backend 2>/dev/null) && \
VERSION=$(grep '^VERSION=' .env | cut -d '=' -f 2) && \
docker run --rm --network=container:${BACKEND_ID} -i docker.mitigator.ru/collector/grpcurl:${VERSION} -proto settings.proto -format text -d "$(sed -s 's/#.*//' floxy-rules.txtpb)" :8853 collector.proto.Settings/ReplaceProxyRules

В случае успеха команда ничего не печатает.

Запрос статистики

Следующая команда запрашивает статистику:

BACKEND_ID=$(docker-compose ps -q backend 2>/dev/null) && \
VERSION=$(grep '^VERSION=' .env | cut -d '=' -f 2) && \
docker run --rm --network=container:${BACKEND_ID} docker.mitigator.ru/collector/grpcurl:${VERSION} -proto settings.proto -format text :8853 collector.proto.Settings/GetProxyStats

В случае успеха вывод может быть таким (на примере тех же правил):

rules: {
    exporter: {
        endpoint: {host: "127.0.0.1" port: 2345}
        input: {packets: 1 bytes: 160}
    }
    outputs: {
        collectors: {
            endpoint: {host: "192.0.2.11" port: 1001}
            output: {packets: 1 bytes: 160}
        }
    }
    outputs: {
        collectors: {
            endpoint: {host: "2001:db8::12" port: 1002}
            output: {packets: 0 bytes: 0}
        }
    }
}
rules: {
    exporter: {
        endpoint: {host: "192.0.0.1"}
        input: {packets: 1 bytes: 160}
    }
    outputs: {
        collectors: {
            endpoint: {host: "192.0.2.21" port: 2001}
            output: {packets: 1 bytes: 160}
        }
    }
}
rules: {
    exporter: {
        endpoint: {host: "2001:db8::3" port: 3000}
        input: {packets: 0 bytes: 0}
    }
    outputs: {
        collectors: {
            endpoint: {host: "2001:db8::31" port: 3001}
            output: {packets: 0 bytes: 0}
        }
    }
    outputs: {
        collectors: {
            endpoint: {host: "2001:db8::32"}
            output: {packets: 0 bytes: 0}
        }
    }
}
rules: {
    exporter: {
        endpoint: {host: "192.0.2.4" port: 4000}
        input: {packets: 2 bytes: 320}
    }
    outputs: {
        collectors: {
            endpoint: {host: "192.0.2.41" port: 4001}
            output: {packets: 1 bytes: 160}
        }
        collectors: {
            endpoint: {host: "192.0.2.42" port: 4002}
            output: {packets: 1 bytes: 160}
        }
    }
    outputs: {
        collectors: {
            endpoint: {host: "192.0.2.43" port: 4003}
            output: {packets: 2 bytes: 320}
        }
    }
}
default_outputs: {
    collectors: {
        endpoint: {host: "192.0.2.51" port: 5001}
        output: {packets: 3 bytes: 480}
    }
    collectors: {
        endpoint: {host: "2001:db8::52" port: 5002}
        output: {packets: 5 bytes: 800}
    }
}
default_outputs: {
    collectors: {
        endpoint: {host: "192.0.2.53"}
        output: {packets: 3 bytes: 480}
    }
}
mismatched: {packets: 5 bytes: 800}

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

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

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

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

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

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

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

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

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

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

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

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

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

Настройка BGP выполняется по инструкции.