feat: migrate to VitePress from monorepo docs, add test-contour section
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,527 @@
|
||||
---
|
||||
title: Backend — внешние сервисы и стратегия для test/stage/prod
|
||||
---
|
||||
|
||||
# Backend: внешние сервисы, БД и интеграции
|
||||
|
||||
> Разбор всех **сторонних зависимостей** `apps/backend`: что они делают, где используются в коде, и **что делать в тестовом контуре** (K8s) — поднять свой инстанс, поставить заглушку или эмулятор.
|
||||
>
|
||||
> Связанные документы: [K8s + Terraform + ArgoCD + Gitea](./k8s-cicd-platform-plan.md), локальный контур (`local/`, см. корень репозитория), [бизнес-сценарии](../apps/backend-scenarios/index.md).
|
||||
|
||||
---
|
||||
|
||||
## 0. Сводная матрица решений (test-контур)
|
||||
|
||||
| # | Зависимость | Тип | Где в коде | Test-контур | Stage | Prod |
|
||||
|---|-------------|-----|------------|-------------|-------|------|
|
||||
| 1 | PostgreSQL (основная) | БД | `DATABASE_URL`, Doctrine ORM | **Новый инстанс** (1×) | 1× на stage-сервере | **HA: primary + sync replica** (§7.6 плана) |
|
||||
| 2 | PostgreSQL (cabinet) | БД | `DATABASE_CABINET_URL`, `UsrlogController` | **Новый инстанс** + seed | Отдельный | Prod |
|
||||
| 3 | MySQL (Bitrix CMS) | БД | `DATABASE_BITRIX_URL`, `BitrixService`, SQL views | **Новый инстанс** + seed из `local/mysql-bitrix` | Отдельный | Prod Bitrix |
|
||||
| 4 | Redis | Кеш/сессии | `REDIS_URL` | **Новый инстанс** в K8s | Отдельный | Prod Redis |
|
||||
| 5 | MIS / Инфоклиника (HTTP) | API | `MIS_URL`, `InfoclinicaClientService` | **Mock-сервис** (WireMock / свой stub) | Test MIS или read-only prod | Prod MIS |
|
||||
| 6 | Widget API (`widget.sovamed.ru`) | API | Hardcoded в Upload*Command | **Mock** или `MIS_URL` после рефакторинга | Stage widget | Prod |
|
||||
| 7 | Bitrix site (HTTP, картинки) | API | `BITRIX_URL`, `BitrixClientService` | **Mock** (static files) или seed URLs | Stage | Prod |
|
||||
| 8 | SMS (sms.ru, sms4b) | API | `SMSRU_*`, `SMS4B_*` | **Заглушка** (noop) | Заглушка | **Реальный** провайдер |
|
||||
| 9 | Почта | API | `MAILER_DSN`, `SendMailService` | **Mailpit / null://null** | Mailpit или sandbox SMTP | Prod SMTP |
|
||||
| 10 | Yandex SmartCaptcha | API | `SMARTCAPTCHA_*`, `ServiceController` | **Заглушка** (always OK) | Заглушка | **Реальный** ключ |
|
||||
| 11 | Calltouch | API | `CT_*`, `CalltouchController` | **Заглушка** (noop, уже частично) | Заглушка | **Реальный** API |
|
||||
| 12 | Bitrix24 | — | `BITRIX24_URL` в `.env` | **Не используется в коде** — игнор | — | При появлении интеграции |
|
||||
| 13 | JWT / AES / Lock | Локально | env + файлы ключей | **Свои ключи** test | Свои | Prod secrets |
|
||||
| 14 | Symfony Messenger | Очередь | `MESSENGER_TRANSPORT_DSN` | `doctrine://` или `sync://` | doctrine/redis | prod queue |
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph backend [backend pod]
|
||||
API[Symfony API]
|
||||
CMD[Console / CronJobs]
|
||||
end
|
||||
|
||||
subgraph own_test [Поднимаем в test — свои инстансы]
|
||||
PG[(PostgreSQL main)]
|
||||
PGC[(PostgreSQL cabinet)]
|
||||
MY[(MySQL Bitrix)]
|
||||
RD[(Redis)]
|
||||
end
|
||||
|
||||
subgraph stubs [Заглушки в test]
|
||||
MIS_M[Mock MIS / Widget API]
|
||||
SMS_M[Noop SMS]
|
||||
MAIL_M[Mailpit]
|
||||
CAP_M[Mock SmartCaptcha]
|
||||
CT_M[Noop Calltouch]
|
||||
BTX_M[Mock Bitrix HTTP images]
|
||||
end
|
||||
|
||||
subgraph prod_only [Только prod / stage по решению]
|
||||
MIS_P[Реальная Инфоклиника]
|
||||
SMS_P[sms.ru / sms4b]
|
||||
CAP_P[Yandex SmartCaptcha]
|
||||
CT_P[Calltouch]
|
||||
end
|
||||
|
||||
API --> PG
|
||||
API --> PGC
|
||||
API --> MY
|
||||
API --> RD
|
||||
API --> MIS_M
|
||||
API --> SMS_M
|
||||
API --> MAIL_M
|
||||
API --> CAP_M
|
||||
API --> CT_M
|
||||
API --> BTX_M
|
||||
CMD --> PG
|
||||
CMD --> MY
|
||||
CMD --> MIS_M
|
||||
|
||||
MIS_P -.->|stage/prod| API
|
||||
SMS_P -.->|prod| API
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Базы данных (с БД — новый инстанс)
|
||||
|
||||
### 1.1. PostgreSQL — основная (`DATABASE_URL`)
|
||||
|
||||
**Назначение:** все Doctrine-сущности backend (`User`, `Specialist`, `News`, `Schedule`, …).
|
||||
|
||||
**Где используется:**
|
||||
|
||||
- `config/packages/doctrine.yaml` → connection `default`
|
||||
- все Repository, миграции `apps/backend/migrations`
|
||||
- кеш расписания (`Schedule` в таблице, не Redis)
|
||||
- Symfony Messenger при `MESSENGER_TRANSPORT_DSN=doctrine://default`
|
||||
|
||||
**Test:** Helm Bitnami PostgreSQL / CNPG `instances: 1` в `sova-data-test`.
|
||||
|
||||
**Stage:** один PG на **отдельном stage-сервере**.
|
||||
|
||||
**Prod:** Patroni (2 db-VM) + **witness etcd на отдельной VM** (не prod-app). Подключение: `DATABASE_URL` → PgBouncer **:6432** (transaction, API); migrate Job и Messenger → **:5432** (session). [§7.6 плана](./k8s-cicd-platform-plan.md).
|
||||
|
||||
**Stage/Prod:** отдельные credentials; **никогда** не указывать prod URL в test.
|
||||
|
||||
---
|
||||
|
||||
### 1.2. PostgreSQL — cabinet (`DATABASE_CABINET_URL`)
|
||||
|
||||
**Назначение:** read-only доступ к legacy-таблицам cabinet (не Doctrine entities backend).
|
||||
|
||||
**Где используется:**
|
||||
|
||||
- `config/packages/doctrine.yaml` → connection `cabinet`
|
||||
- `UsrlogController` — `SELECT` из `public.usrlog` через `doctrine.dbal.cabinet_connection`
|
||||
|
||||
**Test:** отдельный PostgreSQL (можно второй database на том же chart), seed из `local/postgres/init/03-cabinet-schema-and-seed.sql`.
|
||||
|
||||
**Если usrlog не нужен в test:** connection можно оставить на пустую БД; эндпоинт `/usrlog/list` вернёт пустой список.
|
||||
|
||||
---
|
||||
|
||||
### 1.3. MySQL — Bitrix CMS (`DATABASE_BITRIX_URL`)
|
||||
|
||||
**Назначение:** чтение таблиц Bitrix (`b_iblock_*`, `b_file`) для синхронизации контента и отзывов.
|
||||
|
||||
**Где используется:**
|
||||
|
||||
| Компонент | Как |
|
||||
|-----------|-----|
|
||||
| `BitrixService` | прямые SQL через `doctrine.dbal.mysql_connection` |
|
||||
| `BitrixUpdateReviewsCommand` | `getReviews()` — отзывы по `specialist.id` |
|
||||
| `BitrixUpdateDoctorsCommand` | нормализация `dcodes` (Bitrix HTTP закомментирован) |
|
||||
| `*CrudService::syncFromView*` | `INSERT … SELECT FROM public.view_*` |
|
||||
| Миграции | views `view_article`, `view_news`, … с JOIN на `b_*` (через **mysql_fdw** на prod или упрощённые views в test) |
|
||||
|
||||
**Test:** **новый MySQL** в K8s (Bitnami MySQL chart), init SQL из `local/mysql-bitrix/init/` в корне репозитория. Дополнительно — создать упрощённые `view_news`, `view_promo`, … или наполнять таблицы `news`/`promo` через CRUD API без sync-команд.
|
||||
|
||||
**Важно:** на prod PG использует **mysql_fdw** (`infrastructure/pgsql` + extensions). В test можно:
|
||||
|
||||
- **Вариант A (рекомендуется):** mysql_fdw в test-PG → test-MySQL (повторяет prod);
|
||||
- **Вариант B:** отключить sync-команды в test CronJobs, контент только через adminPanel CRUD;
|
||||
- **Вариант C:** materialized views только на PG без FDW (дублировать seed в PG).
|
||||
|
||||
---
|
||||
|
||||
### 1.4. Redis (`REDIS_URL`)
|
||||
|
||||
**Назначение:** Symfony cache, sessions (prod php.ini), потенциально Messenger.
|
||||
|
||||
**Test:** Bitnami Redis в `sova-data-test`, свой пароль в SealedSecret.
|
||||
|
||||
---
|
||||
|
||||
## 2. HTTP-интеграции
|
||||
|
||||
### 2.1. MIS / Инфоклиника (`MIS_URL` → `InfoclinicaClientService`)
|
||||
|
||||
**Prod URL (пример):** `https://widget.sovamed.ru`
|
||||
|
||||
**Эндпоинты клиента:**
|
||||
|
||||
| Метод | Путь | Сценарий |
|
||||
|-------|------|----------|
|
||||
| GET | `/api/reservation/intervals?{query}` | Расписание врача |
|
||||
| GET | `/filials/list` | Список филиалов (через client) |
|
||||
| POST | `/api/reservation/anonymous-reserve` | Анонимная запись |
|
||||
|
||||
**Где вызывается:**
|
||||
|
||||
- `GetScheduleMessageHandler` → `getSchedule()`
|
||||
- `GetAnonymousReserveRequestMessageHandler` → `anonymousReserve()`
|
||||
- `UploadDoctorsCommand`, `UploadDepartmentsCommand` → `$client->request('GET', …)` через `InfoclinicaClientServiceInterface`
|
||||
|
||||
**Test — рекомендация: Mock-сервис в K8s**
|
||||
|
||||
Развернуть **WireMock** или лёгкий **Node/Go stub** в namespace `sova-mocks`:
|
||||
|
||||
```text
|
||||
MIS_URL=http://mis-mock.sova-mocks.svc.cluster.local
|
||||
```
|
||||
|
||||
Stub должен отдавать JSON в формате, который ждёт `InfoclinicaClientService::normalizeSchedule()` (см. [schedule-cache.md](../apps/backend-scenarios/schedule-cache.md)).
|
||||
|
||||
**Альтернативы:**
|
||||
|
||||
| Вариант | Когда |
|
||||
|---------|-------|
|
||||
| WireMock + JSON fixtures | Полный контроль, воспроизводимые тесты |
|
||||
| Отдельный «test MIS» у вендора | Если Infoclinica даёт sandbox (уточнить у владельца интеграции) |
|
||||
| Read-only прокси на prod | **Не рекомендуется** — риск записи/нагрузки |
|
||||
|
||||
**Stage:** sandbox MIS или изолированный контур клиники.
|
||||
|
||||
---
|
||||
|
||||
### 2.2. Widget API (hardcoded `https://widget.sovamed.ru`)
|
||||
|
||||
**Проблема:** часть команд **не читает `MIS_URL`**, а хардкодит URL:
|
||||
|
||||
| Команда | Путь |
|
||||
|---------|------|
|
||||
| `UploadFilialsCommand` | `GET /filials/list` |
|
||||
| `UploadPriceCommand` | `GET /pricelist/list` |
|
||||
| `UploadPriceDepCommand` | `GET /pricelist/departments` |
|
||||
|
||||
**Test:**
|
||||
|
||||
1. **Краткосрочно:** тот же mock-сервис, что для MIS, + **рефакторинг команд** — вынести `base_uri` в env `WIDGET_API_URL` или переиспользовать `MIS_URL`.
|
||||
2. **До рефакторинга:** mock должен слушать на URL, который прописан в коде (или патч через `/etc/hosts` + Ingress) — **технический долг**.
|
||||
|
||||
---
|
||||
|
||||
### 2.3. Bitrix site HTTP (`BITRIX_URL` → `BitrixClientService`)
|
||||
|
||||
**Prod URL (пример):** `https://sovamed.ru`
|
||||
|
||||
**Назначение:** скачивание файлов врачей с путей вида `/upload/iblock/...`.
|
||||
|
||||
**Где используется:**
|
||||
|
||||
- `GetSpecialistPictureMessageHandler` → `getSpecialistImage($path)`
|
||||
|
||||
**Test:**
|
||||
|
||||
| Вариант | Описание |
|
||||
|---------|----------|
|
||||
| **Mock HTTP** | nginx/static с несколькими `.jpg` в `/upload/iblock/` |
|
||||
| **Отключить handler** | Если в test seed картинки уже локальные (`specialist/xxx.jpg`) |
|
||||
| **Прокси на stage Bitrix** | Только read, без записи |
|
||||
|
||||
`BITRIX_URL=http://bitrix-mock.sova-mocks.svc.cluster.local`
|
||||
|
||||
---
|
||||
|
||||
### 2.4. SMS — sms.ru и sms4b (`SMSRU_*`, `SMS4B_*`)
|
||||
|
||||
**Клиенты:** `SmsruClientService`, `Sms4bClientService` (реализуют `SmsClientServiceInterface`).
|
||||
|
||||
**Статус в коде:** сервисы **зарегистрированы** в `config/services.yaml`, но **ни один контроллер/команда их пока не inject'ит**. Сущности `Record` / `AlertSms` есть, логика отправки SMS **не подключена** к HTTP-сценариям.
|
||||
|
||||
**Test (по вашему решению): заглушка**
|
||||
|
||||
```yaml
|
||||
# Symfony: test env — noop implementation
|
||||
App\Service\Client\Interfaces\SmsClientServiceInterface:
|
||||
class: App\Service\Client\Stub\NoopSmsClientService
|
||||
```
|
||||
|
||||
`NoopSmsClientService` пишет в log «SMS suppressed» и возвращает `{ "status": "ok", "stub": true }`.
|
||||
|
||||
**Prod:** реальные `SMSRU_URL` / `SMS4B_URL` и токены из SealedSecret.
|
||||
|
||||
**Stage:** заглушка или отдельный «sandbox»-аккаунт провайдера с whitelist номеров.
|
||||
|
||||
---
|
||||
|
||||
### 2.5. Почта (`MAILER_DSN`, `SendMailService`)
|
||||
|
||||
**Где используется:**
|
||||
|
||||
- `ServiceController::sendmail` — отправка по query-параметрам, защита `MAILER_ACCESS_TOKEN`
|
||||
- Symfony `MailerInterface` → `SendMailService`
|
||||
|
||||
**Prod `.env`:** `MAILER_DSN=null://null` (письма фактически не уходят, но endpoint есть).
|
||||
|
||||
**Test — рекомендация:**
|
||||
|
||||
| DSN | Зачем |
|
||||
|-----|-------|
|
||||
| `smtp://mailpit.sova-mocks:1025` | UI на :8025, видно письма в браузере |
|
||||
| `null://null` | Если endpoint `/service/sendmail` не тестируете |
|
||||
|
||||
**Безопасность Mailpit Web UI:**
|
||||
|
||||
Mailpit UI (`:8025`) **не выставлять в интернет без защиты**. В тестовых письмах могут быть ФИО, mock-пароли, токены сброса (иногда валидные и на stage).
|
||||
|
||||
```yaml
|
||||
# Ingress mailpit.test.sova.dev — только Basic Auth
|
||||
metadata:
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-type: basic
|
||||
nginx.ingress.kubernetes.io/auth-secret: mailpit-basic-auth
|
||||
nginx.ingress.kubernetes.io/auth-realm: "Mailpit test only"
|
||||
```
|
||||
|
||||
Альтернатива: UI **только cluster-internal** (`kubectl port-forward`), SMTP `:1025` — из `sova-test` по Cluster DNS без Ingress.
|
||||
|
||||
**Stage:** Mailpit или корпоративный sandbox SMTP.
|
||||
|
||||
**Prod:** реальный SMTP / API (SendGrid, Yandex 360, …).
|
||||
|
||||
---
|
||||
|
||||
### 2.6. Yandex SmartCaptcha (`SMARTCAPTCHA_URL`, `SMARTCAPTCHA_KEY`)
|
||||
|
||||
**Где используется:**
|
||||
|
||||
- `ServiceController::smartCaptcha` → `POST /smart-captcha`
|
||||
- `AnonymousReserveRequestDto::$captcha` — поле обязательно при записи (валидация на backend)
|
||||
|
||||
**Test — заглушка:**
|
||||
|
||||
Mock возвращает `{ "status": "ok", "message": "" }` для любого token (как Yandex при успехе).
|
||||
|
||||
Или Symfony binding:
|
||||
|
||||
```yaml
|
||||
# when@test
|
||||
App\Service\Client\Interfaces\SmartCaptchaClientServiceInterface:
|
||||
class: App\Service\Client\Stub\AlwaysValidSmartCaptchaClientService
|
||||
```
|
||||
|
||||
**Prod:** реальный `https://smartcaptcha.yandexcloud.net` + prod key.
|
||||
|
||||
**Связь с MIS mock:** при `anonymous-reserve` captcha проверяется на backend **до** вызова MIS; mock captcha достаточен для E2E test.
|
||||
|
||||
---
|
||||
|
||||
### 2.7. Calltouch (`CT_URL`, `CT_PARAMS`)
|
||||
|
||||
**Где используется:**
|
||||
|
||||
- `CalltouchController::createLead` — вызов **`CalltouchClientService::requestCreate` закомментирован**
|
||||
- Клиент готов: `POST /lead-service/v1/api/request/create`
|
||||
|
||||
**Test — заглушка:**
|
||||
|
||||
- Оставить как сейчас (echo request) **или**
|
||||
- `NoopCalltouchClientService` возвращает `{ "data": { "leadId": "test-123" } }`
|
||||
|
||||
**Prod/Stage (маркетинг):** реальные `CT_URL` + region tokens из `CT_PARAMS`.
|
||||
|
||||
---
|
||||
|
||||
### 2.8. Bitrix24 (`BITRIX24_URL`)
|
||||
|
||||
**Статус:** переменная есть в `.env`, **использований в PHP-коде backend не найдено**. Можно не задавать в test до появления интеграции.
|
||||
|
||||
---
|
||||
|
||||
## 3. Локальная инфраструктура (не внешние SaaS)
|
||||
|
||||
| Переменная | Назначение | Test |
|
||||
|------------|------------|------|
|
||||
| `JWT_*` | Lexik JWT auth | Сгенерировать отдельную пару ключей для test |
|
||||
| `AES_SECRET_KEY` | `AESCryptService` (сущность `Record`) | Случайный ключ 32 байта в Secret |
|
||||
| `LOCK_DSN` | Symfony Lock | `flock://` или `postgresql://…` advisory lock |
|
||||
| `MESSENGER_TRANSPORT_DSN` | Очередь | `doctrine://default` (таблица messenger_messages) |
|
||||
| `CORS_ALLOW_ORIGIN` | adminPanel origins | `https://admin.test.sova.dev` |
|
||||
| `API_BASE_URL` | Self-reference / XML feeds | `https://api.test.sova.dev` |
|
||||
| `MAILER_ACCESS_TOKEN` | Защита `/service/sendmail` | Случайный UUID в Secret |
|
||||
|
||||
---
|
||||
|
||||
## 4. Эталон: что уже сделано локально (`local/.env.local`)
|
||||
|
||||
В `apps/backend/.env.local` для `sova-local` уже задан паттерн **mock URL**:
|
||||
|
||||
```dotenv
|
||||
MIS_URL=http://mock-mis.local
|
||||
BITRIX_URL=http://mock-bitrix.local
|
||||
SMS4B_URL=http://mock-sms4b.local
|
||||
MAILER_DSN=null://null
|
||||
SMARTCAPTCHA_URL=http://mock-smartcaptcha.local
|
||||
```
|
||||
|
||||
**Для K8s test** нужно не просто «мёртвые» hostname, а **реально поднятые mock-поды** + DNS внутри кластера (Service names).
|
||||
|
||||
---
|
||||
|
||||
## 5. Архитектура mock-слоя в Kubernetes (test)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph sova_test [namespace sova-test]
|
||||
BE[backend]
|
||||
end
|
||||
|
||||
subgraph sova_mocks [namespace sova-mocks]
|
||||
MIS[mis-mock :8080]
|
||||
BTX[bitrix-http-mock :8080]
|
||||
CAP[captcha-mock :8080]
|
||||
CT[calltouch-mock :8080]
|
||||
MP[mailpit :8025]
|
||||
end
|
||||
|
||||
subgraph sova_data [namespace sova-data-test]
|
||||
PG[(PostgreSQL)]
|
||||
MY[(MySQL Bitrix)]
|
||||
RD[(Redis)]
|
||||
end
|
||||
|
||||
BE --> PG
|
||||
BE --> MY
|
||||
BE --> RD
|
||||
BE --> MIS
|
||||
BE --> BTX
|
||||
BE --> CAP
|
||||
BE --> CT
|
||||
BE --> MP
|
||||
```
|
||||
|
||||
### 5.1. Рекомендуемые Helm releases (test)
|
||||
|
||||
| Release | Chart / образ | Назначение |
|
||||
|---------|---------------|------------|
|
||||
| `mis-mock` | WireMock / custom | расписание, запись, filials, pricelist |
|
||||
| `bitrix-http-mock` | nginx + static | `/upload/iblock/*.jpg` |
|
||||
| `captcha-mock` | tiny HTTP server | `POST /validate` → ok |
|
||||
| `calltouch-mock` | WireMock | lead create |
|
||||
| `mailpit` | axllent/mailpit | SMTP + Web UI (**Basic Auth** на Ingress) |
|
||||
| `postgresql-test` | bitnami/postgresql | main + cabinet DBs |
|
||||
| `mysql-bitrix-test` | bitnami/mysql | Bitrix tables seed |
|
||||
| `redis-test` | bitnami/redis | cache |
|
||||
|
||||
Namespace **`sova-mocks`** общий для всех контуров test (не prod).
|
||||
|
||||
### 5.2. Env backend test (фрагмент SealedSecret)
|
||||
|
||||
```yaml
|
||||
DATABASE_URL: postgresql://sova_test:***@postgresql-test.sova-data-test:5432/sova_backend_test
|
||||
DATABASE_CABINET_URL: postgresql://sova_test:***@postgresql-test.sova-data-test:5432/sova_cabinet_test
|
||||
DATABASE_BITRIX_URL: mysql://bitrix_test:***@mysql-bitrix-test.sova-data-test:3306/sova_bitrix_test
|
||||
REDIS_URL: redis://:***@redis-test.sova-data-test:6379/0
|
||||
MIS_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080
|
||||
BITRIX_URL: http://bitrix-http-mock.sova-mocks.svc.cluster.local:8080
|
||||
SMARTCAPTCHA_URL: http://captcha-mock.sova-mocks.svc.cluster.local:8080
|
||||
SMARTCAPTCHA_KEY: test-key-not-used-by-mock
|
||||
SMSRU_URL: http://noop.invalid
|
||||
SMS4B_URL: http://noop.invalid
|
||||
CT_URL: http://calltouch-mock.sova-mocks.svc.cluster.local:8080
|
||||
MAILER_DSN: smtp://mailpit.sova-mocks.svc.cluster.local:1025
|
||||
MAILER_ACCESS_TOKEN: "<uuid>"
|
||||
CORS_ALLOW_ORIGIN: https://admin.test.sova.dev
|
||||
```
|
||||
|
||||
При внедрении **NoopSmsClientService** URL sms можно не резолвить.
|
||||
|
||||
---
|
||||
|
||||
## 6. CronJobs и внешние вызовы
|
||||
|
||||
| CronJob (из `scripts/cron.*`) | Внешние зависимости | Test |
|
||||
|-------------------------------|---------------------|------|
|
||||
| `upload:deps`, `upload:doctors` | MIS HTTP | mock MIS или отключить |
|
||||
| `upload:filials`, `upload:price*` | widget HTTP (hardcoded) | mock + рефакторинг URL |
|
||||
| `bitrix-update-reviews` | MySQL Bitrix | test MySQL + seed |
|
||||
| `bitrix-update-doctors` | только PG | OK |
|
||||
| `upload:news`, `upload:promo`, … | PG views → MySQL | test MySQL + views или CRUD only |
|
||||
| `ClearScheduleCacheCommand` | только PG | OK |
|
||||
|
||||
**Рекомендация для первого выката test:** включить CronJobs только для **очистки кеша расписания**; sync-команды — после готовности mock MIS и Bitrix MySQL.
|
||||
|
||||
**concurrencyPolicy в K8s:**
|
||||
|
||||
Для всех sync CronJobs обязательно:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
concurrencyPolicy: Forbid # не запускать вторую копию, пока первая не завершилась
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 3600
|
||||
```
|
||||
|
||||
Без `Forbid` при зависшей БД `bitrix-update-reviews` через час стартует дубликат — параллельные job'ы начнут мешать друг другу.
|
||||
|
||||
---
|
||||
|
||||
## 7. Stage vs Prod — отличия от test
|
||||
|
||||
| Сервис | Test | Stage | Prod |
|
||||
|--------|------|-------|------|
|
||||
| PostgreSQL / Redis / Bitrix MySQL | Изолированные test DB | Изолированные stage DB | Production DB |
|
||||
| MIS | Mock | Sandbox MIS **или** mock | Production MIS |
|
||||
| SMS | Noop | Noop или sandbox | Live |
|
||||
| Mail | Mailpit | Sandbox SMTP | Live |
|
||||
| SmartCaptcha | Mock | Mock | Live |
|
||||
| Calltouch | Noop | Noop | Live |
|
||||
| Bitrix HTTP (images) | Mock | Stage Bitrix site | Prod |
|
||||
|
||||
---
|
||||
|
||||
## 8. Технический долг (сделать до/во время миграции)
|
||||
|
||||
1. **Hardcoded `widget.sovamed.ru`** в `UploadFilialsCommand`, `UploadPriceCommand`, `UploadPriceDepCommand` → env `WIDGET_API_URL` или `MIS_URL`.
|
||||
2. **Hardcoded `https://api.sovamed.ru`** в `XmlFeedGenerator*` → env `API_PUBLIC_URL`.
|
||||
3. **Реализовать или явно отключить** SMS-клиенты (`NoopSmsClientService` + bind по env).
|
||||
4. **Calltouch** — раскомментировать с env-флагом `CALLTOUCH_ENABLED=false` в test.
|
||||
5. **BITRIX24_URL** — удалить из `.env` или документировать при появлении кода.
|
||||
6. **Mock-сервисы** — вынести JSON fixtures в репозиторий `sova-mocks` (рядом с `sova-deploy`).
|
||||
|
||||
---
|
||||
|
||||
## 9. Чек-лист готовности интеграций test-контура
|
||||
|
||||
- [ ] PostgreSQL test: миграции backend применены
|
||||
- [ ] MySQL Bitrix test: seed + (опционально) mysql_fdw views
|
||||
- [ ] Redis test: ping из backend pod
|
||||
- [ ] MIS mock: `GET /api/reservation/intervals` возвращает валидный JSON
|
||||
- [ ] MIS mock: `POST /api/reservation/anonymous-reserve` → 200
|
||||
- [ ] Captcha mock: `POST /validate` → ok
|
||||
- [ ] Mailpit: письмо из `/service/sendmail` видно в UI (Basic Auth или port-forward)
|
||||
- [ ] SMS: noop binding, приложение стартует без sms.ru
|
||||
- [ ] Calltouch: lead endpoint не бьёт prod
|
||||
- [ ] CORS: admin.test.sova.dev → api.test.sova.dev
|
||||
- [ ] JWT keys: login работает
|
||||
- [ ] CronJobs sync: `concurrencyPolicy: Forbid`
|
||||
- [ ] CronJobs: только безопасные включены на первом выкате
|
||||
|
||||
---
|
||||
|
||||
## 10. Связанные файлы в репозитории
|
||||
|
||||
| Путь | Содержимое |
|
||||
|------|------------|
|
||||
| `apps/backend/.env` | prod-like переменные (образец) |
|
||||
| `apps/backend/.env.local` | local mock URLs |
|
||||
| `apps/backend/config/services.yaml` | DI клиентов |
|
||||
| `apps/backend/config/packages/doctrine.yaml` | 3 DB connection |
|
||||
| `apps/backend/src/Service/Client/*` | HTTP-клиенты |
|
||||
| `apps/backend/src/Service/Bitrix/BitrixService.php` | MySQL Bitrix |
|
||||
| `local/mysql-bitrix/init/` | seed Bitrix tables |
|
||||
| `local/postgres/init/` | seed PG backend + cabinet |
|
||||
| `monitoring/prometheus/prometheus.yml` | scrape Bitrix server `192.168.2.11` (prod-only) |
|
||||
|
||||
---
|
||||
|
||||
*Версия 1.0. При изменении интеграций обновлять матрицу в §0 и env-фрагмент в §5.2.*
|
||||
@@ -0,0 +1,73 @@
|
||||
# Docker Compose
|
||||
|
||||
Compose-конфигурация разделена на несколько файлов в `environments`.
|
||||
|
||||
## Файлы
|
||||
|
||||
- `docker-compose.networks.yml` - `public-network` и `internal-network`.
|
||||
- `docker-compose.dbs.yml` - PostgreSQL и Redis.
|
||||
- `docker-compose.apps.yml` - nginx, `php84`, `php82`, `nextjs`.
|
||||
- `docker-compose.dev.yml` - Node.js helper-контейнер для разработки frontend-приложений.
|
||||
- `docker-compose.monitoring.yml` - node-exporter, php-fpm-exporter, Prometheus, Grafana.
|
||||
- `docker-compose.jenkins.yml` - Jenkins.
|
||||
|
||||
## Make targets
|
||||
|
||||
```bash
|
||||
make help
|
||||
```
|
||||
|
||||
Основные цели:
|
||||
|
||||
- `make dev` - dev-режим без мониторинга;
|
||||
- `make up` - prod-режим с мониторингом;
|
||||
- `make down` - остановка сервисов;
|
||||
- `make restart` - остановка и повторный запуск;
|
||||
- `make clean` - остановка и удаление volumes;
|
||||
- `make prune` - полная очистка Docker;
|
||||
- `make chown-up` - выставить владельцев для мониторинга и PostgreSQL data;
|
||||
- `make chown-1000` - вернуть владельца `1000:1000`;
|
||||
- `make fix-certs` - поправить права сертификатов nginx;
|
||||
- `make rebuild-nextjs` - пересобрать и перезапустить Next.js-контейнер.
|
||||
|
||||
## Ручной запуск compose
|
||||
|
||||
Эквивалент `make dev`:
|
||||
|
||||
```bash
|
||||
COMPOSE_PROJECT_ENV=dev COMPOSE_NODE_ENV=development \
|
||||
docker compose --env-file .env \
|
||||
-f environments/docker-compose.networks.yml \
|
||||
-f environments/docker-compose.dbs.yml \
|
||||
-f environments/docker-compose.apps.yml \
|
||||
-f environments/docker-compose.dev.yml \
|
||||
up -d
|
||||
```
|
||||
|
||||
Эквивалент `make up`:
|
||||
|
||||
```bash
|
||||
COMPOSE_PROJECT_ENV=prod COMPOSE_NODE_ENV=production \
|
||||
docker compose --env-file .env \
|
||||
-f environments/docker-compose.networks.yml \
|
||||
-f environments/docker-compose.dbs.yml \
|
||||
-f environments/docker-compose.apps.yml \
|
||||
-f environments/docker-compose.dev.yml \
|
||||
-f environments/docker-compose.monitoring.yml \
|
||||
up -d
|
||||
```
|
||||
|
||||
## Порты
|
||||
|
||||
- `80`, `443` - nginx.
|
||||
- `5432` - PostgreSQL.
|
||||
- `3001` - Next.js `sovamed`.
|
||||
- `3000` - Grafana.
|
||||
- `9090` - Prometheus.
|
||||
- `8080`, `50000` - Jenkins.
|
||||
|
||||
## Volumes и данные
|
||||
|
||||
PostgreSQL хранит данные в `infrastructure/pgsql/data`, Redis - в `infrastructure/redis/data`. Эти директории игнорируются git и не должны удаляться без необходимости.
|
||||
|
||||
`make clean` удаляет docker volumes, а `make prune` чистит Docker глобально на машине.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
# ArgoCD: sova-root, data-test и «почему нельзя войти»
|
||||
|
||||
В UI ArgoCD видны приложения разных типов. Не у всех есть URL в браузере или смысл открывать Terminal «как в backend».
|
||||
|
||||
## Сводная таблица
|
||||
|
||||
| Application | Что деплоит | Namespace | Есть URL? | Terminal |
|
||||
|-------------|-------------|-----------|-----------|----------|
|
||||
| **sova-root** | другие `Application` CR (app-of-apps) | `argocd` | нет | нет pod'ов |
|
||||
| **data-test** | PostgreSQL, MySQL, Redis (Helm Bitnami) | `sova-data-test` | нет | только в pod БД |
|
||||
| **backend-test** | Symfony API | `sova-test` | api.test.sova.local | php-fpm |
|
||||
| **adminpanel-test** | React admin | `sova-test` | admin.test.sova.local | nginx |
|
||||
| **cabinet-test** | Symfony ЛК | `sova-test` | cabinet.test.sova.local | php-fpm |
|
||||
| **docs-test** | документация (nginx) | `sova-test` | docs.sova.local | nginx |
|
||||
| **mocks-test** | WireMock, Mailpit | `sova-mocks` | internal only | по pod |
|
||||
|
||||
---
|
||||
|
||||
## sova-root — «корневое» GitOps-приложение
|
||||
|
||||
**Назначение:** паттерн *app-of-apps*. Один `Application` следит за каталогом `sova-deploy/argocd/apps/` и создаёт/обновляет остальные Application-манифесты (`backend-test`, `data-test`, …).
|
||||
|
||||
**Почему «нельзя войти»:**
|
||||
|
||||
- Это **мета-приложение**. Оно не разворачивает Deployment, Service или Ingress.
|
||||
- В дереве ресурсов — только объекты типа `Application` в namespace `argocd`.
|
||||
- Нет веб-интерфейса, логина пользователя или pod'а для exec.
|
||||
|
||||
**Как пользоваться:** смотрите дочерние приложения (`backend-test`, `docs-test`, …). `sova-root` нужен для автоматического подхвата новых Application при push в `sova-deploy`.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
root["sova-root Application"]
|
||||
apps["argocd/apps/*.yaml"]
|
||||
be["backend-test"]
|
||||
data["data-test"]
|
||||
docs["docs-test"]
|
||||
root --> apps
|
||||
apps --> be & data & docs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## data-test — инфраструктура данных
|
||||
|
||||
**Назначение:** Helm-чарт `sova-deploy/data/test` — PostgreSQL (backend + cabinet БД), MySQL Bitrix, Redis для test-контура.
|
||||
|
||||
**Почему «нельзя войти»:**
|
||||
|
||||
- Это **слой данных**, не пользовательское приложение.
|
||||
- Нет Ingress и публичного hostname.
|
||||
- «Войти» в ArgoCD UI можно только в смысле открыть карточку приложения — там StatefulSet/Deployment БД, а не сайт.
|
||||
|
||||
**Как подключаться:**
|
||||
|
||||
```bash
|
||||
# PostgreSQL из другого pod в кластере
|
||||
postgresql-test.sova-data-test.svc.cluster.local:5432
|
||||
|
||||
# Инициализация schema/seed — отдельный Job db-init (чарт data/db-init), не через браузер
|
||||
kubectl get jobs -n sova-data-test
|
||||
```
|
||||
|
||||
**Terminal:** технически можно `exec` в pod PostgreSQL/MySQL, но это для DBA/отладки, не «логин в приложение».
|
||||
|
||||
**Sync degraded:** если в чарте `data/test` был лишний шаблон `db-init` с несуществующими values (`postgres.*` вместо `postgresql.*`), Application падал в ошибку. Инициализация БД выполняется **отдельным** чартом `data/db-init` через `deploy-test-stack.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Куда идти вместо этого
|
||||
|
||||
| Задача | Куда |
|
||||
|--------|------|
|
||||
| API, миграции, cron | **backend-test** → Pod → container **php-fpm** → Terminal |
|
||||
| Админка | **adminpanel-test** → http://admin.test.sova.local |
|
||||
| Личный кабинет | **cabinet-test** → http://cabinet.test.sova.local |
|
||||
| Документация | **docs-test** → http://docs.sova.local |
|
||||
| Git, CI | http://git.sova.local |
|
||||
| Метрики/логи | http://grafana.sova.local |
|
||||
|
||||
Exec в ArgoCD включён в `platform/argocd/values-test.yaml` (`exec.enabled: true`).
|
||||
@@ -0,0 +1,13 @@
|
||||
# Test-контур k3s
|
||||
|
||||
Документация по песочнице `k3s-test/`: локальное развёртывание на Multipass/k3s, CI/CD через Gitea, GitOps через ArgoCD.
|
||||
|
||||
**Живой сайт в test-контуре:** http://docs.sova.local
|
||||
|
||||
## Разделы
|
||||
|
||||
- [Test-контур: что сделано и перенос на сервер](./test-contour-article) — полная статья
|
||||
- [Система тегов CI/CD](./tags) — формат тегов и release-скрипт
|
||||
- [ArgoCD: sova-root и data-test](./argocd-apps) — зачем эти приложения и почему «нельзя войти»
|
||||
|
||||
Исходники: репозиторий `sova/docs` в Gitea, локально — `k3s-test/sova-docs/`.
|
||||
@@ -0,0 +1,90 @@
|
||||
# Система тегов CI/CD
|
||||
|
||||
Каждое приложение в Gitea публикуется **отдельным репозиторием** и выпускается **своим тегом**. Тег запускает Gitea Actions: сборка Docker-образа → push в registry → обновление `values-{env}.yaml` в `sova-deploy`.
|
||||
|
||||
## Формат тега
|
||||
|
||||
```
|
||||
{component}-v{semver}-{env}
|
||||
```
|
||||
|
||||
| Часть | Пример | Описание |
|
||||
|-------|--------|----------|
|
||||
| `component` | `backend`, `adminpanel`, `cabinet`, `docs` | имя сервиса |
|
||||
| `semver` | `1.0.1` | версия образа |
|
||||
| `env` | `test`, `stage` | контур (подставляется в `values-{env}.yaml`) |
|
||||
|
||||
Примеры для test-контура:
|
||||
|
||||
| Репозиторий Gitea | Тег | Helm values |
|
||||
|-------------------|-----|-------------|
|
||||
| `sova/backend` | `backend-v1.0.1-test` | `apps/backend/values-test.yaml` |
|
||||
| `sova/adminpanel` | `adminpanel-v1.0.1-test` | `apps/adminpanel/values-test.yaml` |
|
||||
| `sova/cabinet` | `cabinet-v1.0.1-test` | `apps/cabinet/values-test.yaml` |
|
||||
| `sova/docs` | `docs-v1.0.1-test` | `apps/docs/values-test.yaml` |
|
||||
|
||||
`sova-deploy` и `sova-mocks` **не** собираются по тегам — их меняют вручную или через bootstrap; ArgoCD подхватывает `main`.
|
||||
|
||||
## Release-скрипт
|
||||
|
||||
```bash
|
||||
./scripts/release-test-tag.sh backend backend-v1.0.1-test
|
||||
./scripts/release-test-tag.sh adminpanel adminpanel-v1.0.1-test
|
||||
./scripts/release-test-tag.sh cabinet cabinet-v1.0.1-test
|
||||
./scripts/release-test-tag.sh docs docs-v1.0.1-test
|
||||
```
|
||||
|
||||
Скрипт создаёт аннотированный тег в локальном зеркале репозитория и пушит в Gitea. Workflow парсит суффикс `-test` и обновляет соответствующий `values-test.yaml`.
|
||||
|
||||
## Pipeline (общая схема)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
tag["git tag push"] --> test["job: test"]
|
||||
test --> build["build-and-push"]
|
||||
build --> registry["Gitea registry"]
|
||||
build --> deploy["deploy-gitops"]
|
||||
deploy --> deployRepo["sova-deploy main"]
|
||||
deployRepo --> argocd["ArgoCD sync"]
|
||||
argocd --> k8s["Pod rollout"]
|
||||
```
|
||||
|
||||
## Секреты Actions (на репозиторий)
|
||||
|
||||
Настраиваются `./scripts/bootstrap-gitea-ci-secrets.sh`:
|
||||
|
||||
| Secret | Назначение |
|
||||
|--------|------------|
|
||||
| `REGISTRY_USER` / `REGISTRY_PASSWORD` | push образа в Gitea registry |
|
||||
| `DEPLOY_TOKEN` | HTTPS push в `sova/sova-deploy` |
|
||||
| `HOST_IP` | резерв для jobs с внешним доступом |
|
||||
|
||||
Перед первым CI после bootstrap:
|
||||
|
||||
```bash
|
||||
./scripts/configure-k3s-registry.sh
|
||||
./scripts/bootstrap-gitea-ci-secrets.sh
|
||||
```
|
||||
|
||||
## Локальная сборка (без CI)
|
||||
|
||||
```bash
|
||||
./scripts/build-images.sh local-test # backend, adminpanel, cabinet, docs
|
||||
./scripts/import-images-to-vm.sh local-test
|
||||
```
|
||||
|
||||
Образы с тегом `local-test` и `pullPolicy: Never`/`IfNotPresent` — для первого деплоя до настройки registry.
|
||||
|
||||
## Проверка
|
||||
|
||||
```bash
|
||||
# Workflow
|
||||
open http://git.sova.local/sova/backend/actions
|
||||
|
||||
# Образ в registry
|
||||
curl -u gitea_admin:PASSWORD http://git.sova.local/v2/sova/backend/tags/list
|
||||
|
||||
# ArgoCD
|
||||
kubectl get applications -n argocd
|
||||
kubectl get deploy -n sova-test
|
||||
```
|
||||
@@ -0,0 +1,634 @@
|
||||
# Test-контур Sova на k3s: что сделано и как перенести на удалённый сервер
|
||||
|
||||
Статья описывает изолированный test-контур в каталоге `k3s-test/`: архитектуру, порядок локального развёртывания и план переноса на реальный сервер.
|
||||
|
||||
---
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
Монорепозиторий Sova (`apps/backend`, `apps/cabinet`, `local/` и т.д.) не трогали. Вместо этого собран **отдельный контур** — песочница, где можно:
|
||||
|
||||
- поднять backend, admin panel, БД и моки в Kubernetes;
|
||||
- проверить GitOps (ArgoCD), CI (Gitea Actions), мониторинг (Prometheus/Grafana);
|
||||
- накатывать **изолированные test-БД** (не `*_local`, а `*_test`) из тех же SQL, что и в `local/`;
|
||||
- отрабатывать сценарии до выкладки на stage/production.
|
||||
|
||||
Домены локально: `*.sova.local`. На удалённом сервере их заменят на реальные, например `*.test.sova.dev`.
|
||||
|
||||
---
|
||||
|
||||
## Архитектура
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph dev["Mac (разработчик)"]
|
||||
docker["Docker build"]
|
||||
helm["Helm / kubectl"]
|
||||
scripts["scripts/*.sh"]
|
||||
end
|
||||
|
||||
subgraph vm["VM sova-test (Multipass) / удалённый сервер"]
|
||||
k3s["k3s single-node"]
|
||||
ingress["ingress-nginx"]
|
||||
end
|
||||
|
||||
subgraph platform["Platform layer"]
|
||||
argocd["ArgoCD"]
|
||||
gitea["Gitea + Actions"]
|
||||
prom["Prometheus"]
|
||||
graf["Grafana"]
|
||||
end
|
||||
|
||||
subgraph apps["Application layer"]
|
||||
be["backend nginx+php-fpm"]
|
||||
ap["adminpanel nginx"]
|
||||
mocks["WireMock + Mailpit"]
|
||||
end
|
||||
|
||||
subgraph data["Data layer (sova-data-test)"]
|
||||
pg["PostgreSQL Bitnami"]
|
||||
mysql["MySQL 8.0"]
|
||||
redis["Redis"]
|
||||
dbinit["Job db-init: schema → seed"]
|
||||
end
|
||||
|
||||
scripts --> helm
|
||||
docker --> k3s
|
||||
helm --> k3s
|
||||
k3s --> ingress
|
||||
ingress --> be & ap & argocd & gitea & graf & prom
|
||||
argocd --> apps & data
|
||||
gitea --> argocd
|
||||
dbinit --> pg & mysql
|
||||
be --> pg & redis & mysql
|
||||
be --> mocks
|
||||
```
|
||||
|
||||
### Структура репозитория `k3s-test/`
|
||||
|
||||
| Каталог | Назначение |
|
||||
|---------|------------|
|
||||
| `sova-backend/` | Копия Symfony API + Dockerfile + workflow Gitea |
|
||||
| `sova-adminpanel/` | Копия React admin + runtime `env.js` |
|
||||
| `sova-cabinet/` | Копия Symfony ЛК + Dockerfile + workflow Gitea |
|
||||
| `sova-docs/` | VitePress-документация (из `docs/` монорепо) + Dockerfile + workflow Gitea |
|
||||
| `sova-deploy/` | Helm charts, ArgoCD manifests, SQL для test-БД |
|
||||
| `sova-mocks/` | WireMock (MIS, Calltouch, Captcha) + Mailpit |
|
||||
| `sova-platform/` | Terraform-модуль установки k3s на VM |
|
||||
| `scripts/` | Bootstrap, сборка образов, деплой, smoke |
|
||||
|
||||
---
|
||||
|
||||
## Что сделано в коде
|
||||
|
||||
### Backend (`sova-backend`)
|
||||
|
||||
- Вынесены URL интеграций в env: `WIDGET_API_URL`, `API_PUBLIC_URL`.
|
||||
- Stub-режим внешних сервисов: SMS, Calltouch, SmartCaptcha (`INTEGRATIONS_STUB_MODE=true`).
|
||||
- Production Dockerfile: PHP 8.4-FPM, multistage.
|
||||
- JWT-ключи монтируются из Helm Secret (`sova-deploy/apps/backend/jwt/`).
|
||||
|
||||
### Admin Panel (`sova-adminpanel`)
|
||||
|
||||
- Runtime-конфиг `public/env.js` (API URL без пересборки).
|
||||
- Dockerfile: Node build → nginx.
|
||||
- ConfigMap + entrypoint для подстановки URL в k8s.
|
||||
|
||||
### Базы данных
|
||||
|
||||
SQL из монорепо (`local/postgres/init/`, `local/mysql-bitrix/init/`) **разделён на два этапа**:
|
||||
|
||||
1. **Schema** — `sova-deploy/data/test/sql/*/schema/`
|
||||
2. **Seed** — `sova-deploy/data/test/sql/*/seed/`
|
||||
|
||||
Скрипт `scripts/prepare-db-init.py`:
|
||||
|
||||
- переименовывает `*_local` → `*_test`;
|
||||
- добавляет `\connect` в seed-файлы;
|
||||
- заменяет `md5('...')` на литералы (PostgreSQL 18 не поддерживает `md5()` в INSERT).
|
||||
|
||||
Job `db-init` (Helm chart `sova-deploy/data/db-init/`) выполняет: schema PostgreSQL → schema MySQL → seed PostgreSQL → seed MySQL.
|
||||
|
||||
| База | Имя | Назначение |
|
||||
|------|-----|------------|
|
||||
| PostgreSQL | `sova_backend_test` | Backend API, admin auth |
|
||||
| PostgreSQL | `sova_cabinet_test` | Личный кабинет (если подключается) |
|
||||
| MySQL | `sova_bitrix_test` | Views/синк Bitrix |
|
||||
| Redis | — | Кэш, messenger |
|
||||
|
||||
MySQL поднят через простой manifest `mysql:8.0` (Bitnami chart давал ImagePullBackOff). Auth plugin: `mysql_native_password` для совместимости с клиентом в init Job.
|
||||
|
||||
### GitOps (`sova-deploy`)
|
||||
|
||||
- Helm: `apps/backend`, `apps/adminpanel`, `data/db-init`, `data/test`.
|
||||
- ArgoCD Applications: backend, adminpanel, mocks, data-test.
|
||||
- Репозитории в Gitea: `sova/backend`, `sova/adminpanel`, `sova/sova-deploy`, `sova/sova-mocks`.
|
||||
|
||||
#### Backend: stateless console в ArgoCD
|
||||
|
||||
Помимо Deployment (nginx + php-fpm), chart `apps/backend` создаёт **CronJob-ы с контейнером `console`** — Symfony-команды по расписанию. В ArgoCD они видны в дереве приложения `backend-test` как отдельные ресурсы с label `app.kubernetes.io/component: console`:
|
||||
|
||||
| CronJob | Расписание (MSK) | Команда |
|
||||
|---------|------------------|---------|
|
||||
| `backend-clear-schedule-cache` | `0 */6 * * *` | `app:schedule:clear-cache` |
|
||||
| `backend-sync-doctors` | `0 3 * * *` | `upload:doctors` |
|
||||
| `backend-sync-reviews` | `30 3 * * *` | `bitrix-update-reviews` |
|
||||
|
||||
Конфигурация — список `cronjobs` в `values.yaml`. Для test-контура Job миграций (`backend-migrate`) **отключён** (`migrate.enabled: false`), т.к. схема накатывается через `db-init`, а не `doctrine:migrations:migrate`. На stage/prod можно включить PreSync-migrate.
|
||||
|
||||
Deployment использует initContainer `warmup-cache` и `emptyDir` для `/app/var/cache` и `/app/var/log` — иначе Symfony не может писать кэш в prod (HTTP 500).
|
||||
|
||||
### Platform layer
|
||||
|
||||
| Компонент | Namespace | Ingress |
|
||||
|-----------|-----------|---------|
|
||||
| ingress-nginx | `ingress` | LoadBalancer на IP VM |
|
||||
| cert-manager | `cert-manager` | — |
|
||||
| sealed-secrets | `kube-system` | — |
|
||||
| ArgoCD | `argocd` | `argocd.sova.local` |
|
||||
| Gitea | `gitea` | `git.sova.local` |
|
||||
| kube-prometheus-stack | `monitoring` | `grafana.sova.local`, `prometheus.sova.local` |
|
||||
| Loki + Promtail | `monitoring` | только внутри кластера (логи в Grafana) |
|
||||
|
||||
**Метрики vs логи:** Prometheus собирает **метрики** (CPU, память, kube-state). **Логи подов** — через **Loki + Promtail** (Explore → Loki в Grafana). Без Loki в Grafana «логов нет» — это ожидаемо до `./scripts/deploy-monitoring-logs.sh`.
|
||||
|
||||
```bash
|
||||
# После deploy-platform или отдельно:
|
||||
./scripts/deploy-monitoring-logs.sh
|
||||
|
||||
# В Grafana Explore:
|
||||
# datasource: Loki
|
||||
# query: {namespace="sova-test", app="backend"}
|
||||
```
|
||||
|
||||
**Важно для ArgoCD:** UI работает по HTTP только при:
|
||||
|
||||
- `server.insecure=true` в `argocd-cmd-params-cm` (ключ `server.insecure`, не вложенный YAML);
|
||||
- `url: http://argocd.sova.local` в `argocd-cm`;
|
||||
- ingress без принудительного HTTPS.
|
||||
|
||||
**Терминал в pod (exec):** по умолчанию в Argo CD выключен. В test-контуре включён через `sova-deploy/platform/argocd/values-test.yaml` (`exec.enabled: true` + RBAC). В UI: Application → backend-test → Pod → **⋮** → **Terminal** → контейнер **`php-fpm`**.
|
||||
|
||||
Пример миграций из терминала ArgoCD или kubectl:
|
||||
|
||||
```bash
|
||||
php bin/console doctrine:migrations:migrate --no-interaction
|
||||
php bin/console doctrine:migrations:status
|
||||
```
|
||||
|
||||
Через kubectl (если UI недоступен):
|
||||
|
||||
```bash
|
||||
kubectl exec -n sova-test deploy/backend -c php-fpm -it -- sh
|
||||
# внутри pod:
|
||||
php bin/console doctrine:migrations:migrate --no-interaction
|
||||
```
|
||||
|
||||
ArgoCD внутри кластера ходит в Gitea по **внутреннему URL**:
|
||||
`http://gitea-http.gitea.svc.cluster.local:3000/sova/...`
|
||||
(снаружи браузер использует `http://git.sova.local`).
|
||||
|
||||
---
|
||||
|
||||
## Локальное развёртывание (Multipass)
|
||||
|
||||
Требования: Docker, Multipass, Helm ≥ 3.14, kubectl, Terraform (опционально).
|
||||
|
||||
### Полный цикл
|
||||
|
||||
```bash
|
||||
cd k3s-test
|
||||
|
||||
# 1. Синхронизация кода из монорепо (если нужно обновить)
|
||||
./scripts/sync-from-monorepo.sh
|
||||
|
||||
# 2. VM + k3s (4 CPU, 8 GB RAM, 40 GB disk)
|
||||
./scripts/bootstrap-multipass.sh local-test
|
||||
|
||||
# 3. Platform: ingress, ArgoCD, Gitea, Prometheus/Grafana
|
||||
./scripts/deploy-platform.sh
|
||||
|
||||
# 4. Приложения, БД, моки
|
||||
USE_MULTIPASS=1 ./scripts/deploy-test-stack.sh local-test
|
||||
|
||||
# 5. Репозитории в Gitea + CI user
|
||||
./scripts/bootstrap-gitea.sh
|
||||
|
||||
# 6. Gitea Actions runner
|
||||
./scripts/bootstrap-gitea-runner.sh
|
||||
|
||||
# 7. ArgoCD applications + HTTP UI
|
||||
./scripts/bootstrap-argocd.sh
|
||||
|
||||
# 8. Логины и URL
|
||||
./scripts/print-test-users.sh
|
||||
./scripts/print-urls.sh
|
||||
```
|
||||
|
||||
### /etc/hosts на Mac
|
||||
|
||||
Подставьте IP из `multipass info sova-test`:
|
||||
|
||||
```
|
||||
192.168.x.x api.test.sova.local admin.test.sova.local
|
||||
192.168.x.x argocd.sova.local git.sova.local grafana.sova.local prometheus.sova.local
|
||||
```
|
||||
|
||||
Kubeconfig: `~/.kube/sova-test-config`.
|
||||
|
||||
### Альтернатива без Multipass (k3d)
|
||||
|
||||
Для быстрой проверки на Mac без VM:
|
||||
|
||||
```bash
|
||||
./scripts/k3d-bootstrap.sh local-test
|
||||
echo "127.0.0.1 api.test.sova.local admin.test.sova.local" | sudo tee -a /etc/hosts
|
||||
./scripts/smoke-test.sh
|
||||
```
|
||||
|
||||
Platform layer (Gitea, ArgoCD) в k3d-варианте поднимается по необходимости через `deploy-platform.sh`.
|
||||
|
||||
---
|
||||
|
||||
## URL и тестовые пользователи
|
||||
|
||||
| Сервис | URL |
|
||||
|--------|-----|
|
||||
| Backend API | http://api.test.sova.local |
|
||||
| Admin Panel | http://admin.test.sova.local |
|
||||
| Gitea | http://git.sova.local/sova/ |
|
||||
| ArgoCD | http://argocd.sova.local |
|
||||
| Grafana | http://grafana.sova.local |
|
||||
| Prometheus | http://prometheus.sova.local |
|
||||
|
||||
### Пользователи приложения (seed в БД)
|
||||
|
||||
| Сценарий | Логин | Пароль |
|
||||
|----------|-------|--------|
|
||||
| Admin Panel + Backend JWT | `local.backend@example.test` | `local-password` |
|
||||
| Cabinet (отдельная БД) | `local.cabinet@example.test` | `local-password` |
|
||||
| Auth по pcode | uid `100001`, birthDate `19900101` | — |
|
||||
|
||||
Проверка логина:
|
||||
|
||||
```bash
|
||||
curl -X POST http://api.test.sova.local/user/login \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username":"local.backend@example.test","password":"local-password"}'
|
||||
```
|
||||
|
||||
### Platform credentials
|
||||
|
||||
После `bootstrap-gitea.sh` — файл `.generated/platform-credentials.env`:
|
||||
|
||||
- Gitea admin: `gitea_admin`
|
||||
- CI user: `sova-ci`
|
||||
- ArgoCD: `admin` + пароль из `argocd-initial-admin-secret`
|
||||
|
||||
Актуальные значения: `./scripts/print-test-users.sh`.
|
||||
|
||||
---
|
||||
|
||||
## CI/CD (Gitea Actions)
|
||||
|
||||
В репозиториях лежат workflow:
|
||||
|
||||
- `sova-backend/.gitea/workflows/build.yml`
|
||||
- `sova-adminpanel/.gitea/workflows/build.yml`
|
||||
|
||||
Цепочка по тегу `backend-v1.0.1-test` / `adminpanel-v1.0.1-test`:
|
||||
|
||||
1. **test** — composer / npm, lint, build
|
||||
2. **build-and-push** — Docker-образ в Gitea Container Registry
|
||||
3. **deploy-gitops** — commit в `sova/sova-deploy` (repository, tag, pullPolicy)
|
||||
|
||||
### Registry и секреты CI
|
||||
|
||||
| Секрет | Назначение |
|
||||
|--------|------------|
|
||||
| `REGISTRY_USER` / `REGISTRY_PASSWORD` | Push образов (`gitea_admin` — у `sova-ci` нет прав на packages) |
|
||||
| `DEPLOY_TOKEN` | HTTPS push в `sova-deploy` |
|
||||
| `HOST_IP` | IP VM для `/etc/hosts` (имена с префиксом `GITEA_` Gitea не принимает) |
|
||||
|
||||
Push из runner идёт на **внутренний URL** `gitea-http.gitea.svc.cluster.local:3000` (DinD не резолвит `git.sova.local`). В `values-test.yaml` для pull на ноде k3s используется **`git.sova.local/sova/backend`** — после `./scripts/configure-k3s-registry.sh`.
|
||||
|
||||
```bash
|
||||
./scripts/bootstrap-gitea-ci-secrets.sh # секреты в Gitea Actions
|
||||
./scripts/configure-k3s-registry.sh # k3s registries.yaml + pull secret
|
||||
./scripts/release-test-tag.sh backend backend-v1.0.1-test
|
||||
```
|
||||
|
||||
### Runner (Gitea Actions)
|
||||
|
||||
Развёрнут через официальный chart `gitea-charts/actions` + DinD (Docker-in-Docker):
|
||||
|
||||
```bash
|
||||
./scripts/bootstrap-gitea-runner.sh
|
||||
```
|
||||
|
||||
Конфиг: `sova-deploy/platform/gitea-actions/values-test.yaml`
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Release | `gitea-actions` |
|
||||
| Namespace | `gitea` |
|
||||
| Имя runner | `sova-test-k8s` |
|
||||
| Labels | `ubuntu-latest`, `ubuntu-22.04` |
|
||||
| Gitea URL (внутри кластера) | `http://gitea-http.gitea.svc.cluster.local:3000` |
|
||||
|
||||
Проверка: http://git.sova.local/admin/actions/runners — должен быть **Online**.
|
||||
|
||||
Логи: `kubectl logs -n gitea -l app.kubernetes.io/name=actions-runner -c runner -f`
|
||||
|
||||
Workflow запускается по push тега. Job `test` не требует registry; `build-and-push` — нужен Container Registry (`packages.ENABLED=true` в Gitea).
|
||||
|
||||
---
|
||||
|
||||
## Проверка штатного режима (чеклист)
|
||||
|
||||
После полного bootstrap или CI-релиза:
|
||||
|
||||
```bash
|
||||
export KUBECONFIG=~/.kube/sova-test-config
|
||||
|
||||
# 1. Поды
|
||||
kubectl get pods -n sova-test
|
||||
kubectl get cronjobs -n sova-test # backend-sync-doctors, backend-sync-reviews, ...
|
||||
|
||||
# 2. ArgoCD
|
||||
kubectl get applications -n argocd
|
||||
# UI: http://argocd.sova.local → backend-test → дерево с CronJob
|
||||
|
||||
# 3. API
|
||||
curl -s -o /dev/null -w "%{http_code}\n" -H "Host: api.test.sova.local" \
|
||||
"http://$(multipass info sova-test | awk '/IPv4/{print $2; exit}')/news/list?page=1"
|
||||
# Ожидается: 200
|
||||
|
||||
curl -X POST http://api.test.sova.local/user/login \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username":"local.backend@example.test","password":"local-password"}'
|
||||
|
||||
# 4. CI (если настроен runner)
|
||||
# http://git.sova.local/sova/backend/actions — последний run: success
|
||||
|
||||
# 5. Логи в Grafana (не Prometheus!)
|
||||
# http://grafana.sova.local → Explore → Loki → {namespace="sova-test"}
|
||||
|
||||
# 6. Admin panel
|
||||
curl -s -o /dev/null -w "%{http_code}\n" -H "Host: admin.test.sova.local" \
|
||||
"http://$(multipass info sova-test | awk '/IPv4/{print $2; exit}')/"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Перенос на удалённый сервер
|
||||
|
||||
Ниже — пошаговый план миграции с Multipass на bare metal / VPS / облако.
|
||||
|
||||
### 1. Требования к серверу
|
||||
|
||||
| Ресурс | Минимум (test) | Рекомендуется |
|
||||
|--------|----------------|---------------|
|
||||
| CPU | 4 vCPU | 8 vCPU |
|
||||
| RAM | 8 GB | 16 GB |
|
||||
| Disk | 40 GB SSD | 80+ GB SSD |
|
||||
| ОС | Ubuntu 22.04 LTS | Ubuntu 22.04 / 24.04 |
|
||||
| Сеть | Публичный IP или VPN | + DNS на ваш домен |
|
||||
|
||||
Открытые порты: **80**, **443** (ingress), опционально **22** (SSH).
|
||||
|
||||
### 2. Подготовка сервера
|
||||
|
||||
```bash
|
||||
# На сервере (Ubuntu)
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install -y curl git
|
||||
|
||||
# Установка k3s (аналог install-k3s-multipass.sh, но на bare metal)
|
||||
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable traefik" sh -
|
||||
|
||||
# Kubeconfig на вашу машину
|
||||
scp user@SERVER:/etc/rancher/k3s/k3s.yaml ~/.kube/sova-remote-config
|
||||
# Заменить 127.0.0.1 на IP сервера в server:
|
||||
export KUBECONFIG=~/.kube/sova-remote-config
|
||||
```
|
||||
|
||||
Terraform-модуль `sova-platform/terraform/modules/k3s-single-node` можно использовать и для удалённого сервера: задать `server_ip`, `ssh_user`, `ssh_private_key_path` в `terraform.tfvars`.
|
||||
|
||||
### 3. DNS вместо /etc/hosts
|
||||
|
||||
Замените `*.sova.local` на реальный домен, например:
|
||||
|
||||
| Было (local) | Станет (remote test) |
|
||||
|--------------|----------------------|
|
||||
| `api.test.sova.local` | `api.test.sova.dev` |
|
||||
| `admin.test.sova.local` | `admin.test.sova.dev` |
|
||||
| `git.sova.local` | `git.test.sova.dev` |
|
||||
| `argocd.sova.local` | `argocd.test.sova.dev` |
|
||||
| `grafana.sova.local` | `grafana.test.sova.dev` |
|
||||
|
||||
A-записи всех имён → **публичный IP сервера**.
|
||||
|
||||
Файлы для правки:
|
||||
|
||||
- `sova-deploy/apps/backend/values-test.yaml` — ingress host, `API_PUBLIC_URL`, CORS
|
||||
- `sova-deploy/apps/adminpanel/values-test.yaml` — ingress, env.js API URL
|
||||
- `scripts/deploy-platform.sh` — Gitea `DOMAIN`, `ROOT_URL`
|
||||
- `scripts/deploy-platform-ingress.sh` — host rules
|
||||
- `sova-adminpanel/public/env.js` (или ConfigMap) — `API_BASE_URL`
|
||||
|
||||
### 4. TLS (рекомендуется на сервере)
|
||||
|
||||
1. cert-manager уже ставится через `deploy-platform.sh`.
|
||||
2. Создайте ClusterIssuer Let's Encrypt (HTTP-01 или DNS-01).
|
||||
3. В Ingress добавьте `tls:` секции и annotation `cert-manager.io/cluster-issuer`.
|
||||
4. Для ArgoCD при TLS на ingress: оставьте `server.insecure=true` **или** настройте TLS passthrough — см. [документацию ArgoCD](https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/).
|
||||
|
||||
### 5. Образы: с локального import на registry
|
||||
|
||||
**Сейчас (Multipass):** образы собираются на Mac, импортируются через `multipass transfer` + `k3s ctr images import`, `image.pullPolicy: Never`.
|
||||
|
||||
**На сервере:**
|
||||
|
||||
```bash
|
||||
# Вариант A: registry в Gitea
|
||||
# После bootstrap-gitea — включить Container Registry в Gitea,
|
||||
# push: git.test.sova.dev/sova/backend:backend-v1.0.0-test
|
||||
|
||||
# Вариант B: внешний registry (GitHub CR, GitLab, Yandex CR)
|
||||
docker build -t registry.example.com/sova/backend:1.0.0-test ./sova-backend
|
||||
docker push registry.example.com/sova/backend:1.0.0-test
|
||||
```
|
||||
|
||||
В `values-test.yaml`:
|
||||
|
||||
```yaml
|
||||
image:
|
||||
repository: git.test.sova.dev/sova/backend # или ваш registry
|
||||
tag: backend-v1.0.0-test
|
||||
pullPolicy: IfNotPresent
|
||||
```
|
||||
|
||||
Добавьте `imagePullSecrets` если registry приватный.
|
||||
|
||||
### 6. Секреты
|
||||
|
||||
**Сейчас:** plain Secrets в Helm values (`sova-deploy/apps/backend/values.yaml`).
|
||||
|
||||
**На сервере:**
|
||||
|
||||
1. [Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) — уже ставится в platform layer.
|
||||
2. Зашифруйте секреты локально, commit sealed-манifests в `sova-deploy`.
|
||||
3. Уберите пароли из plain `values.yaml`.
|
||||
|
||||
Обязательно смените:
|
||||
|
||||
- `APP_SECRET`, пароли БД, `JWT` keys (новая пара для test/stage/prod)
|
||||
- Gitea admin password
|
||||
- Grafana admin password
|
||||
|
||||
### 7. Базы данных
|
||||
|
||||
Test-контур использует in-cluster PostgreSQL/Redis/MySQL. Для удалённого test это допустимо; для stage/prod рассмотрите:
|
||||
|
||||
- managed PostgreSQL (Yandex Cloud, RDS, etc.);
|
||||
- отдельный MySQL для Bitrix views;
|
||||
- backup PVC или external storage class.
|
||||
|
||||
Порядок инициализации **тот же**:
|
||||
|
||||
```bash
|
||||
./scripts/prepare-db-init.sh
|
||||
helm upgrade --install db-init ./sova-deploy/data/db-init -n sova-data-test
|
||||
```
|
||||
|
||||
При смене PostgreSQL major version перегенерируйте SQL (`prepare-db-init.py` уже учитывает отличия PG 18).
|
||||
|
||||
### 8. Деплой на сервер — чеклист
|
||||
|
||||
```bash
|
||||
# С вашей машины (KUBECONFIG → удалённый кластер)
|
||||
export KUBECONFIG=~/.kube/sova-remote-config
|
||||
|
||||
# 1. Platform
|
||||
BOOTSTRAP_PLATFORM=1 ./scripts/deploy-platform.sh
|
||||
|
||||
# 2. Обновить values-test.yaml под новый домен (см. п.3)
|
||||
# 3. Apps + data
|
||||
./scripts/deploy-test-stack.sh test # или ваш tag
|
||||
|
||||
# 4. Gitea repos (push с CI-машины или с сервера)
|
||||
GITEA_HOST=git.test.sova.dev ./scripts/bootstrap-gitea.sh
|
||||
|
||||
# 5. ArgoCD
|
||||
GITEA_REPO_URL=http://gitea-http.gitea.svc.cluster.local:3000 \
|
||||
./scripts/bootstrap-argocd.sh
|
||||
|
||||
# 6. Gitea Actions runner
|
||||
./scripts/bootstrap-gitea-runner.sh
|
||||
|
||||
# 7. Smoke
|
||||
curl https://api.test.sova.dev/news/list?page=1
|
||||
./scripts/print-test-users.sh
|
||||
```
|
||||
|
||||
### 9. GitOps как единственный источник правды
|
||||
|
||||
После первичного bootstrap:
|
||||
|
||||
1. Все изменения infra/apps — через commit в `sova/sova-deploy`.
|
||||
2. ArgoCD sync автоматически (у Applications включён `automated.selfHeal`).
|
||||
3. CI по тегу обновляет `values-test.yaml` → ArgoCD выкатывает новый образ.
|
||||
|
||||
### 10. Мониторинг, логи и алерты
|
||||
|
||||
- **Prometheus** — метрики k8s и приложений: http://prometheus.sova.local
|
||||
- **Grafana** — дашборды + **логи через Loki**: http://grafana.sova.local
|
||||
- Установка логов: `./scripts/deploy-monitoring-logs.sh` (Loki + Promtail + datasource)
|
||||
- На сервере: смените пароль Grafana, TLS на Ingress
|
||||
|
||||
### 11. Registry на сервере
|
||||
|
||||
```bash
|
||||
./scripts/configure-k3s-registry.sh # HTTP mirror git.sova.local + imagePullSecret
|
||||
./scripts/bootstrap-gitea-ci-secrets.sh
|
||||
```
|
||||
|
||||
В `values-test.yaml` после CI:
|
||||
|
||||
```yaml
|
||||
image:
|
||||
repository: git.test.sova.dev/sova/backend
|
||||
tag: backend-v1.0.1-test
|
||||
pullPolicy: IfNotPresent
|
||||
imagePullSecrets:
|
||||
- name: gitea-registry
|
||||
```
|
||||
|
||||
### 12. Отличия local vs remote (сводка)
|
||||
|
||||
| Аспект | Multipass (сейчас) | Удалённый сервер |
|
||||
|--------|-------------------|------------------|
|
||||
| Домен | `*.sova.local` + /etc/hosts | Реальный DNS |
|
||||
| TLS | HTTP | Let's Encrypt / свой сертификат |
|
||||
| Образы | local import, `pullPolicy: Never` | Gitea/registry, `IfNotPresent` |
|
||||
| Секреты | plain values | SealedSecrets / External Secrets |
|
||||
| k3s | VM Multipass | bare metal / VPS / Terraform |
|
||||
| Gitea URL для ArgoCD | internal service URL | тот же паттерн (internal) |
|
||||
| CI runner | `gitea-actions` StatefulSet (DinD) | масштабировать replicas / отдельная VM |
|
||||
| State Terraform | local | S3 + DynamoDB / GitLab state |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Симптом | Причина | Решение |
|
||||
|---------|---------|---------|
|
||||
| ArgoCD редирект на HTTPS | неверный `server.insecure` | `bootstrap-argocd.sh`, patch `argocd-cmd-params-cm` |
|
||||
| Gitea 503 | неверный service в Ingress | `gitea-http:3000` в `deploy-platform-ingress.sh` |
|
||||
| `/user/login` 500 | нет JWT keys | Helm chart `backend-jwt` secret, remount |
|
||||
| `/news/list` 500 | Symfony cache not writable | initContainer `warmup-cache`, emptyDir `/app/var/cache` |
|
||||
| ImagePullBackOff после CI | k3s не резолвит `.svc.cluster.local` | `repository: git.sova.local/...` + `configure-k3s-registry.sh` |
|
||||
| Grafana без логов | Loki не установлен | `./scripts/deploy-monitoring-logs.sh`, Explore → Loki |
|
||||
| ArgoCD нет кнопки Terminal в pod | `exec.enabled: false` | `./scripts/bootstrap-argocd.sh` или values `platform/argocd/values-test.yaml` |
|
||||
| db-init Failed | MySQL TLS / auth plugin | `--skip-ssl`, `mysql_native_password` |
|
||||
| db-init Failed на seed | нет `\connect` / md5() | перезапустить `prepare-db-init.sh` |
|
||||
| ArgoCD Unknown sync | Gitea по внешнему DNS из pod | internal URL `gitea-http.gitea.svc.cluster.local:3000` |
|
||||
| Bitnami chart 403 | закрытый HTTP repo | OCI: `oci://registry-1.docker.io/bitnamicharts/...` |
|
||||
|
||||
---
|
||||
|
||||
## Полезные команды
|
||||
|
||||
```bash
|
||||
# Статус
|
||||
kubectl get pods -A
|
||||
kubectl get applications -n argocd
|
||||
|
||||
# Логи backend
|
||||
kubectl logs -n sova-test deploy/backend -c php-fpm --tail=50
|
||||
|
||||
# Пересоздать БД
|
||||
kubectl delete job db-init -n sova-data-test
|
||||
USE_MULTIPASS=1 ./scripts/deploy-test-stack.sh local-test
|
||||
|
||||
# Helm dry-run
|
||||
helm template backend-test ./sova-deploy/apps/backend \
|
||||
-f ./sova-deploy/apps/backend/values-test.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
В `k3s-test/` собран **полноценный test-контур**: приложения, изолированные БД (schema → seed), моки внешних сервисов, GitOps и заготовка CI. Локально он крутится на Multipass + k3s и имитирует production-подобный стек без изменений монорепо.
|
||||
|
||||
Перенос на удалённый сервер — это в основном замена **домена**, **TLS**, **registry образов** и **управления секретами**; скрипты и Helm charts из `k3s-test/` переиспользуются с минимальными правками `values-test.yaml`.
|
||||
|
||||
Дальнейшие шаги для production-ready test-сервера:
|
||||
|
||||
1. DNS + TLS
|
||||
2. Gitea Container Registry (для `docker push` в CI)
|
||||
3. SealedSecrets
|
||||
4. Backup БД
|
||||
5. Отдельный stage-контур с `values-stage.yaml`
|
||||
Reference in New Issue
Block a user