diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 2480640..174b62a 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -120,6 +120,7 @@ export default defineConfig({ { text: 'Grafana / Prometheus / Loki', link: '/infrastructure/test-contour/guides/monitoring' }, { text: 'Redmine', link: '/infrastructure/test-contour/guides/redmine' }, { text: 'CLOUD-SITE-TEST-01 (удалённый сервер)', link: '/infrastructure/test-contour/cloud-site-test-01' }, + { text: 'Как развернуть (пошагово)', link: '/infrastructure/test-contour/deploy-walkthrough' }, { text: 'Что сделано + перенос на сервер', link: '/infrastructure/test-contour/test-contour-article' }, { text: 'Git-flow: ветки и релизы', link: '/infrastructure/test-contour/git-flow' }, { text: 'Система тегов CI/CD', link: '/infrastructure/test-contour/tags' }, diff --git a/infrastructure/test-contour/deploy-walkthrough.md b/infrastructure/test-contour/deploy-walkthrough.md new file mode 100644 index 0000000..2ad1b22 --- /dev/null +++ b/infrastructure/test-contour/deploy-walkthrough.md @@ -0,0 +1,356 @@ +# Как развернуть test-контур на CLOUD-SITE-TEST-01 + +Пошаговый рассказ: что делали при переносе песочницы с локальной Multipass-VM на удалённый сервер **CLOUD-SITE-TEST-01** (`dev.sovamed.ru`). Для справочника по архитектуре см. [CLOUD-SITE-TEST-01](./cloud-site-test-01.md), для общего плана — [`k3s/DEPLOY.md`](../../../../k3s/DEPLOY.md). + +--- + +## 0. Что было до этого + +Локально крутилась **Multipass-ферма** (`vm-k8s-git`, `*.sova.local`, NodePort). Для общего test-контура на железе решили: + +- один сервер, один **k3s**; +- публичные домены **`*.dev.sovamed.ru`**; +- **Let's Encrypt** вместо self-signed; +- **без Redmine** (экономия RAM); +- CI/CD и GitOps — как на локалке: Gitea → ArgoCD → Helm. + +Исходники лежат в монорепо: оркестрация в **`k3s/`**, приложения и Helm — в **`k8s/`**. + +--- + +## 1. Подготовка сервера и DNS + +### Сервер + +| | | +|--|--| +| Имя | CLOUD-SITE-TEST-01 | +| Публичный IP | `46.243.172.227` | +| VPN / SSH / kubectl | `10.0.186.3` | +| Пользователь | `petrov` | +| RAM | 12 GB (+ swap 8 GB) | + +### DNS + +A-записи на **`46.243.172.227`**: + +``` +git.dev.sovamed.ru +argocd.dev.sovamed.ru +grafana.dev.sovamed.ru +api.dev.sovamed.ru +adm.dev.sovamed.ru +cabinet.dev.sovamed.ru +docs.dev.sovamed.ru +``` + +Порт **80** с интернета обязателен — без него Let's Encrypt (HTTP-01) не выпустит сертификаты. + +### VPN + +SSH и `kubectl` с рабочей машины — через VPN на **`10.0.186.3`**. Браузер — на публичные URL через DNS. + +--- + +## 2. Настройка на Mac + +```bash +cd k3s +cp remote.env.example remote.env +``` + +Заполнил **`remote.env`** (главное): + +```bash +SERVER_IP=10.0.186.3 # VPN для SSH/kubectl +BASE_DOMAIN=dev.sovamed.ru +GITEA_DOMAIN=git.dev.sovamed.ru +API_DOMAIN=api.dev.sovamed.ru +# ... остальные домены +ENABLE_TLS=1 +LETSENCRYPT_EMAIL=devops@sovamed.ru +CLUSTER_ISSUER=letsencrypt-prod +SWAP_GB=8 +SKIP_REDMINE=1 +KUBECONFIG_PATH=~/.kube/config-sova-remote-test +``` + +SSH-пароль и sudo — в `remote.env` (или ключ). **SSH-пароль на сервере потом не меняли** — только сервисные креды в k8s. + +Права на скрипты: + +```bash +chmod +x scripts/*.sh scripts/lib/*.sh +chmod +x ../k8s/scripts/*.sh +``` + +Проверка: + +```bash +ssh petrov@10.0.186.3 +``` + +--- + +## 3. Автоматический bootstrap (основной прогон) + +```bash +cd k3s +./scripts/bootstrap-remote-test.sh +``` + +Скрипт **`bootstrap-remote-test.sh`** по шагам: + +| Шаг | Что происходит | +|-----|----------------| +| **1** | На сервере: swap 8 GB, apt, установка **k3s** (`--disable traefik`), скачивание **kubeconfig** на Mac | +| **2** | Platform: ingress-nginx (LB 80/443), cert-manager, sealed-secrets, ArgoCD, Prometheus/Grafana, Loki, Gitea; **basic auth** + ingress для git/argocd/grafana | +| **3** | Gitea: org `sova`, push репозиториев (backend, adminpanel, cabinet, docs, sova-deploy, sova-mocks) | +| **4** | Gitea Actions runner, CI secrets, **registries.yaml** на ноде для pull образов | +| **5** | PostgreSQL, MySQL, Redis, WireMock/Mailpit, db-init | +| **6** | ArgoCD: project, test-contour apps, ожидание Healthy | +| **7** | TLS: ClusterIssuer Let's Encrypt, выпуск сертификатов | +| **8** | Итог: список URL и паролей | + +Если упало на середине — продолжить: + +```bash +BOOTSTRAP_FROM_STEP=4 ./scripts/bootstrap-remote-test.sh +``` + +Kubeconfig после шага 1: + +```bash +export KUBECONFIG=~/.kube/config-sova-remote-test +kubectl get nodes +``` + +--- + +## 4. Что правили после bootstrap + +Автомат не покрывает всё — ниже реальные доработки на этом контуре. + +### 4.1. Домены в GitOps + +В **`k8s/sova-deploy/apps/*/values-test.yaml`** выставили хосты `*.dev.sovamed.ru`, TLS, образы из Gitea registry: + +```yaml +ingress: + host: api.dev.sovamed.ru + tls: + enabled: true + clusterIssuer: letsencrypt-prod +image: + repository: git.sova.local/sova/backend + tag: backend-v1.0.13-test +``` + +Запушили ветку **`test`** в Gitea (`sova/sova-deploy`) → ArgoCD подхватил. + +### 4.2. Registry и pull образов + +CI пушит в registry под **`git.sova.local`**, нода должна резолвить registry: + +- **`/etc/hosts`** на сервере: `10.0.186.3 git.dev.sovamed.ru git.sova.local` +- **`/etc/rancher/k3s/registries.yaml`** — mirror + credentials +- Скрипт: `k8s/scripts/configure-k3s-registry-remote.sh` + +### 4.3. CI/CD под HTTPS + +Обновили workflow **`build.yml`** в app-репозиториях и скрипты (`gitea-url.sh`, `release-tag.sh`, `bootstrap-gitea-ci-secrets.sh`) — Gitea с Mac/VPN через `https://10.0.186.3` + заголовок `Host: git.dev.sovamed.ru`. + +Проверка релиза: + +```bash +cd k8s +export KUBECONFIG=~/.kube/config-sova-remote-test +export VM_IP=10.0.186.3 GITEA_SCHEME=https GITEA_HTTP_PORT=443 GITEA_INSECURE_TLS=1 +export GITEA_HOST=git.dev.sovamed.ru + +./scripts/release-tag.sh backend backend-v1.0.13-test +``` + +Цепочка: **тег → Gitea Actions → образ в registry → commit в sova-deploy → ArgoCD sync → pod**. + +### 4.4. Ветки issues/27 + +Перенесли feature-ветки из монорепо в Gitea и смержили в **`test`**: + +```bash +./scripts/migrate-issues-27-branches.sh +# merge issues/27 → test для backend, adminpanel, cabinet +``` + +### 4.5. TLS на приложениях + +После sync ArgoCD ingress терял TLS — добавили блок `tls` в Helm-шаблоны `sova-deploy/apps/*/templates/all.yaml` и `ingress.tls.enabled` в values-test. + +### 4.6. Redmine убрали + +Redmine на этом сервере не нужен: + +```bash +kubectl delete application redmine-test -n argocd +``` + +### 4.7. Пароли + +Сгенерировали сложные пароли для Gitea, ArgoCD, Grafana, БД, app secrets. Применили: + +- helm/API для platform; +- `ALTER USER` в PostgreSQL/MySQL; +- GitOps (`sova-deploy/data/test`, `apps/*/values.yaml`); +- bcrypt для seed-пользователей admin/cabinet. + +Все креды — **`k8s/.generated/platform-credentials.env`** (не в git). SSH не трогали. + +### 4.8. Admin Panel — API URL + +Admin Panel не логинился: в **`values-test.yaml`** был ключ `env:` вместо **`runtimeEnv:`** → в pod уходил `http://api.test.sova.local`. Исправили: + +```yaml +runtimeEnv: + API_BASE_URL: https://api.dev.sovamed.ru +``` + +### 4.9. Grafana + Loki + +Grafana падала из-за двух default datasource. Решение: + +- Loki подключён через **`grafana.additionalDataSources`** в `values-lite-12gb.yaml`; +- отдельный ConfigMap `loki-loki-stack` удаляется после helm loki-stack. + +### 4.10. Basic Auth на периметре + +Все публичные URL закрыты **HTTP Basic Auth** на ingress: + +```bash +./scripts/bootstrap-ingress-basic-auth.sh # secret contour-basic-auth +./scripts/deploy-platform-ingress.sh # platform ingress +``` + +Логin: **`sova-contour`**, пароль — в `platform-credentials.env`. + +Для Gitea — **два Ingress**: `/api`, `/v2`, `/sova` без auth (CI/git), веб-UI `/` — с auth. + +--- + +## 5. Типичный рабочий цикл после развёртывания + +### kubectl + +```bash +export KUBECONFIG=~/.kube/config-sova-remote-test +kubectl get applications -n argocd +kubectl get pods -n sova-test +``` + +### Выкат новой версии приложения + +```bash +cd k8s +./scripts/release-tag.sh backend backend-v1.0.14-test +# аналогично: adminpanel, cabinet, docs +``` + +### Выкат документации + +```bash +./scripts/release-tag.sh docs docs-v1.0.15-test +``` + +### ArgoCD sync вручную + +```bash +kubectl annotate application backend-test -n argocd argocd.argoproj.io/refresh=hard --overwrite +``` + +### Креды + +```bash +cat k8s/.generated/platform-credentials.env +./scripts/print-credentials.sh +``` + +--- + +## 6. Проверка «всё живо» + +```bash +export KUBECONFIG=~/.kube/config-sova-remote-test +source k8s/.generated/platform-credentials.env + +# Basic auth + TLS +curl -sk -o /dev/null -w "%{http_code}\n" -u "${BASIC_AUTH_USER}:${BASIC_AUTH_PASS}" \ + -H "Host: api.dev.sovamed.ru" https://10.0.186.3/ + +# ArgoCD +kubectl get applications -n argocd + +# Сертификаты +kubectl get certificate -A + +# CI +curl -sk -u "gitea_admin:${GITEA_ADMIN_PASS}" -H "Host: git.dev.sovamed.ru" \ + "https://10.0.186.3/api/v1/repos/sova/backend/actions/runs?limit=1" +``` + +Чеклист: + +- [ ] `kubectl get nodes` — Ready +- [ ] ArgoCD apps — Synced / Healthy +- [ ] URL открываются (с basic auth → затем логин сервиса) +- [ ] `kubectl get certificate -A` — Ready +- [ ] CI по тегу `*-test` — success +- [ ] Grafana Explore → Loki → `{namespace="sova-test"}` + +--- + +## 7. Карта скриптов (что за что отвечает) + +``` +k3s/scripts/bootstrap-remote-test.sh ← главная команда «развернуть всё» +k3s/remote.env ← IP, домены, TLS, SSH + +k8s/scripts/deploy-platform-remote.sh ← Helm: ingress, cert-manager, ArgoCD, Gitea… +k8s/scripts/deploy-platform-ingress.sh ← Ingress git / argocd / grafana (+ basic auth) +k8s/scripts/bootstrap-ingress-basic-auth.sh +k8s/scripts/bootstrap-gitea.sh ← org, repos, admin +k8s/scripts/bootstrap-gitea-runner.sh ← Actions runner +k8s/scripts/bootstrap-gitea-ci-secrets.sh +k8s/scripts/configure-k3s-registry-remote.sh +k8s/scripts/deploy-test-stack.sh ← БД + mocks (DATA_ONLY=1) +k8s/scripts/bootstrap-argocd.sh ← GitOps apps +k8s/scripts/bootstrap-tls.sh ← Let's Encrypt +k8s/scripts/release-tag.sh ← тег → CI → deploy +``` + +--- + +## 8. Частые проблемы + +| Симптом | Что делали | +|---------|------------| +| ImagePullBackOff | `configure-k3s-registry-remote.sh`, `/etc/hosts` на ноде | +| ArgoCD «Failed to authenticate» к Gitea | обновить secret `repo-sova-deploy` с новым паролем Gitea | +| Admin Panel не логинится | `runtimeEnv.API_BASE_URL`, не `env:` | +| Grafana CrashLoop | один default datasource; Loki через Helm `additionalDataSources` | +| Symfony «parameter 3Dbi6a» | в `REDIS_URL`/`DATABASE_URL` удвоить `%` → `%%` для GitOps | +| CI 403 на push | проверить Gitea credentials, `gitea_git_remote_url` (URL-encode пароля) | +| Let's Encrypt pending | DNS, порт 80, `/.well-known/acme-challenge` без auth | + +--- + +## 9. Ссылки + +- [CLOUD-SITE-TEST-01 — справочник по системе](./cloud-site-test-01.md) +- [Gitea CI / теги](./guides/gitea-ci.md) +- [Система тегов](./tags.md) +- [ArgoCD apps](./argocd-apps.md) +- [Grafana / Loki](./guides/monitoring.md) +- [`k3s/TLS.md`](../../../../k3s/TLS.md) + +--- + +*Документ описывает фактический процесс развёртывания test-контура на CLOUD-SITE-TEST-01 (2026).* diff --git a/infrastructure/test-contour/index.md b/infrastructure/test-contour/index.md index 67de144..a0dad32 100644 --- a/infrastructure/test-contour/index.md +++ b/infrastructure/test-contour/index.md @@ -17,6 +17,7 @@ ### Текстовая документация - [**CLOUD-SITE-TEST-01: удалённый test-сервер**](./cloud-site-test-01) — домены, TLS, basic auth, CI/CD, мониторинг +- [**Как развернуть test-контур (пошагово)**](./deploy-walkthrough) — bootstrap, доработки, рабочий цикл - [Git-flow: ветки, теги, автодеплой](./git-flow) — prod / test / stage, PR, пример через UI Gitea - [Test-контур: что сделано и перенос на server](./test-contour-article) — полная статья - [Система тегов CI/CD](./tags) — формат тегов и release-скрипт