chore: initial docs site for test contour
This commit is contained in:
@@ -0,0 +1,103 @@
|
|||||||
|
name: docs-ci-cd
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'docs-v*'
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: gitea-http.gitea.svc.cluster.local:3000
|
||||||
|
IMAGE: gitea-http.gitea.svc.cluster.local:3000/sova/docs
|
||||||
|
IMAGE_DEPLOY: git.sova.local/sova/docs
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Validate site files
|
||||||
|
run: |
|
||||||
|
test -f site/index.html
|
||||||
|
test -f site/README.md
|
||||||
|
test -f site/docs/test-contour-article.md
|
||||||
|
|
||||||
|
parse-tag:
|
||||||
|
if: startsWith(github.ref, 'refs/tags/docs-v')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
full_tag: ${{ steps.meta.outputs.full_tag }}
|
||||||
|
env: ${{ steps.meta.outputs.env }}
|
||||||
|
version: ${{ steps.meta.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- name: Parse tag
|
||||||
|
id: meta
|
||||||
|
run: |
|
||||||
|
TAG="${GITHUB_REF#refs/tags/}"
|
||||||
|
echo "full_tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "env=$(echo "$TAG" | sed -E 's/docs-v([0-9.]+)-([a-z]+)/\2/')" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "version=$(echo "$TAG" | sed -E 's/docs-v([0-9.]+).*/\1/')" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
build-and-push:
|
||||||
|
needs: [test, parse-tag]
|
||||||
|
if: startsWith(github.ref, 'refs/tags/docs-v')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Docker login
|
||||||
|
env:
|
||||||
|
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||||||
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
echo "${REGISTRY_PASSWORD}" | docker login "$REGISTRY" -u "${REGISTRY_USER}" --password-stdin
|
||||||
|
- name: Build and push
|
||||||
|
run: |
|
||||||
|
TAG="${{ needs.parse-tag.outputs.full_tag }}"
|
||||||
|
docker build -f Dockerfile -t "$IMAGE:${TAG}" -t "$IMAGE:${{ needs.parse-tag.outputs.version }}" .
|
||||||
|
docker push "$IMAGE:${TAG}"
|
||||||
|
docker push "$IMAGE:${{ needs.parse-tag.outputs.version }}"
|
||||||
|
|
||||||
|
deploy-gitops:
|
||||||
|
needs: [build-and-push, parse-tag]
|
||||||
|
if: startsWith(github.ref, 'refs/tags/docs-v')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Bump image tag in sova-deploy
|
||||||
|
env:
|
||||||
|
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
|
||||||
|
DEPLOY_USER: ${{ secrets.REGISTRY_USER }}
|
||||||
|
run: |
|
||||||
|
REPO_URL="http://${DEPLOY_USER}:${DEPLOY_TOKEN}@gitea-http.gitea.svc.cluster.local:3000/sova/sova-deploy.git"
|
||||||
|
git clone "${REPO_URL}"
|
||||||
|
cd sova-deploy
|
||||||
|
ENV="${{ needs.parse-tag.outputs.env }}"
|
||||||
|
TAG="${{ needs.parse-tag.outputs.full_tag }}"
|
||||||
|
git config user.email "ci-bot@sova.local"
|
||||||
|
git config user.name "sova-ci"
|
||||||
|
MAX_RETRIES=5
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64) YQ_ARCH=amd64 ;;
|
||||||
|
aarch64|arm64) YQ_ARCH=arm64 ;;
|
||||||
|
*) echo "Unsupported arch: $(uname -m)"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
curl -sSL -o /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_${YQ_ARCH}"
|
||||||
|
chmod +x /usr/local/bin/yq
|
||||||
|
for attempt in $(seq 1 $MAX_RETRIES); do
|
||||||
|
git pull --rebase "${REPO_URL}" main
|
||||||
|
yq -i ".image.repository = \"${IMAGE_DEPLOY}\"" "apps/docs/values-${ENV}.yaml"
|
||||||
|
yq -i ".image.tag = \"${TAG}\"" "apps/docs/values-${ENV}.yaml"
|
||||||
|
yq -i ".image.pullPolicy = \"IfNotPresent\"" "apps/docs/values-${ENV}.yaml"
|
||||||
|
git add "apps/docs/values-${ENV}.yaml"
|
||||||
|
git diff --cached --quiet && { echo "No changes"; exit 0; }
|
||||||
|
git commit -m "chore(docs): bump ${ENV} to ${TAG}"
|
||||||
|
if git push "${REPO_URL}" main; then
|
||||||
|
echo "Push OK on attempt ${attempt}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Push failed, retry ${attempt}/${MAX_RETRIES}..."
|
||||||
|
git reset --hard HEAD~1
|
||||||
|
sleep $((attempt * 2))
|
||||||
|
done
|
||||||
|
echo "Failed to push after ${MAX_RETRIES} attempts"
|
||||||
|
exit 1
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
FROM nginx:1.27-alpine
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY site/ /usr/share/nginx/html/
|
||||||
|
EXPOSE 8080
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(md|html|css|js|json)$ {
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Документация test-контура Sova
|
||||||
|
|
||||||
|
Статический сайт с инструкциями по песочнице `k3s-test`: развёртывание, CI/CD, GitOps и перенос на удалённый сервер.
|
||||||
|
|
||||||
|
## Быстрые ссылки
|
||||||
|
|
||||||
|
| URL | Сервис |
|
||||||
|
|-----|--------|
|
||||||
|
| http://docs.sova.local | эта документация |
|
||||||
|
| http://api.test.sova.local | backend API |
|
||||||
|
| http://admin.test.sova.local | admin panel |
|
||||||
|
| http://cabinet.test.sova.local | личный кабинет |
|
||||||
|
| http://argocd.sova.local | ArgoCD |
|
||||||
|
| http://git.sova.local | Gitea |
|
||||||
|
|
||||||
|
## Разделы
|
||||||
|
|
||||||
|
- [Test-контур k3s](docs/test-contour-article.md) — полная статья: архитектура, bootstrap, CI, troubleshooting
|
||||||
|
- [Система тегов](docs/tags.md) — формат тегов и release-скрипт
|
||||||
|
- [ArgoCD приложения](docs/argocd-apps.md) — зачем `sova-root` и `data-test`, почему «нельзя войти»
|
||||||
|
|
||||||
|
Исходники: репозиторий `sova/docs` в Gitea, каталог `k3s-test/sova-docs/` локально.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
* [Главная](/README.md)
|
||||||
|
* [Test-контур k3s](/docs/test-contour-article.md)
|
||||||
|
* [Система тегов CI/CD](/docs/tags.md)
|
||||||
|
* [ArgoCD: sova-root и data-test](/docs/argocd-apps.md)
|
||||||
@@ -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,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/` | Документация (Docsify) + 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`
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Sova Test Contour Docs</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script>
|
||||||
|
window.$docsify = {
|
||||||
|
name: 'Sova Test Contour',
|
||||||
|
repo: '',
|
||||||
|
loadSidebar: true,
|
||||||
|
subMaxLevel: 3,
|
||||||
|
auto2top: true,
|
||||||
|
homepage: 'README.md',
|
||||||
|
search: 'auto',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/plugins/search.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user