Архитектура
Citeck Launcher – единый бинарный файл на Go (~24 МБ) без внешних зависимостей (pure Go, без CGO). Он совмещает в себе CLI-клиент и фоновый демон, взаимодействующий с Docker Engine для управления контейнерами платформы.
Общая схема
+------------------+ Unix socket +------------------+
| | ----------------------> | |
| CLI (citeck) | HTTP API | Daemon |
| | <---------------------- | (HTTP server) |
+------------------+ +--------+---------+
|
Docker SDK
|
+--------v---------+
| |
| Docker Engine |
| |
+--------+---------+
|
+------------------------------------------+
| | |
+------v------+ +------v------+ +----------v--+
| postgres | | keycloak | | eapps |
+-------------+ +-------------+ +-------------+
| zookeeper | | rabbitmq | | emodel |
+-------------+ +-------------+ +-------------+
| proxy | | pgadmin | | uiserv |
+-------------+ +-------------+ +-------------+
Компоненты:
CLI – Cobra-команды, форматирование вывода (текст/JSON), интерактивные TUI-промпты
Daemon – HTTP-сервер на Unix-сокете, обслуживающий REST API и SSE-поток событий
Docker SDK – прямое взаимодействие с Docker Engine через официальный Go SDK
Контейнеры – Docker-контейнеры с компонентами платформы Citeck
Взаимодействие CLI и демона
CLI и демон общаются через Unix-сокет (/run/citeck/daemon.sock). Все команды CLI отправляют HTTP-запросы к демону:
citeck status -> GET /api/v1/namespace
citeck start -> POST /api/v1/namespace/start
citeck stop -> POST /api/v1/namespace/stop
citeck reload -> POST /api/v1/namespace/reload
citeck logs -> GET /api/v1/apps/{name}/logs
Для мониторинга в реальном времени (citeck status --watch, citeck start) используется SSE (Server-Sent Events), а не WebSocket.
Жизненный цикл контейнеров
Каждое приложение проходит через состояния:
READY_TO_PULL --> PULLING --> DEPS_WAITING --> STARTING --> RUNNING
^ | |
| v v
| PULL_FAILED START_FAILED
| |
+--------------------------------------------+
(reconciler retry: 1m -> 30m)
Описание состояний:
Состояние |
Описание |
|---|---|
|
Начальное состояние, готово к загрузке образа |
|
Загрузка Docker-образа |
|
Ошибка загрузки образа |
|
Ожидание запуска зависимостей (например, postgres перед keycloak) |
|
Контейнер создан и запускается |
|
Контейнер работает, liveness-проверка пройдена |
|
Контейнер не смог запуститься |
|
Контейнер остановлен |
При сбое запуска реконсилер автоматически повторяет попытку с экспоненциальным backoff: 1 минута, 2 минуты, 4 минуты, …, до максимума 30 минут.
Порядок запуска
Приложения запускаются с учётом зависимостей:
Фаза 1: postgres
Фаза 2: keycloak, zookeeper, rabbitmq
Фаза 3: Веб-приложения (eapps, emodel, gateway, ...)
Фаза 4: proxy
Каждое приложение ожидает готовности своих зависимостей (состояние DEPS_WAITING), прежде чем начать запуск.
Порядок остановки – обратный:
Фаза 1: proxy
Фаза 2: Веб-приложения
Фаза 3: keycloak, zookeeper, rabbitmq
Фаза 4: postgres
Deployment hash
При команде reload лончер использует механизм, аналогичный docker-compose up:
Для каждого приложения вычисляется deployment hash на основе:
Docker-образа (image + tag)
Переменных окружения
Смонтированных томов
Портов
Лимитов ресурсов
Зависимостей
Hash сравнивается с hash работающего контейнера.
Только изменённые контейнеры пересоздаются – неизменённые продолжают работать без прерывания.
Примечание
Стабильность функции GetHashInput является жёстким контрактом совместимости между версиями лончера. Изменение алгоритма хеширования требует миграции.
Обновление CLI и демона
Установку CLI и демона обновляет тот же install.sh, что и первичная
установка – он определяет факт наличия предыдущей версии и переключается
в режим обновления:
curl -fsSL https://github.com/Citeck/citeck-launcher/releases/latest/download/install.sh | bash
При обновлении бинарного файла лончера:
Создаётся резервная копия текущего бинарного файла (
/usr/local/bin/citeck.bak).Демон останавливается в режиме detach: процесс демона завершается, но контейнеры Docker продолжают работать.
Новый бинарный файл копируется в
/usr/local/bin/citeck.Запускается новый демон, который подхватывает работающие контейнеры через сравнение deployment hash.
Старый демон Новый демон
+-----------+ +-----------+
| daemon v1 | --detach--> | daemon v2 |
+-----------+ (containers +-----------+
| stay running) |
+----v----+ +----v----+
| Docker | =================> | Docker |
| Engine | (контейнеры | Engine |
+---------+ сохранены) +---------+
Что происходит с приложениями зависит от того, изменился ли их
deployment hash (см. раздел «Smart regenerate» выше):
Hash приложения не изменился (новая версия CLI не меняет формат generator-а для этого типа приложения) – контейнер продолжает работать без перезапуска. Это типичный сценарий zero-downtime-обновления.
Hash приложения изменился (например, новая версия добавила переменную окружения в generator, сменился формат volume mount, обновилась версия образа в бандле) – соответствующие контейнеры пересоздаются. Ожидаемое время простоя по каждому такому приложению – от 1 до 5 минут (зависит от типа сервиса; Java-приложения дольше).
Примечание
Чтобы заранее узнать, какие приложения будут пересозданы, после
обновления бинарника выполните citeck reload --dry-run. Команда
покажет список контейнеров с изменённым hash до того, как вы их
фактически перезапустите.
Если обновление прошло неудачно, используйте откат:
citeck install --rollback
Это восстановит бинарный файл из .bak и перезапустит демон.
Контейнеры Docker не затрагиваются.
Интеграция с systemd
Лончер автоматически создаёт systemd-сервис при установке:
Unit-файл: /etc/systemd/system/citeck.service
Основные характеристики:
Restart=on-failure – автоматический перезапуск при сбое демона
Контейнеры Docker продолжают работать при перезапуске демона
Новый экземпляр демона подхватывает работающие контейнеры через hash matching
При обновлении используется runtime drop-in (
/run/systemd/system/citeck.service.d/no-restart.conf), чтобы systemd не перезапустил старый демон в момент замены бинарного файла
Управление через systemd:
# Статус сервиса
systemctl status citeck
# Логи демона через journald
journalctl -u citeck -f
# Перезапуск (контейнеры сохраняются)
systemctl restart citeck
Предупреждение
Не используйте systemctl stop citeck для остановки платформы. Это остановит только демон, но не контейнеры. Используйте citeck stop --shutdown.
Управление секретами
Секреты хранятся с шифрованием AES-256-GCM в директории /opt/citeck/conf/secrets/.
Типы секретов:
Системные – генерируются автоматически:
JWT-ключ для подписи токенов
OIDC client secret для интеграции с Keycloak
Пароль администратора — для пользовательского входа (ecos-app realm)
Пароль сервисной УЗ
citeck— для внутренних операций с KeycloakПароли для RabbitMQ и PgAdmin
Пользовательские – задаются через
citeck setup:Пароль SMTP
Secret key для S3
Учётные данные Docker-реестра
Каждый секрет шифруется отдельно. Мастер-пароль используется для вывода ключей шифрования (PBKDF2-HMAC-SHA256).
Реконсилер
Реконсилер – фоновый процесс, работающий в демоне, который обеспечивает соответствие желаемого и фактического состояния контейнеров:
Периодическая проверка (по умолчанию каждые 60 секунд): сравнивает конфигурацию с реальным состоянием Docker.
Liveness-проверки (по умолчанию каждые 30 секунд): выполняет HTTP-запрос к health endpoint приложения. После 3 последовательных неудач – перезапуск.
Автовосстановление: при обнаружении упавшего контейнера инициирует повторный запуск с экспоненциальным backoff.
Настройка через /opt/citeck/conf/daemon.yml:
reconciler:
interval: 60
livenessPeriod: 30000
livenessEnabled: true