Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ body:
attributes:
label: Версии
description: Panel, Node Agent, HAProxy и ОС ноды.
placeholder: "Panel 2.0.2, Agent 2.0.2, HAProxy 3.4, Ubuntu 24.04"
placeholder: "Panel 2.0.0, Agent 2.0.0, HAProxy 3.4, Ubuntu 24.04"
validations:
required: true
- type: textarea
Expand Down
11 changes: 1 addition & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
# Changelog

## 2.0.2 — Подсказки к весу и стоимости

- В таблице «Вес и стоимость отдельных IP» у DNS-пула появились подсказки к «Вес» и «Стоимость» и строка с формулой и примером под текущий алгоритм (для «Меньше соединений»: доля IP = вес ÷ стоимость).

## 2.0.1 — Толерантность на одном DNS-пуле

- Исправлено: маршрут с одним сервером-доменом в режиме DNS-пула терял «Толерантность» и алгоритм «Меньше соединений» при сохранении — панель сворачивала его в старый формат одиночного маршрута, где эти настройки не хранятся. Теперь такой маршрут остаётся пулом серверов, и толерантность сохраняется и применяется агентом. Маршруты без толерантности и с закреплением по хешу IP рендерятся как раньше, байт в байт.
- Агент для этого не меняется; номер 2.0.1 у Panel и Node Agent общий.

## 2.0.0 — Готовые образы и расширенная балансировка

Panel и Node Agent — 2.0.0, HAProxy renderer v21. Первый стабильный релиз после 1.0.8; в него вошли все изменения предварительных сборок 1.1.x. Заметки к релизу с инструкцией по обновлению: [docs/releases/2.0.0.md](docs/releases/2.0.0.md).
Expand All @@ -28,7 +19,7 @@ Panel и Node Agent — 2.0.0, HAProxy renderer v21. Первый стабиль
- **Домены в «Доверенных адресах» PROXY protocol.** `accept_proxy_from` принимает, кроме IP и подсетей, домены (до 32 на маршрут): домен означает все его A/AAAA-адреса (DNS-пул). Для порта с доменами рендерер добавляет `acl nf_pp_trusted src -f /etc/haproxy/nodeflow/pp-trusted-<frontend>.acl` и `expect-proxy … if { src <статические> } || nf_pp_trusted` с аннотацией `# nf-pp-trusted`; порты без доменов рендерятся байт-в-байт как раньше (версия рендерера не меняется). Node Agent **1.1.3** резолвит домены перед каждой проверкой/перезагрузкой HAProxy и затем каждые 30 с; при изменении набора атомарно переписывает файл и подменяет ACL через runtime API (`prepare/add/commit acl`) без reload; без изменений — ни одной команды в сокет; при сбое DNS остаётся последний известный набор. Панель требует Agent ≥ 1.1.3: `422 pp_trusted_domains_requires_agent_1_1_3` при сохранении и публикации. В редакторе подсказка «IP, подсети или домены…», предпросмотр совпадает с рендерером.
- **Splice-буферы 1 МиБ, когда ядро позволяет.** Node Agent **1.1.2** при старте и в каждом heartbeat поднимает `fs.pipe-max-size` до 1048576 (никогда не понижает) и ставит `fs.pipe-user-pages-soft = 0`: пишет прямо в `/proc/sys/fs/*` (без `sysctl`), сохраняет `/etc/sysctl.d/90-nodeflow-pipes.conf`; `NODE_AGENT_TUNE_SYSCTL=off` — только отчёт. Heartbeat сообщает `metrics.kernel_pipes {pipe_max_size, pipe_user_pages_soft, tuned, managed}`. systemd-юнит агента открывает на запись только эти два файла `/proc/sys` и `/etc/sysctl.d` (`ProtectKernelTunables` остаётся); самообновление юнит не меняет, поэтому на нодах, установленных 1.0.x, нужен однократный drop-in `20-kernel-pipes.conf` (см. заметки к релизу). Панель рендерит `tune.pipesize 1048576` для ноды, где `tuned=true`, `pipe_max_size ≥ 1048576` и `pipe_user_pages_soft = 0`, иначе прежние 262144.
- **«Авто» размер stick-table от RAM ноды — изменение поведения.** `sticky_table_entries=''` для `sticky_mode=source_table` больше не означает фиксированные 100k: размер = clamp(5 % RAM / 228 Б / N, 100k, 10m), округлённый вниз до k, где N — число включённых «Авто»-таблиц на ноде; RAM из последнего heartbeat (`memory_total_bytes`), округлённый вниз до 256 МиБ, чтобы колебания не публиковали ревизии; RAM неизвестна — 1m. Память занимается только по мере прихода клиентов. Явные размеры не меняются. `GET` маршрута/списка отдаёт read-only `sticky_table_entries_effective` (например `919k`); редактор показывает «Авто: ~N клиентов (5% RAM ноды), ≈X МБ при полной таблице», превью совпадает с рендером.
- **«Меньше соединений»: стоимость и толерантность.** Для `balance_algorithm=leastconn` действуют `servers[].cost` и `ip_weights[].cost` (0,01..100): соединение с сервером стоимости *c* считается за *c*, панель рендерит статический `weight` = base/cost × K (без Agent; без стоимости конфиг байт-в-байт прежний). Новое поле `balance_tolerance` (алиас `leastping_tolerance`, та же колонка, без миграции): серверы, чья нагрузка (соединения × стоимость / вес) не больше минимума на столько процентов, считаются равными и делят новых клиентов по весу; при толерантности > 0 Node Agent 1.1.1 каждые 5 с читает `scur` и выставляет runtime-веса (гистерезис ×1,5, только изменённые веса). Требует Agent ≥ 1.1.1 (`422 leastconn_tolerance_requires_agent_1_1_1`). В редакторе «Стоимость» теперь видна и для «Меньше соединений», в блоке «Распределение клиентов» — «Толерантность, %».
- **«Меньше соединений»: вес и толерантность.** Для `balance_algorithm=leastconn` новые клиенты делятся пропорционально весу сервера и отдельного IP. В редакторе у этого алгоритма только «Вес»: стоимость там была бы просто обратным весом, поэтому колонки «Стоимость» нет, а сохранённые ранее `cost` при открытии маршрута переводятся в веса с теми же пропорциями. API по-прежнему принимает `servers[].cost` и `ip_weights[].cost` для `leastconn` (доля = вес ÷ стоимость, панель рендерит статический `weight` = base/cost × K; без стоимости конфиг байт-в-байт прежний). Новое поле `balance_tolerance` (алиас `leastping_tolerance`, та же колонка, без миграции): серверы, чья нагрузка (соединения / вес) не больше минимума на столько процентов, считаются равными и делят новых клиентов по весу; при толерантности > 0 Node Agent каждые 5 с читает `scur` и выставляет runtime-веса (гистерезис ×1,5, только изменённые веса). Требует Agent ≥ 1.1.1 (`422 leastconn_tolerance_requires_agent_1_1_1`). Маршрут из одного домена в режиме DNS-пула сохраняет толерантность и алгоритм (остаётся пулом серверов, а не сворачивается в одиночный маршрут). Подсказки к «Вес» и «Стоимость» в таблицах серверов и отдельных IP.

### Из предварительных сборок 1.1.x

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ NodeFlow — панель управления парком HAProxy-нод дл

- **SNI-маршрутизация и фолбэк.** Общие listener'ы на порт, несколько SNI на маршрут, «Фолбэк» для всего, что не совпало; IP-, доменные и Unix-socket backend'ы.
- **Несколько серверов и DNS-пулы.** До 16 серверов на маршрут в режимах «Пул» и «Основной + резервные»; домен как DNS-пул (все A/AAAA-адреса, с исключением недоступных), отдельные веса для IP пула.
- **Балансировка.** `roundrobin`, `static-rr`, `random`, `leastconn` и `leastping` («Меньше задержка»). Для `leastconn`/`leastping` — стоимость сервера и толерантность: близкие по нагрузке или задержке серверы делят клиентов по весу, веса на лету выставляет Agent через runtime API, без reload.
- **Балансировка.** `roundrobin`, `static-rr`, `random`, `leastconn` и `leastping` («Меньше задержка»). Вес сервера и отдельного IP DNS-пула, для `leastping` — ещё стоимость (множитель задержки); толерантность: близкие по нагрузке или задержке серверы делят клиентов по весу, веса на лету выставляет Agent через runtime API, без reload.
- **Закрепление клиента.** Хеш IP (consistent или map-based, группировка IPv6 по префиксу) или таблица с TTL, переживающая reload; размер «Авто» подбирается от RAM ноды.
- **PROXY protocol.** Приём от доверенных IP, подсетей и доменов (Agent резолвит их и обновляет ACL без reload), вариант «от всех»; health-check с PROXY-заголовком.
- **Ограничение скорости.** Лимиты upload/download на IP клиента — фильтрами HAProxy или в ядре через nftables (`shaper_mode=kernel`), без потери splice.
Expand Down Expand Up @@ -58,7 +58,7 @@ curl -fsSL https://raw.githubusercontent.com/NodeFlow-dev/nodeflow/main/install.
2. предложит режим доступа: Caddy cookie-gate (ссылка активации ставит защищённую cookie) или без него — токен администратора Panel нужен в любом случае;
3. установит Docker и **Caddy** — Caddy сам получит сертификат Let's Encrypt и будет проксировать HTTPS на Panel, которая слушает только `127.0.0.1:8080`;
4. скачает install kit последнего релиза, проверит его по SHA-256, который GitHub публикует для каждого asset релиза, возьмёт из него `compose.release.yaml`, сгенерирует `.env`, CA, сертификат mTLS и ключ подписи обновлений в `/opt/nodeflow`;
5. выполнит `docker compose pull && docker compose up -d` с образом `ghcr.io/nodeflow-dev/nodeflow-panel:2.0.2` — на сервере ничего не собирается, миграции БД применяет сам образ;
5. выполнит `docker compose pull && docker compose up -d` с образом `ghcr.io/nodeflow-dev/nodeflow-panel:2.0.0` — на сервере ничего не собирается, миграции БД применяет сам образ;
6. опубликует подписанные релизы Node Agent (amd64 и arm64) и сохранит реквизиты входа в `~/nodeflow-credentials.txt` (права `0600`).

Файрвол установщик не меняет. Для автоматизации без вопросов передайте переменные `NODEFLOW_DOMAIN`, `NODEFLOW_AUTH_MODE=cookie|none` и при необходимости `NODEFLOW_VERSION=2.0.0` (по умолчанию — последний релиз):
Expand Down Expand Up @@ -90,7 +90,7 @@ sudo NODE_AGENT_TOKEN=<токен> bash install-node.sh
Команды выполняются от root (`sudo -i`): каталог `/opt/nodeflow` закрыт для остальных пользователей.

```bash
v=2.0.2
v=2.0.0
kit=NodeFlow-Panel-$v-Agent-$v-install-kit
curl -fsSLO "https://github.com/NodeFlow-dev/nodeflow/releases/download/v$v/$kit.tar.gz"
# сверьте с digest asset'а на странице релиза или в API:
Expand Down Expand Up @@ -119,7 +119,7 @@ curl -fsSL https://raw.githubusercontent.com/NodeFlow-dev/nodeflow/main/install.

Найдя `/opt/nodeflow/.env`, он работает как апгрейдер: делает `pg_dump` и архив конфигурации в `/var/backups/nodeflow/`, сохраняет `.env`, `tls/`, `pki/` и Caddy-сниппет `/etc/caddy/conf.d/nodeflow-panel.caddy`, переводит установку со сборки из исходников на образ ghcr.io, запускает миграции и проверяет, что Panel отвечает версией 2.0.0. При ошибке возвращаются прежние `compose.yaml` и `.env`; дамп БД остаётся (миграции автоматически не откатываются).

Затем в **Настройки → Node Agent** обновите ноды до 2.0.2 — updater заменит Agent атомарно и откатит его при неудачном запуске. Самообновление не меняет systemd-юнит, поэтому на нодах, установленных версиями 1.0.x, один раз добавьте права на настройку pipe-буферов ядра (без этого splice остаётся на 256 КиБ) — или переустановите Agent из меню ноды:
Затем в **Настройки → Node Agent** обновите ноды до 2.0.0 — updater заменит Agent атомарно и откатит его при неудачном запуске. Самообновление не меняет systemd-юнит, поэтому на нодах, установленных версиями 1.0.x, один раз добавьте права на настройку pipe-буферов ядра (без этого splice остаётся на 256 КиБ) — или переустановите Agent из меню ноды:

```bash
sudo install -d /etc/systemd/system/nodeflow-node-agent.service.d
Expand Down
2 changes: 1 addition & 1 deletion cmd/node-agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/nodeflow/nodeflow/internal/agent"
)

var version = "2.0.2"
var version = "2.0.0"

func main() {
showVersion := flag.Bool("version", false, "print Node Agent version and exit")
Expand Down
2 changes: 1 addition & 1 deletion cmd/panel-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

// panelVersion is the published Panel release version. Release builds may
// replace it with -ldflags "-X main.panelVersion=...".
var panelVersion = "2.0.2"
var panelVersion = "2.0.0"

func main() {
if len(os.Args) > 1 {
Expand Down
4 changes: 2 additions & 2 deletions compose.release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ services:
<<: *hardening

migrate:
image: ghcr.io/nodeflow-dev/nodeflow-panel:${NODEFLOW_VERSION:-2.0.2}
image: ghcr.io/nodeflow-dev/nodeflow-panel:${NODEFLOW_VERSION:-2.0.0}
restart: "no"
command: ["migrate"]
depends_on:
Expand Down Expand Up @@ -79,7 +79,7 @@ services:
<<: *hardening

panel-api:
image: ghcr.io/nodeflow-dev/nodeflow-panel:${NODEFLOW_VERSION:-2.0.2}
image: ghcr.io/nodeflow-dev/nodeflow-panel:${NODEFLOW_VERSION:-2.0.0}
restart: unless-stopped
depends_on:
migrate:
Expand Down
8 changes: 4 additions & 4 deletions docs/install/README-NODE-AGENT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ NODEFLOW NODE AGENT — SIGNED RELEASE UPLOAD
===========================================

Бинарники Agent — отдельные assets GitHub Release:
nodeflow-node-agent-2.0.2-linux-amd64
nodeflow-node-agent-2.0.2-linux-arm64
nodeflow-node-agent-2.0.0-linux-amd64
nodeflow-node-agent-2.0.0-linux-arm64

install.sh публикует их в Panel сам. Для ручной загрузки скачайте файл и
сверьте SHA-256 с digest, который GitHub показывает для asset'а:

v=2.0.2 f=nodeflow-node-agent-2.0.2-linux-amd64
v=2.0.0 f=nodeflow-node-agent-2.0.0-linux-amd64
curl -fsSLO https://github.com/NodeFlow-dev/nodeflow/releases/download/v$v/$f
curl -fsSL https://api.github.com/repos/NodeFlow-dev/nodeflow/releases/tags/v$v \
| jq -r --arg n "$f" '.assets[] | select(.name == $n) | .digest'
Expand All @@ -17,7 +17,7 @@ install.sh публикует их в Panel сам. Для ручной загр
В Panel откройте:
Настройки → Node Agent (подписанные релизы)

Версия 2.0.2, ОС linux, архитектура amd64 или arm64 — по файлу. Выберите
Версия 2.0.0, ОС linux, архитектура amd64 или arm64 — по файлу. Выберите
бинарник и нажмите «Загрузить и подписать». Затем назначьте релиз на
странице нужной ноды.

Expand Down
Loading
Loading