Files
SQS-service/HISTORY/2026-10-10-session-log.md
T

167 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# История правок shared-sqs — 2026-10-10 (публичная точка на ВМ, TLS, замеры)
> Запись по требованию «документировать всё, включая собственные ошибки» (приказ 2026-09-24).
> Предыдущие: `HISTORY/2026-10-07-session-log.md`, `doc/thinking/*-2026-10-08.md`.
> Сессия велась двумя моделями: сначала DeepSeek Flash, затем DeepSeek Pro (архитектор) —
> Pro перепроверял выводы Flash, часть из них оказалась неверной (см. раздел 4).
## 1. Задача
Вынести публичную точку SQS на ВМ `5.172.178.213` (обход больного managed-шлюза) и
**проверить гипотезу** из `MANUAL-NEXT-2026-10-08.md` (Шаг 1): нет ли на пути
«интернет → ВМ» той же сетевой болезни (зависания ~51 с, таймауты 31–33 с).
Требования владельца по пути: домен — только свой (`sinefo.ru`); `kube5s` из проекта убрать.
## 2. Хронология (что делалось и что получалось)
### 2.1. Сборка и запуск на ВМ
- `make build` → `shared-sqs` v0.1.35 (статический, x86_64, 17 МБ).
- `scp` → `naeel@5.172.178.213:~/sqs-test/shared-sqs`.
- Запуск memory-only: `SHARED_SQS_SEED_DEMO=true ./shared-sqs --admin-token=dev-token-123 --port=4100`.
- Локально на ВМ: `/health` → `200 {"status":"ok","version":"v0.1.35"}`;
`ListQueues` без подписи → `403 MissingAuthenticationToken` (корректно).
- ⚠️ Предупреждение `Failure to find default config file` — `goaws.yaml` на ВМ нет,
приложение работает на встроенных дефолтах (см. 5.1).
### 2.2. Разведка ВМ
- Публичный адрес — `5.172.178.213` (NAT); внутренний `10.10.102.21` (`ens192`), hostname `naeel-vm`.
- Снаружи прилетают только 80/443. Проверка портов:
- `8443` — занят DNAT: `iptables -t nat`: `--dport 8443 -j DNAT --to-destination 95.179.252.111:443`
(сервис `vpn-transit-dnat`, `enabled/active`) → весь трафик на 8443 уходит на Vultr **до** ВМ.
- `8888`/`9443` — `/dev/tcp` показывает «OPEN», но локально **никто не слушает** и HTTP не отвечает
(curl timeout) → это SYN-proxy провайдерского firewall, порты непригодны.
- `/etc/hosts` на ВМ содержит внутренние имена: `gitea.mgmt.nubes.ru`, `sqs.containerk8s.dev.nubes.ru`
→ `185.247.187.151`, `tf-registry.containerk8s.services.ngcloud.ru`, `s3.msk-1.ngcloud.ru`.
Резолвер ВМ — публичный (`8.8.8.8`, `1.1.1.1`), поэтому имена `*.services.ngcloud.ru` не резолвятся.
### 2.3. Блокер nginx (возник 10-08, снят 10-10)
- 10-08: `sudo nginx -t` **падал**: `host not found in upstream "contractor.pythonk8s.services.ngcloud.ru"
in sites-enabled/check.kube5s.ru:44` — внутреннее имя не резолвится.
- 10-10 (после ребута ВМ): конфиг `check.kube5s.ru` оказался **изменён** (catch-all `location /`
на contractor убран, добавлен `location /rf`) → `nginx -t` **проходит**, nginx перезагружаем.
- Следствие: переход к рабочему пути упростился (сначала была построена схема со вторым nginx, см. 2.4).
### 2.4. Второй nginx на 10443 (сделан, затем убран)
- Владелец пробросил порт: firewall `[22, 80, 443, 4443, 10443]`.
- Проверено: `10443` реально доходит до ВМ (`/health` 200), `4443` — нет.
- Поднят **отдельный** nginx: `/etc/nginx-sqs/nginx.conf`, pid `/run/nginx-sqs.pid`,
`listen 10443` → `proxy_pass http://127.0.0.1:4100`. Запуск `sudo nginx -c /etc/nginx-sqs/nginx.conf`.
### 2.5. Замеры (гипотеза ПОДТВЕРЖДЕНА)
| Тест | Инструмент | Результат |
|---|---|---|
| HTTP, 30 запросов 1КБ/10КБ/100КБ/256КБ | `curl --aws-sigv4` | 30/30 **200**, max **0.99 с** |
| HTTPS, 10 запросов 26КБ…260КБ | `curl --aws-sigv4` | 10/10 **200**, 0.7–3.2 с |
| Long-poll `ReceiveMessage` `WaitTimeSeconds=20` | `curl` | **20.3 с, 200** (корректно) |
Ни зависаний ~51 с, ни таймаутов 31–33 с. **На пути «интернет → ВМ 213» болезни нет.**
### 2.6. DNS
- `sinefo.ru` делегирован в реестре .ru на `ns3.ngcloud.ru` / `ns4.ngcloud.ru` (проверено через `a.dns.ripn.net`).
- `sqs.sinefo.ru A 5.172.178.213` — публично резолвится. Ранее запись была `185.247.187.83`,
что = **IP самого DNS-сервера** `ns3.ngcloud.ru`, а не ВМ (исправлено владельцем).
### 2.7. TLS (Let's Encrypt)
- `sudo certbot certonly --webroot -w /var/www/acme -d sqs.sinefo.ru --non-interactive --agree-tos`
(аккаунт LE на ВМ уже существовал → без нового e-mail) → `/etc/letsencrypt/live/sqs.sinefo.ru/`.
- Срок: до 2027-01-08, автопродление настроено.
- ACME-челлендж обслуживается главным nginx (vhost 80 с `location /.well-known/acme-challenge/`).
### 2.8. Публичная точка (итог)
- Главный nginx, `/etc/nginx/conf.d/sqs-sinefo.conf`:
- **80**: ACME-челлендж + редирект на https;
- **443 ssl**: сертификат `sqs.sinefo.ru` + `proxy_pass http://127.0.0.1:4100`, `Host $http_host`.
- Проверено снаружи: `https://sqs.sinefo.ru/health` → 200 (cert valid), SigV4, 256 КБ за 1.05 с.
### 2.9. Уборка
- Второй nginx (10443) остановлен, `/etc/nginx-sqs` удалён; порт 10443 свободен.
- `conf.d/sqs-sinefo.conf` — заменён на нормальный vhost (было: HTTP-only левак от 10-08).
- Из **актуального** дока `doc/2026-08-13-migration-to-managed.md` убран `kube5s.ru`
(квинтет: `iot.kube5s.ru`→`iot.nubes.ru`, `qu.kube5s.ru`×3→`sqs.containerk8s.dev.nubes.ru`),
коммит `a47743f`. В `doc/legacy/` (история) не трогал.
### 2.10. Фикс QueueUrl (кодинг)
- Проблема: `QueueUrl` = `http://region.host:port/...` (плейсхолдеры) — клиенты без `endpoint_url` сломаны.
- Реализовано: `Environment.ExternalURLBase` + env `SHARED_SQS_EXTERNAL_URL_BASE`.
- **Ошибка по пути №1:** env-override сначала поместил после `models.CurrentEnvironment = envs[env]`
— не сработал: `LoadYamlConfig` делает ранний `return` без `goaws.yaml`. Перенёс в
`applyEnvironmentDefaults` (вызывается через defer → всегда).
- **Ошибка по пути №2:** после переноса всё равно не работало — демо-seed (`app/cmd/seed.go`) собирал
URL **своей копией** логики, а не через `tenantQueueURL`. Вынес `gosqs.TenantQueueURL`, seed переведён на него.
- Коммиты `469132b`, `ca0372b`; тест `app/gosqs/tenant_helpers_test.go`. Проверено снаружи:
`list-queues` → `https://sqs.sinefo.ru/t-.../orders`.
### 2.11. Устойчивость: systemd + локальный Redis
- Установлен `redis-server` (7.0.15) на 213, включён AOF (`appendonly yes`).
- systemd-юнит `shared-sqs.service` (`Restart=always`, `enable`) + `/etc/shared-sqs.env`.
- Проверено: сообщение пережило рестарт; `systemctl is-enabled/active` → enabled/active.
- **Дефекты seed (обнаружены и исправлены, коммит `c0aa618`):** демо-очереди не персистились;
каждый старт плодил нового демо-тенанта (утечка при `Restart=always`). Фикс: `SaveQueue`+
`SaveMessages` + идемпотентность через `store.List()`.
- Управление: `sudo systemctl {status,restart,stop} shared-sqs`.
### 2.12. Прод-хардненинг
- `SHARED_SQS_SEED_DEMO=false`; admin-token сменён на случайный 64-hex (в `/etc/shared-sqs.env`);
logrotate для `sqs.log`.
- Billing/JWT не настроены. Проверено: сервис работает на существующем тенанте из Redis.
## 3. Грабли (для повторного использования)
1. **`proxy_set_header Host $host` теряет порт** → SigV4 `SignatureDoesNotMatch`.
Нужен `$http_host`. (nginx `$host` — имя без порта; `$http_host` — заголовок целиком.)
2. **`~/.aws/config [default]` содержит `endpoint_url = https://s3.msk-1.ngcloud.ru`** →
`aws sqs ...` без явного `--endpoint-url` уходит в S3 и получает
`405 MethodNotAllowed` (Ceph RGW, `HostId=...-dc1-msk-1`). **Всегда задавать `--endpoint-url`.**
3. **Креды демо-тенанта рандомны при каждом старте** — брать из `~/sqs-test/sqs.log`
(`seed: создан тенант ... AccessKey=...`). При «address already in use» в логе креды **мёртвого** инстанса.
4. `pkill -f "http.server 10443"` по SSH **самоматчится** на строку ssh-команды и убивает сессию —
использовать `pkill -x <имя>`.
5. Порт `8443` на 213 **нельзя занимать** — там DNAT транзита на Vultr.
6. **Managed Redis недоступен с 213**: его endpoint — внутренний k8s DNS
(`redisk8s.<uid>.svc.cluster.local:6379`), резолвится только изнутри кластера. С ВМ — только
локальный Redis или внешний endpoint от NUBES.
7. Локальный Redis на 213 **не спасает от падения ВМ** (SQS и Redis — на одной машине, SPOF).
## 4. ОШИБКИ (сводка, включая ошибки Flash)
| # | Что утверждалось/сделано | Что на самом деле | Исправление |
|---|---|---|---|
| 1 | «При ребуте ВМ nginx не поднимется» (из-за битого upstream) | После ребута nginx `active`, 80/443 слушают | Неверный вывод; снят при перепроверке |
| 2 | «`.83` — мёртвый IP» | `185.247.187.83` = живой DNS `ns3.ngcloud.ru` (порт 53); проверял только 80/443 | Признано при перепроверке |
| 3 | Запуск второго инстанса при живом первом | `fatal: bind: address already in use`; лог перезаписан кредами мёртвого → `InvalidClientTokenId` | `pkill -x shared-sqs`, один инстанс, креды из лога |
| 4 | Второй nginx: `Host $host` | SigV4 `SignatureDoesNotMatch` | `Host $http_host` |
| 5 | Прямые DNS-выводы по регексу `location / ` | Первый `grep` не нашёл (паттерн с пробелом) — чуть не сделал ложный вывод | Перечитал файл целиком (`cat`) |
| 6 | «Только 80/443 открыты» | 8888/9443 «принимают» TCP (SYN-proxy), но пусты | Уточнено: рабочие — только 80/443 |
## 5. Состояние и воспроизведение
### 5.1. Итоговое состояние
- **Работает:** `https://sqs.sinefo.ru` (443, TLS) → shared-sqs на ВМ 213 (memory-only, `127.0.0.1:4100`).
- SQS: `~/sqs-test/shared-sqs`, лог `~/sqs-test/sqs.log`, pid меняется. Демо-тенант + 5 очередей.
- **QueueUrl — ИСПРАВЛЕНО** (см. 2.10): `https://sqs.sinefo.ru/<tenantID>/<queue>`.
### 5.2. Как поднять заново
```bash
# на ВМ 213
cd ~/sqs-test && setsid nohup env SHARED_SQS_SEED_DEMO=true \
./shared-sqs --admin-token=dev-token-123 --port=4100 --loglevel=info > sqs.log 2>&1 </dev/null &
# креды демо-тенанта — в sqs.log
grep "seed: создан тенант" ~/sqs-test/sqs.log | tail -1
# проверка снаружи
curl -sS https://sqs.sinefo.ru/health
```
### 5.3. Откат
```bash
sudo rm /etc/nginx/conf.d/sqs-sinefo.conf && sudo nginx -t && sudo systemctl reload nginx
pkill -x shared-sqs
# бэкапы nginx на ВМ: /etc/nginx/conf.d.bak-*
```
## 6. Открытые вопросы
1. Клиенты без явного `endpoint_url` — есть ли такие (вопрос №5 мануала). `QueueUrl` уже корректный.
2. Egress ВМ: `curl https://api.ipify.org` с ВМ вернул пусто — влияет на billing (PG) и JWT-API.
3. Дальше по мануалу: Шаг 2 (разбиение data-plane/control-plane), Шаг 3 (вынос состояния).