Капстоун, шаг 1: планирование пакета Firefly III
Что нужно знать перед уроком
- M10.10 — Troubleshooting по статусной модели — весь курс M0–M10 пройден — капстоун применяет накопленные знания самостоятельно, без новой теории
- M5.01 — Анатомия пакета Application целиком — нужна структура пакета как отправная точка планирования
Что нужно знать перед уроком
Это первый из пяти уроков капстоуна — итогового модуля курса. В отличие от всех предыдущих уроков, где новая концепция вводилась и тут же закреплялась практикой, капстоун не вводит новых концепций — он требует самостоятельно спланировать и собрать production-ready Application-пакет, применяя весь стек знаний M0–M10 к новому приложению — Firefly III, self-hosted менеджер личных финансов (PHP/Laravel + MySQL/MariaDB, AGPL-3.0). Перед этим уроком нужно уверенно ориентироваться в: анатомии пакета (M5 урок 1), полях package.yaml (M5 урок 2), контракте настроек (M5 урок 3), ограничениях Application (M5 урок 5) и модели requirements.modules.mandatory (M6 урок 1).
Теория
Почему именно Firefly III для капстоуна
На протяжении курса каждый урок использовал новое self-hosted приложение возрастающей сложности — от тривиального статического контейнера Excalidraw (M1 урок 1) до полноценного сквозного примера Umami (M5–M10). Firefly III выбран для финального капстоуна по трём причинам, делающим его показательным mid-size приложением:
- PHP/Laravel-стек — ни разу не встречался в курсе (Vikunja — Go, Umami — Node.js), что вынуждает самостоятельно перенести уже усвоенные паттерны (werf-сборка, Nelm-шаблоны, миграции) на незнакомый рантайм, а не копировать готовое решение.
- Жёсткая зависимость от реляционной БД — Firefly III не может работать без MySQL/MariaDB (или PostgreSQL, но капстоун фиксирует MySQL для симметрии с уже пройденным managed-postgres в M6), что требует полноценного применения
requirements.modules.mandatoryс новым модулем —managed-mysql. - Одноразовый секрет уровня приложения (
APP_KEY, аналог LaravelAPP_KEY— 32-байтный ключ шифрования, генерируемый один раз и не должный меняться между обновлениями) — заставляет применить паттерн «ресурс только при первой установке» из M7 урока 8 (use case 6,deploy-on: install+ownership: anyone) в реальном сценарии, а не в изолированном примере.
Формальный план работы: пять шагов капстоуна
Это прямое повторение маршрута всего курса в миниатюре: M3 (сборка) → M4–M7 (Nelm-чарт и зависимости) → M8–M9 (CI/CD и публикация) → M10 (эксплуатационная готовность), только все решения принимает сам разработчик, а не берёт готовые ответы из теории урока.
Шаг планирования 1 — анализ приложения перед написанием кода
Прежде чем создавать структуру пакета командой d8 package bootstrap (M5 урок 1), необходимо ответить на вопросы, которые в предыдущих модулях уже были даны в готовом виде для Umami/Vikunja:
| Вопрос | Ответ для Firefly III |
|---|---|
| Какой рантайм и какой официальный образ существует? | PHP 8.x + Apache/FPM, официальный образ fireflyiii/core на Docker Hub — используется как референс для собственной Stapel-сборки (M3 урок 3), а не копируется напрямую |
| От какого Module зависит функционально? | managed-mysql (mandatory) — без базы данных приложение не проходит даже первичную инициализацию Laravel |
| Нужен ли постоянный том? | Да — каталог storage/upload (вложения транзакций) и storage/logs; данные критичны — требуется полная модель защиты из M6 урока 7 |
| Нужна ли Job-миграция? | Да — php artisan migrate --force перед запуском основного контейнера, паттерн из M6 урока 4 |
| Нужен ли одноразовый секрет? | Да — APP_KEY (php artisan key:generate), паттерн deploy-on: install + ownership: anyone из M7 урока 8 |
| Какая внешняя точка входа? | HTTP через Ingress/HTTPRoute (M1 уроки 8–9) |
| Какой уровень сложности проб? | startupProbe обязателен (миграция и прогрев Laravel-кэша конфигурации занимают заметное время при первом старте, аналогично мотивации startupProbe в M1 уроке 7 на примере Node-RED) |
Этот вопросник — не формальность, а систематизация того самого анализа, который в модулях M1–M10 курс проводил за студента при выборе очередного OSS-приложения; теперь эта работа выполняется самостоятельно.
package.yaml для Firefly III
| |
Прямое применение полей, разобранных в M5 уроке 2 — apiVersion/type/stage/category как обязательные поля манифеста, name (≤ 24 символов, соблюдено), descriptions на обоих языках (M9 урок 7 требует их для приёмки), объектный формат requirements.deckhouse.constraint/requirements.kubernetes.constraint (а не плоская строка), и ключевая для капстоуна секция requirements.modules.mandatory, зафиксированная в M6 уроке 1 как единственно допустимый способ для Application задекларировать жёсткую зависимость от платформенного компонента.
Контракт настроек: config-values.yaml для Firefly III
Проектируется по правилам M5 урока 3 — пользователю экспонируются только осмысленные для конфигурации параметры, внутренние детали (сгенерированный APP_KEY, реквизиты managed-mysql) остаются в internal.* и никогда не попадают в config-values.yaml:
| |
Частые ошибки и подводные камни
- Начинать с написания шаблонов Nelm до завершения планирования зависимостей. Как показывает вопросник выше, решение «какой Module обязателен» напрямую влияет на структуру
templates/(потребуетсяSecret/ConfigMapс реквизитами подключения к БД, разобранный принцип получения данных о зависимом Module — M6 урок 2) — планирование зависимостей должно предшествовать написанию манифестов, а не следовать за ним. - Копировать официальный
docker-entrypoint.shобразаfireflyiii/coreдословно, включая логику авто-миграции при старте контейнера. Официальный образ мигрирует схему БД автоматически при каждом запуске — это удобно для одиночногоdocker run, но противоречит паттерну курса «явныйJob-миграция передDeployment» (M6 урок 4), обеспечивающему предсказуемый, наблюдаемый и не гоняющийся параллельно с несколькими репликами процесс миграции. - Забыть зафиксировать вопросник анализа приложения в документации пакета. Ответы на вопросы из таблицы (почему выбран именно
managed-mysql, почему нуженstartupProbe) стоит явно задокументировать вdocs/README.mdпакета — это упрощает онбординг следующего разработчика, продолжающего сопровождение пакета.
Linux / Сети / Docker
Firefly III в официальном образе объединяет PHP-FPM и веб-сервер (Apache или nginx+php-fpm, в зависимости от варианта тега образа) в одном контейнере — это классический паттерн «multi-process container», отличающийся от связки из двух отдельных образов/контейнеров (например, отдельно nginx и отдельно php-fpm как sidecar), которую студент мог видеть в других PHP-проектах. Собственная Stapel-сборка капстоуна (следующий урок) должна явно решить, следовать ли этому паттерну (один процесс-менеджер вроде supervisord внутри контейнера) или разделить на два контейнера в одном Pod — оба подхода валидны, различие в компромиссах, разобранных в M1 уроке 1 (совместное размещение процессов в одном Pod оправдано только при тесной связи жизненного цикла).
Практика в кластере
Практики установки в кластере в этом уроке нет — она начнётся в M11 уроке 5, после завершения сборки образа (шаг 2) и Application-чарта (шаг 3). На этом шаге — только подготовка окружения:
| |
Практика разработки
- Изучите официальный репозиторий Firefly III, обратив внимание на
.env.example(полный список переменных окружения — основа для будущегоopenapi/values.yaml) иdocker/entrypoint.sh(что именно происходит при старте — для сравнения с собственным явным паттерном миграции):
| |
- Инициализируйте скелет пакета:
| |
- Заполните
package.yamlиopenapi/config-values.yamlпо образцам из теории урока, зафиксируйте их в git:
| |
Шпаргалка команд урока
| |
Полная шпаргалка d8:
📋 d8
.
Вопросы для самопроверки
Капстоун проверяет перенос общих принципов, а не запоминание конкретного стека.
Источник: Рекомендуемая литература
Firefly III зависит от реляционной СУБД; капстоун фиксирует MySQL/MariaDB через managed-mysql для симметрии с managed-postgres, уже разобранным в M6.
Источник: Рекомендуемая литература
M6 урок 4 явно разбирает, почему миграция должна быть отдельным управляемым Job, а не неявной частью старта контейнера.
Источник: Рекомендуемая литература
Это прямое применение разграничения config-values.yaml/internal.*, разобранного в M5 уроке 3.
Источник: Рекомендуемая литература
Та же мотивация, что и для Node-RED в M1 уроке 7 — заметная задержка старта требует отдельного startupProbe.
Источник: Рекомендуемая литература
Рекомендуемая литература
Официальная документация
Статьи и блоги
- Готовим Gitea со вкусом werf CI/CD в кластере Deckhouse. Часть 3 — Flant на Habr.
- Разворачиваем приложение в кластере Kubernetes под управлением Deckhouse c помощью werf — Flant на Habr.
- GitLab + K8s + Werf — Habr.
Книги
- Gene Kim, Jez Humble, Patrick Debois, John Willis. The DevOps Handbook. 2nd ed., 2021. ISBN 978-1942788003.
Связанные материалы
- Предыдущий модуль: M10.10 — Troubleshooting по статусной модели.
- Следующий урок: M11.02 — Сборка образа Firefly III через werf.
- Опорные уроки: M5 — Application: глубокое погружение, M6 — Зависимости.
✓ Урок пройден — все вопросы самопроверки отвечены верно