Руководство — дальше: nginx, Docker, Kubernetes, кластер PostgreSQL

Продолжение Большого руководства. Здесь — то, что нужно, когда базовый сервер и первый проект уже работают: тонкая настройка nginx, Docker, Kubernetes и отказоустойчивый кластер PostgreSQL.

← Назад: Начало · Дальше: Эксплуатация


5. Свой nginx-конфиг

Стандартный шаблон подходит большинству проектов (reverse proxy + websocket). Если нужен особый конфиг (свои location, кэширование, лимиты), есть два пути:

Путь 1 — конфиг в репозитории (рекомендуется). Положите файл в проект по одному из путей: .mitdev/nginx.conf, deploy/nginx.conf или nginx.conf в корне. mitdev app найдёт его сам и спросит, использовать ли.

Путь 2 — путь на сервере. На вопрос «Свой nginx-конфиг» укажите путь, например /home/deploy/configs/myapp.conf.

В своём конфиге можно (не обязательно) использовать плейсхолдеры — mitdev подставит значения из ответов: __APP_NAME__, __DOMAIN__, __PORT__:

server {
    listen 80;
    server_name __DOMAIN__;
    client_max_body_size 100m;

    location / {
        proxy_pass http://127.0.0.1:__PORT__;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Безопасность: перед включением mitdev прогоняет nginx -t; если ваш конфиг с ошибкой — сайт не включается, прежнее состояние восстанавливается, nginx не ломается. SSL выпускается так же автоматически (certbot сам дописывает секцию 443 в ваш конфиг).

6. Проект в Docker

Ничего особенного делать не нужно: если в корне репозитория есть docker-compose.yml (или compose.yml), mitdev app выполнит docker compose up -d, а mitdev deployup -d --build + очистку старых образов. Nginx проксирует домен на порт, который вы указали — он должен совпадать с портом, опубликованным в compose (ports: "3000:3000").

Полезное: mitdev docker ps, mitdev docker logs <контейнер>, mitdev docker prune.

7. Kubernetes

Если слова «под» и «кластер» пугают: под (pod) — это ваш контейнер, запущенный в Kubernetes; deployment — правило «держи N копий пода живыми, обновляй без простоя». mitdev использует k3s — лёгкий полноценный Kubernetes для одного сервера.

Установка: при install.sh отметьте «Kubernetes (k3s + kubectl + helm)». Если на сервере есть nginx — mitdev сам разрулит конфликт портов.

Деплой приложения из готового Docker-образа — одна команда:

sudo mitdev k8s deploy myapp ghcr.io/you/myapp:latest 3000 myapp.example.com
#                       имя   образ                  порт домен

mitdev создаст deployment (2 копии пода, обновление без простоя, проверки живости), сервис и опубликует домен (через traefik или nginx — сам решит), предложит SSL. Дальше:

mitdev k8s status          # обзор кластера и ваших приложений
mitdev k8s pods            # список подов
mitdev k8s logs myapp      # логи приложения (живой поток)
sudo mitdev k8s deploy …   # повторный запуск = обновление без простоя
sudo mitdev k8s delete myapp

Обновление на новую версию образа: соберите и запушьте образ с тем же тегом и повторите k8s deploy (или используйте новый тег — честнее).

Отказоустойчивый кластер из трёх серверов — чтобы падение любого сервера не прерывало сервис: на первом сервере при установке выберите режим init, получите токен (sudo mitdev k8s token), на двух других — режим join (URL + токен). Реплики подов сами разносятся по серверам; домен направьте на все три IP. Серверов должно быть нечётное число (3 или 5).

8. Кластер PostgreSQL

Задача: база переживает смерть целого дата-центра, проект использует одну строку подключения, которая никогда не меняется. Нужно три сервера Ubuntu 24.04 (можно самых маленьких, 1–2 ГБ, но выделенных только под базу) и один сервер приложений. Обозначим IP: A (главный), B, C (реплики).

Как это работает, в двух словах: primary принимает записи и шлёт журнал изменений (WAL) репликам — у них всегда точная копия. Если primary умер, watchdog сам повышает основную реплику за ~30 секунд, вторая реплика сама перецепляется на новую главную, а ожившый старый primary сам возвращается в кластер репликой. Прокси на сервере приложений сам находит, кто сейчас primary. Ни одного ручного действия при аварии.

# ── Сервер A ─────────────────────────────────────────────
curl -fsSL https://mitdev.top/get | sudo bash
#   компоненты: + PostgreSQL, + PostgreSQL-кластер («Виртуальный IP» НЕ нужен)
#   база данных: имя/пользователь/пароль вашего проекта
#   роль: primary; IP реплик: B C
sudo cat /root/.mitdev-credentials        # запишите replication_password

# залейте бекап вашей базы (реплики получат его сами!):
sudo mitdev pg import /path/backup.dump mydb

# ── Серверы B и C ────────────────────────────────────────
curl -fsSL https://mitdev.top/get | sudo bash
#   роль: replica; primary: <A>; пароль репликации — из credentials на A
#   авто-failover: «Да»;  приоритет: B → «1 — основная», C → «2 — резервная»

# ── На каждом из A, B, C: доступ серверу приложений ──────
sudo mitdev pg allow <IP-приложения> mydb <пользователь-БД>

# ── На сервере приложений ────────────────────────────────
sudo mitdev pg proxy <A> <B> <C>

В .env проекта — та самая одна строка навсегда:

DATABASE_URL=postgresql://пользователь:пароль@127.0.0.1:5432/mydb?sslmode=require

Проверка: mitdev pg replication на A (две реплики streaming), mitdev pg watchdog status на B и C, mitdev doctor везде.

Учебная тревога (обязательно, до продакшена): на A выполните sudo systemctl stop postgresql. Через ~30 секунд B станет primary — проект продолжит работать. Через минуту-две C сама перецепится на B. Запустите A обратно (sudo systemctl start postgresql) — он сам поймёт, что его сместили, и вернётся репликой B. Наблюдать за автоматикой: journalctl -t mitdev-pg-watchdog -f на любом узле. Руками не делаете ничего — только смотрите.

Все узлы в одной приватной сети? Тогда добавьте модуль «Виртуальный IP» — строка будет …@<VIP>:5432/…, а прокси не нужен. Ещё проще — приватная сеть mitdev: см. Рецепты. Подробности и тонкая настройка — COMMANDS.md.


← Назад: Начало · Дальше: Эксплуатация: бекапы, уход, поломки