Перейти к основному содержанию Перейти к навигации Перейти к нижнему колонтитулу

Правила Rediacc

Основные правила и соглашения для разработки приложений на платформе Rediacc. Охватывает Rediaccfile, compose, сетевую конфигурацию, хранение, CRIU и развёртывание.

Правила Rediacc

Каждый репозиторий Rediacc работает в изолированной среде с собственным Docker-демоном, зашифрованным томом LUKS и выделенным диапазоном IP-адресов. Эти правила обеспечивают корректную работу вашего приложения в рамках этой архитектуры.

Rediaccfile

  • Каждому репозиторию нужен Rediaccfile — bash-скрипт с функциями жизненного цикла.
  • Функции жизненного цикла: up(), down(). Необязательная: info().
  • up() запускает ваши сервисы. down() останавливает их.
  • info() предоставляет информацию о состоянии (состояние контейнеров, последние логи, здоровье).
  • Rediaccfile подключается (source) через renet — имеет доступ к переменным оболочки, а не только к переменным окружения.

Доступные переменные окружения в Rediaccfile

ПеременнаяПримерОписание
REDIACC_WORKING_DIR/mnt/rediacc/mounts/abc123/Корневой путь смонтированного репозитория
REDIACC_NETWORK_ID6336Идентификатор сетевой изоляции
REDIACC_REPOSITORYabc123-...GUID репозитория
{SVCNAME}_IPHEARTBEAT_IP=127.0.24.195Loopback IP для каждого сервиса (имя сервиса в верхнем регистре)

Минимальный Rediaccfile

#!/bin/bash

_compose() {
  renet compose -- "$@"
}

up() {
  _compose up -d
}

down() {
  _compose down
}

Compose

  • Используйте renet compose, никогда docker compose — renet внедряет сетевую изоляцию, хост-сеть, loopback IP-адреса и метки сервисов.
  • НЕ устанавливайте network_mode в вашем compose-файле — renet принудительно устанавливает network_mode: host для всех сервисов. Любое ваше значение будет перезаписано.
  • НЕ устанавливайте метки rediacc.* — renet автоматически внедряет rediacc.network_id, rediacc.service_ip и rediacc.service_name.
  • Маппинги ports: игнорируются в режиме хост-сети. Используйте метку rediacc.service_port для маршрутизации прокси на порты, отличные от 80.
  • Политики перезапуска (restart: always, on-failure и др.) безопасны в использовании — renet автоматически удаляет их для совместимости с CRIU. Watchdog маршрутизатора автоматически восстанавливает остановленные контейнеры на основе исходной политики, сохранённой в .rediacc.json.
  • Опасные настройки заблокированы по умолчаниюprivileged: true, pid: host, ipc: host и bind-монтирование системных путей отклоняются. Используйте renet compose --unsafe для переопределения на ваш страх и риск.

Переменные окружения внутри контейнеров

Renet автоматически внедряет их в каждый контейнер:

ПеременнаяОписание
SERVICE_IPВыделенный loopback IP этого контейнера
REDIACC_NETWORK_IDID сетевой изоляции

Именование сервисов и маршрутизация

  • The compose service name becomes the auto-route URL prefix.
  • Grand repos: https://{service}.{repo}.{machine}.{baseDomain} (например: https://myapp.marketing.server-1.example.com).
  • Fork repos: https://{service}-{tag}.{machine}.{baseDomain} — uses the machine wildcard cert to avoid Let’s Encrypt rate limits.
  • Для пользовательских доменов используйте метки Traefik (примечание: пользовательские домены НЕ совместимы с fork — домен принадлежит grand repo).

Сеть

  • Каждый репозиторий получает собственный Docker-демон по пути /var/run/rediacc/docker-<networkId>.sock.
  • Каждый сервис получает уникальный loopback IP в подсети /26 (например, 127.0.24.192/26).
  • Привязывайтесь к SERVICE_IP — каждый сервис получает уникальный loopback IP.
  • Health-проверки должны использовать ${SERVICE_IP}, а не localhost. Пример: healthcheck: test: ["CMD", "curl", "-f", "http://${SERVICE_IP}:8080/health"]
  • Межсервисное взаимодействие: Используйте loopback IP-адреса или переменную окружения SERVICE_IP. DNS-имена Docker НЕ работают в хост-режиме.
  • Конфликты портов невозможны между репозиториями — у каждого свой Docker-демон и диапазон IP-адресов.
  • Перенаправление портов TCP/UDP: Добавьте метки для открытия не-HTTP портов:
    labels:
      - "rediacc.tcp_ports=5432,3306"
      - "rediacc.udp_ports=53"

Хранение

  • Все данные Docker хранятся внутри зашифрованного репозиторияdata-root Docker находится по пути {mount}/.rediacc/docker/data внутри тома LUKS. Именованные тома, образы и слои контейнеров — всё зашифровано, включено в резервные копии и автоматически форкается.
  • Bind-монтирование в ${REDIACC_WORKING_DIR}/... рекомендуется для ясности, но именованные тома также работают безопасно.
    volumes:
      - ${REDIACC_WORKING_DIR}/data:/data        # bind-монтирование (рекомендуется)
      - pgdata:/var/lib/postgresql/data      # именованный том (тоже безопасно)
  • Том LUKS монтируется в /mnt/rediacc/mounts/<guid>/.
  • Снапшоты BTRFS захватывают весь файл поддержки LUKS, включая все данные bind-монтирования.
  • Хранилище данных — это файл пула BTRFS фиксированного размера на системном диске. Используйте rdc machine query <name> --system для просмотра эффективного свободного пространства. Расширяйте с помощью rdc datastore resize.

CRIU (Живая миграция)

  • Подключение через метку: Добавьте rediacc.checkpoint=true к контейнерам, которые хотите чекпоинтить. Контейнеры без метки (базы данных, кеши) запускаются заново и восстанавливаются через собственные механизмы (WAL, LDF, AOF).
  • backup push --checkpoint захватывает состояние памяти работающих процессов + состояние диска для помеченных контейнеров.
  • repo fork --checkpoint захватывает состояние процессов перед форком — форк автоматически восстанавливается при repo up.
  • repo down --checkpoint сохраняет состояние процессов перед остановкой — при следующем repo up автоматически восстанавливается.
  • repo up автоматически обнаруживает данные чекпоинта и восстанавливает при наличии. Используйте --skip-checkpoint для чистого запуска.
  • Восстановление с учётом зависимостей: Использует compose depends_on для запуска баз данных первыми (ожидание healthy), затем CRIU-восстановление контейнеров приложения.
  • TCP-соединения становятся устаревшими после восстановления — приложения должны обрабатывать ECONNRESET и переподключаться.
  • Экспериментальный режим Docker включается автоматически на демонах каждого репозитория.
  • CRIU устанавливается во время rdc config machine setup.
  • /etc/criu/runc.conf настроен с tcp-established для сохранения TCP-соединений.
  • Настройки безопасности контейнеров автоматически внедряются для помеченных контейнеровrenet compose добавляет следующее к контейнерам с rediacc.checkpoint=true:
    • cap_add: CHECKPOINT_RESTORE, SYS_PTRACE, NET_ADMIN (минимальный набор для CRIU на ядре 5.9+)
    • security_opt: apparmor=unconfined (поддержка AppArmor в CRIU ещё нестабильна)
    • userns_mode: host (CRIU требует доступ к пространству имён init для /proc/pid/map_files)
  • Контейнеры без метки работают с более чистым профилем безопасности (без дополнительных capabilities).
  • Стандартный профиль seccomp Docker сохраняется — CRIU использует PTRACE_O_SUSPEND_SECCOMP (ядро 4.3+) для временной приостановки фильтров во время checkpoint/restore.
  • НЕ устанавливайте CRIU capabilities вручную в файле compose — renet управляет ими на основе метки.
  • Смотрите шаблон heartbeat для эталонной реализации, совместимой с CRIU.

Паттерны приложений, совместимых с CRIU

  • Обрабатывайте ECONNRESET на всех постоянных соединениях (пулы баз данных, вебсокеты, очереди сообщений).
  • Используйте библиотеки пулов соединений, поддерживающие автоматическое переподключение.
  • Добавьте process.on("uncaughtException") как страховочную сеть для ошибок устаревших сокетов от внутренних объектов библиотек.
  • Политики перезапуска управляются автоматически renet (удаляются для CRIU, watchdog обрабатывает восстановление).
  • Не полагайтесь на DNS Docker — используйте loopback IP-адреса для межсервисного взаимодействия.

Безопасность

  • Шифрование LUKS обязательно для стандартных репозиториев. Каждый репозиторий имеет свой ключ шифрования.
  • Учётные данные хранятся в конфигурации CLI (~/.config/rediacc/rediacc.json). Потеря конфигурации означает потерю доступа к зашифрованным томам.
  • Никогда не коммитьте учётные данные в систему контроля версий. Используйте env_file и генерируйте секреты в up().
  • Изоляция репозитория: Docker-демон, сеть и хранилище каждого репозитория полностью изолированы от других репозиториев на той же машине.
  • Изоляция агентов: ИИ-агенты по умолчанию работают в режиме только fork. Каждый репозиторий имеет собственный SSH-ключ с серверным применением sandbox (ForceCommand sandbox-gateway). Все соединения изолированы с помощью Landlock LSM, оверлея OverlayFS для домашней директории и TMPDIR для каждого репозитория. Доступ к файловой системе между репозиториями блокируется ядром.

Развёртывание

  • rdc repo up выполняет up() во всех Rediaccfile.
  • rdc repo up --mount сначала открывает том LUKS, затем выполняет жизненный цикл. Требуется после backup push на новую машину.
  • rdc repo down выполняет down() и останавливает Docker-демон.
  • rdc repo down --unmount также закрывает том LUKS (блокирует зашифрованное хранилище).
  • Форки (rdc repo fork) создают CoW-клон (copy-on-write) с новым GUID и networkId. Форк разделяет ключ шифрования родителя.
  • Takeover (rdc repo takeover <fork> -m <machine>) заменяет данные grand-репозитория данными форка. Grand сохраняет свою идентичность (GUID, networkId, домены, автозапуск, цепочку резервных копий). Старые производственные данные сохраняются как резервный форк. Использование: тестировать обновление на форке, проверить, затем выполнить takeover в продакшн. Откатить с помощью rdc repo takeover <backup-fork> -m <machine>.
  • Маршруты прокси становятся активными примерно через 3 секунды после развёртывания. Предупреждение «Proxy is not running» во время repo up является информационным в средах ops/dev.

Распространённые ошибки

  • Использование docker compose вместо renet compose — контейнеры не получат сетевую изоляцию.
  • Политики перезапуска безопасны — renet автоматически удаляет их, watchdog обрабатывает восстановление.
  • Использование privileged: true — не нужно, renet вместо этого внедряет специальные capabilities для CRIU.
  • Не привязываться к SERVICE_IP — вызывает конфликты портов между репозиториями.
  • Жёсткое кодирование IP-адресов — используйте переменную окружения SERVICE_IP; IP-адреса выделяются динамически для каждого networkId.
  • Забыли --mount при первом развёртывании после backup push — том LUKS требует явного открытия.
  • Использование rdc term -c как обходного пути для неудачных команд — вместо этого сообщайте об ошибках.
  • repo delete выполняет полную очистку, включая loopback IP-адреса и systemd-юниты. Запустите rdc machine prune <name> для очистки остатков от устаревших удалений.