Migration: update steps
This commit is contained in:
+50
-29
@@ -284,28 +284,33 @@ sudo /usr/local/sbin/backup-all.py 2>&1 | tee /tmp/final-backup.log
|
|||||||
|
|
||||||
### Шаг 2. Остановить все приложения на источнике
|
### Шаг 2. Остановить все приложения на источнике
|
||||||
|
|
||||||
Аккуратно остановить контейнеры каждого приложения (через
|
Останавливаем docker-демон целиком — это атомарно гасит все
|
||||||
`docker compose down` от соответствующего пользователя или одним
|
контейнеры за один вызов, не зависит от текущего списка приложений
|
||||||
проходом):
|
и шлёт корректный SIGTERM (с грейс-периодом ~15 сек) каждому, что
|
||||||
|
функционально эквивалентно `docker compose down` по всем стекам.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
inv ssh
|
inv ssh
|
||||||
for user in caddyproxy authelia netdata miniflux rssbridge wakapi \
|
sudo systemctl stop docker.service docker.socket
|
||||||
dozzle transcriber wanderer memos gitea outline homepage gramps \
|
sudo systemctl disable docker.service docker.socket # страховка от автостарта при ребуте
|
||||||
calibre remembos apprise tuwunel goaccess; do
|
sudo systemctl stop cron # чтобы ночной backup-cron не побежал
|
||||||
sudo -iu "$user" bash -c "cd /mnt/applications/$user && docker compose down"
|
|
||||||
done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
(Можно завести вспомогательный плейбук `playbook-shutdown-all.yml`,
|
Финальный бэкап (шаг 1) **обязательно** должен пройти до этого
|
||||||
если такое будет часто.)
|
момента — `backup-all.py` запускает скрипты приложений, которые
|
||||||
|
делают `docker compose exec ... pg_dump ...`; без работающего
|
||||||
|
daemon это сломается.
|
||||||
|
|
||||||
Проверить `docker ps`, что пусто. Снять флаги cron на бэкап (чтобы
|
`disable` — страховка: если по какой-то причине старая машина
|
||||||
финальный backup не побежал во время миграции):
|
перезагрузится во время rsync (или мы вернёмся на источник для
|
||||||
|
проверки/отката), docker не поднимется автоматически и сервисы
|
||||||
|
не начнут писать в данные, которые мы уже считаем «фиксированной
|
||||||
|
копией». В случае отката — `enable` + `start` обратно.
|
||||||
|
|
||||||
```bash
|
Проверить, что `docker ps` сейчас отвечает «daemon not running»
|
||||||
sudo systemctl stop cron
|
(или вернёт пустой список — зависит от того, как `inv ssh` пройдёт
|
||||||
```
|
до/после стопа). Если нужно убедиться, что контейнеры реально
|
||||||
|
ушли — `ps auxf | grep -E "containerd|docker" | grep -v grep`.
|
||||||
|
|
||||||
### Шаг 3. Раскатать инфраструктуру на target БЕЗ запуска приложений
|
### Шаг 3. Раскатать инфраструктуру на target БЕЗ запуска приложений
|
||||||
|
|
||||||
@@ -323,7 +328,9 @@ uv run ansible-playbook -i timeweb.yml --diff \
|
|||||||
Цель — после этого на target есть:
|
Цель — после этого на target есть:
|
||||||
|
|
||||||
- Корректные uid/gid для всех приложений.
|
- Корректные uid/gid для всех приложений.
|
||||||
- Каталоги `/mnt/applications/<app>/{data,config,backups}`.
|
- Каталоги `/srv/applications/<app>/{data,config,backups}` (на
|
||||||
|
Timeweb дефолт изменён с `/mnt/applications`; см.
|
||||||
|
[журнал шаг 5](timeweb-migration-log.md)).
|
||||||
- Шаблоны `docker-compose.yml` и application-конфиги — отрендерены
|
- Шаблоны `docker-compose.yml` и application-конфиги — отрендерены
|
||||||
и лежат на месте.
|
и лежат на месте.
|
||||||
- Docker и сети созданы.
|
- Docker и сети созданы.
|
||||||
@@ -331,34 +338,48 @@ uv run ansible-playbook -i timeweb.yml --diff \
|
|||||||
|
|
||||||
### Шаг 4. Перенос данных
|
### Шаг 4. Перенос данных
|
||||||
|
|
||||||
Два варианта.
|
Пути меняются: на YC данные лежат в `/mnt/applications/<app>`, на
|
||||||
|
Timeweb — в `/srv/applications/<app>`. Rsync делает remap сам
|
||||||
|
(потому что мы указываем источник и приёмник явно). Для трёх
|
||||||
|
приложений без backup-механизма (`caddyproxy`, `remembos`,
|
||||||
|
`transcriber`) rsync — **единственный** канал переноса, restic
|
||||||
|
для них не альтернатива.
|
||||||
|
|
||||||
**Вариант A — rsync напрямую (быстрее).** С target-машины тянем
|
**Вариант A — rsync напрямую (основной путь).** С target-машины
|
||||||
данные со старой:
|
тянем данные со старой:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo rsync -aAX --info=progress2 --delete \
|
sudo rsync -aAX --info=progress2 --delete \
|
||||||
--exclude='lost+found' \
|
--exclude='lost+found' \
|
||||||
major@158.160.46.255:/mnt/applications/ \
|
major@158.160.46.255:/mnt/applications/ \
|
||||||
/mnt/applications/
|
/srv/applications/
|
||||||
```
|
```
|
||||||
|
|
||||||
`-aAX` сохраняет ACL/xattrs и uid/gid (численные значения).
|
`-aAX` сохраняет ACL/xattrs и uid/gid (численные значения).
|
||||||
|
Численные uid/gid на target совпадают с источником, потому что
|
||||||
|
плейбуки на обеих машинах создают пользователей с одинаковыми
|
||||||
|
явно заданными `app_owner_uid`/`gid`.
|
||||||
|
|
||||||
Каждое приложение можно тянуть отдельно — удобнее наблюдать
|
Каждое приложение можно тянуть отдельно — удобнее наблюдать
|
||||||
прогресс и можно частично пересинхронизировать в случае ошибок.
|
прогресс и можно частично пересинхронизировать в случае ошибок:
|
||||||
|
|
||||||
**Вариант B — restore из restic.** Если по сети источник недоступен
|
|
||||||
(например, IP уже закрыли) или хочется проверить, что бэкапы вообще
|
|
||||||
рабочие — восстанавливаемся из YC S3:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo /usr/local/sbin/restic-shell.sh
|
sudo rsync -aAX --info=progress2 --delete \
|
||||||
restic restore latest --target /mnt/applications --path /mnt/applications
|
major@158.160.46.255:/mnt/applications/gitea/ \
|
||||||
|
/srv/applications/gitea/
|
||||||
```
|
```
|
||||||
|
|
||||||
Рекомендую **A с фолбэком на B**: rsync быстрее и точнее (с
|
**Вариант B — restore из restic (страховка).** Если по сети
|
||||||
точностью до секунды), restic держим как страховку.
|
источник недоступен или хочется проверить, что бэкапы вообще
|
||||||
|
рабочие. Подробный пример (с учётом смены `/mnt` → `/srv`) — в
|
||||||
|
[журнале миграции, шаг 5](timeweb-migration-log.md).
|
||||||
|
|
||||||
|
Для `caddyproxy`, `remembos`, `transcriber` использовать B
|
||||||
|
**нельзя** — у них нет архивации, в restic-снапшоте данных просто
|
||||||
|
нет. Только A.
|
||||||
|
|
||||||
|
Рекомендую **A как основной метод**, B держим как страховку
|
||||||
|
для приложений, у которых есть восстановимый снапшот.
|
||||||
|
|
||||||
### Шаг 5. Запуск приложений на target
|
### Шаг 5. Запуск приложений на target
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user