Add step-by-step deploy walkthrough for CLOUD-SITE-TEST-01.
Document bootstrap, post-deploy fixes, and day-to-day workflow on remote test contour. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -120,6 +120,7 @@ export default defineConfig({
|
|||||||
{ text: 'Grafana / Prometheus / Loki', link: '/infrastructure/test-contour/guides/monitoring' },
|
{ text: 'Grafana / Prometheus / Loki', link: '/infrastructure/test-contour/guides/monitoring' },
|
||||||
{ text: 'Redmine', link: '/infrastructure/test-contour/guides/redmine' },
|
{ text: 'Redmine', link: '/infrastructure/test-contour/guides/redmine' },
|
||||||
{ text: 'CLOUD-SITE-TEST-01 (удалённый сервер)', link: '/infrastructure/test-contour/cloud-site-test-01' },
|
{ 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: 'Что сделано + перенос на сервер', link: '/infrastructure/test-contour/test-contour-article' },
|
||||||
{ text: 'Git-flow: ветки и релизы', link: '/infrastructure/test-contour/git-flow' },
|
{ text: 'Git-flow: ветки и релизы', link: '/infrastructure/test-contour/git-flow' },
|
||||||
{ text: 'Система тегов CI/CD', link: '/infrastructure/test-contour/tags' },
|
{ text: 'Система тегов CI/CD', link: '/infrastructure/test-contour/tags' },
|
||||||
|
|||||||
@@ -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).*
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
### Текстовая документация
|
### Текстовая документация
|
||||||
|
|
||||||
- [**CLOUD-SITE-TEST-01: удалённый test-сервер**](./cloud-site-test-01) — домены, TLS, basic auth, CI/CD, мониторинг
|
- [**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
|
- [Git-flow: ветки, теги, автодеплой](./git-flow) — prod / test / stage, PR, пример через UI Gitea
|
||||||
- [Test-контур: что сделано и перенос на server](./test-contour-article) — полная статья
|
- [Test-контур: что сделано и перенос на server](./test-contour-article) — полная статья
|
||||||
- [Система тегов CI/CD](./tags) — формат тегов и release-скрипт
|
- [Система тегов CI/CD](./tags) — формат тегов и release-скрипт
|
||||||
|
|||||||
Reference in New Issue
Block a user