Skip to content

Перенос стека с Traffic Fly ​

Пошагово: как перенести compose-стек с одного хоста на другой так, чтобы пользователи продолжали заходить по тому же адресу, — на примере Forgejo (git-сервер с PostgreSQL), веб и git по SSH которого идут через Traffic Fly.

Почему через Traffic Fly: A-запись git.example.com указывает не на хост, а на VPS-шлюз. При переносе хаб просто переключает цель маршрута на новый хост — DNS, сертификаты и настройки клиентов не меняются.

Простой есть

Стек на старом хосте останавливается на время копирования данных — пока они едут, сервис недоступен. Traffic Fly не убирает этот простой, а избавляет от смены DNS и сертификатов после. Переносите в тихое время; сколько данных поедет, окно плана покажет заранее.

0. Что нужно заранее ​

  • Хаб с «Картой хостов». Карта — экспериментальная функция: «О системе» → «Экспериментальные функции» → «Изменить» → «Карта хостов».

  • Два хоста в хабе, оба на связи, nkt на обоих — 1.13.62 или новее (на Ubuntu 26.04 старее — туннель Traffic Fly не поднимется, см. nkt-edge). На новом хосте установлен Docker. Отдельно настраивать туннель на новом хосте не нужно — хаб поднимет его сам, когда добавит туда цель маршрута.

  • Шлюз Traffic Fly — VPS с nkt-edge в роли fly, «Шлюзы» на странице Traffic Fly.

  • Forgejo, выложенный через Traffic Fly. Если Forgejo ещё нет — «Выкладки» → «Новый конвейер» → текст examples/forgejo/pipeline.fly.yaml: вместо прокси на хосте в нём два маршрута:

    yaml
    fly:
      - route: forgejo-web        # веб: https://git.example.com
        kind: https
        names: [git.example.com]
        tls: gateway              # сертификат выпускает и продлевает шлюз
        service: forgejo
        target_port: 3000
        check: http
        check_path: /api/healthz
      - route: forgejo-ssh        # git по SSH: ssh://git@git.example.com:2222/…
        kind: tcp
        port: 2222
        service: forgejo
        target_port: 2222

    A-запись git.example.com — на адрес шлюза. Поправьте имя, хост (hosts: [web1]) и почту администратора, «Сохранить» → «Выложить». Forgejo уже выложен по обычному примеру (site: и SSH на 2222 у хоста)? — замените в его описании site: и строку ports: блоком fly: выше, выложите и перенесите A-запись на шлюз.

  • Хост в конвейере — по имени (hosts: [web1]), не группой: иначе перенос не сможет переключить конвейер, и следующая выкладка подняла бы стек на старом хосте снова.

Проверьте до переноса: https://git.example.com открывается, в Traffic Fly у обоих маршрутов цель на старом хосте — рабочая и живая.

1. Начать перенос ​

  1. «Хосты» → переключатель «Карта» справа.
  2. Кнопка «Перенос» над картой — режим перетаскивания плиток.
  3. Перетащите плитку forgejo-forgejo-1 на блок нового хоста. Весь стек (forgejo и db) обведён общей рамкой и переносится целиком.

Переключатель «Применять сразу» рядом с «Перенос»: выключен — перенос сначала копится планом и запускается кнопкой «Применить переносы (N)»; включён — запускается прямо из окна плана (а если препятствий и предупреждений нет — даже без окна).

2. Окно плана ​

Окно плана переноса Forgejo

Что проверить:

  • Стек целиком — оба контейнера.
  • Данные — тома forgejo-data (репозитории, вложения, ключ SSH-сервера) и db-data (база) с размерами: столько поедет, столько будет простой.
  • Образы — «уже есть» у тех, что на новом хосте уже скачаны; остальные поедут вместе с данными.
  • Препятствия (красным) — места не хватает, порт занят, нет внешней сети; пока они есть, перенести нельзя.
  • Цель маршрутов Traffic Fly — оба маршрута, рабочая. Галочка «Переключить маршруты на новый хост» — включена: рабочая цель станет рабочей на новом хосте.
  • Стек выложен конвейером forgejo — галочка «Переключить конвейер на новый хост» включена: хост в описании конвейера и учёт выкладки переедут вместе со стеком.

«Добавить в план» → «Применить переносы (1)» (или «Перенести» при «Применять сразу»). Откроется журнал задания.

3. Перенос ​

Задание идёт шагами, карта показывает их вживую:

  1. План — ещё раз проверка обоих хостов.

  2. Упаковка — стек на старом хосте останавливается (с этого момента сервис недоступен), тома и образы упаковываются.

  3. Передача — данные идут через хаб на новый хост. На карте — призрак плитки на новом хосте и бегущие к нему точки с процентом.

    Перенос: копирование данных

  4. Распаковка — тома и образы на новом хосте, стек запускается.

  5. Traffic Fly — в оба маршрута добавляется цель на новом хосте резервом; хаб ждёт до 90 секунд, пока шлюз увидит её живой, затем обмен: новая — рабочая, старая — резерв. На карте к новой плитке прорисовывается линия маршрута, пока шлюз проверяет — бегущий пунктир, потом точки трафика переходят на новую линию.

    Перенос: переключение маршрутов

  6. Конвейер — хост в описании (новой версией с примечанием «перенос стека») и учёт выкладки — на новый хост.

  7. Готово — запись переноса: старый стек остался остановленным на старом хосте для отката.

Ошибка на любом шаге после остановки — задание откатывается само: на новом хосте распакованное убирается, на старом стек запускается снова.

4. Проверить ​

Карта после переноса

  • Карта: Forgejo работает на новом хосте («← с web-1»), на старом — серые плитки «→ web-2 · остановлен»; у маршрутов на старой плитке — пустые кружки (резерв).
  • Traffic Fly: у forgejo-web и forgejo-ssh рабочая цель — на новом хосте и живая, старая — резерв.
  • Сам Forgejo: откройте https://git.example.com, войдите, откройте репозиторий и задачи — данные на месте.
  • git: git clone https://git.example.com/<владелец>/<репо>.git и git clone ssh://git@git.example.com:2222/<владелец>/<репо>.git. Ключ SSH-сервера лежит в томе Forgejo и переехал вместе с ним — клиенты не увидят предупреждения о смене ключа.
  • Конвейер forgejo в «Выкладках»: в описании — новый хост.

5. Если что-то не так ​

  • «Откатить» — щелчок по серой плитке на старом хосте: стек на новом хосте останавливается, на старом запускается, маршруты (рабочая — снова старая) и конвейер возвращаются. Данные — те, что были на старом хосте на момент переноса: изменения, сделанные после переноса на новом, при откате не переезжают обратно.
  • Новый хост не отвечает (выключен, сеть) — в том же меню «Откатить без нового хоста»: стек снова работает на старом, маршруты и конвейер возвращены. На новом хосте может остаться работающая вторая копия — когда хост вернётся, карта пометит её «вторая копия», щелчок — «Остановить вторую копию».
  • «Не ожила за 90 с» в журнале — шлюз не увидел новую цель живой, но обмен всё равно сделан (старая уже остановлена). Причины — в Traffic Fly под шлюзом и у маршрута: туннель нового хоста не поднялся (журнал «Применить»), Forgejo ещё стартует (проверка оживёт сама), неверный порт.
  • Следующая выкладка конвейера сверяет цели маршрутов с хостом из описания и убирает старую резервную цель — после неё откат маршрутов уже не вернёт. Откатывайте до следующей выкладки.

6. Убрать старую копию ​

Когда всё проверено (день-два работы на новом хосте) — щелчок по серой плитке → «Убрать старый»: остановленные контейнеры уходят со старого хоста, старая цель — из маршрутов. Галочка «и данные» удаляет и тома на старом хосте; без неё они остаются — перенести стек обратно туда можно будет только с уборкой этих остатков (окно переноса предложит). Через неделю после переноса хаб напомнит о неубранной копии в «Оповещениях».

То же сценарием ​

Всё от выкладки до проверки после переноса — одним сценарием хаба «Forgejo за Traffic Fly: выкладка и перенос» (он же — examples/scripts/forgejo-fly.nkt, нужен хаб 1.13.67+).

Как запустить: «Профили» → вкладка «Сценарии» → «Новый сценарий», в окне редактора — «Готовые сценарии ▾» → «Forgejo за Traffic Fly: выкладка и перенос»; впишите имя → «Сохранить» → «Проверить» → «Сухой прогон» → «Выполнить» (параметры спросит при запуске, ход — в журнале задания). Готовые сценарии есть и на вкладке «Справка» страницы сценариев (кнопка «В редактор»).

При запуске спрашивает хост, где выложить, хост, куда перенести, и имя; «Сухой прогон» покажет сухой прогон конвейера, а план переноса — при запуске (до выкладки стека на хосте ещё нет).

# Forgejo за Traffic Fly: выкладка и перенос на другой хост
param FROM "хост, где Forgejo будет выложен сначала"
param TO "хост, куда его перенести"
param DOMAIN "имя Forgejo — A-запись на адрес шлюза Traffic Fly"

# Веб и git по SSH — через шлюз; сертификат выпускает шлюз
pipeline forgejo
repo: https://github.com/piqab/nkt.git
ref: main
action: compose
compose:
  file: examples/forgejo/deploy/docker-compose.yml
  project: forgejo
  hosts: [${FROM}]
  wait_timeout: 5m
  env_keys:
    forgejo-admin: [FORGEJO_ADMIN_USER, FORGEJO_ADMIN_PASSWORD, FORGEJO_ADMIN_EMAIL]
  env:
    POSTGRES_PASSWORD: generate:password
    FORGEJO_DOMAIN: ${DOMAIN}
    FORGEJO_ROOT_URL: https://${DOMAIN}/
    FORGEJO_ADMIN_USER: gitadmin
    FORGEJO_ADMIN_PASSWORD: generate:password
    FORGEJO_ADMIN_EMAIL: admin@example.com
  fly:
    - route: forgejo-web
      kind: https
      names: [${DOMAIN}]
      tls: gateway
      service: forgejo
      target_port: 3000
      check: http
      check_path: /api/healthz
    - route: forgejo-ssh
      kind: tcp
      port: 2222
      service: forgejo
      target_port: 2222
end
deploy forgejo 20m

# Проверка снаружи — через DNS и шлюз, как зайдёт пользователь
wait url https://${DOMAIN}/api/healthz 200 10m

# Перенос: маршруты Traffic Fly и конвейер переключаются на новый хост
migrate ${FROM} forgejo-forgejo-1 to ${TO} switch-fly switch-pipeline
wait url https://${DOMAIN}/api/healthz 200 5m
  • pipeline forgejo … end — конвейер, как «Сохранить» в окне: пароли создаст хаб, значения уйдут в «Секреты».
  • deploy forgejo 20m — выкладка с ожиданием; маршруты forgejo-web и forgejo-ssh создаёт сам конвейер (блок fly:).
  • wait url … — проверка снаружи, с хаба по настоящему имени: DNS, шлюз и сертификат — как у пользователя.
  • migrate … switch-fly switch-pipeline — перенос, как с карты: при препятствиях сценарий остановится до остановки стека, упавший перенос откатится сам.

Сценарий — разовый: повторный запуск снова сохранит конвейер с хостом FROM и следующая выкладка вернула бы стек туда. Откат и уборку старой копии делайте с карты (шаги 5 и 6).

По API и из n8n ​

Перенос запускается и без карты: API-токеном администратора — план POST /api/hub/migrate/preview, перенос POST /api/hub/migrate (switch_fly, switch_pipeline), откат и уборка — POST /api/hub/migrations/{id}/rollback|remove; в n8n — Migration → Preview / Move Stack. Подробно — API хаба.

См. также ​