# Журнал сессии — 2026-08-16 (IoT: интеграция с shared-sqs, выбор пути миграции) **Рабочая папка:** /home/naeel/nubes/IoT > Правило этой сессии (задано пользователем): ВСЁ документировать в HISTORY, > каждый шаг — сразу. --- ## 1. Контекст (состояние на входе) - Пользователь завершил handoff по shared-sqs: - `HANDOFF-NEW-CHAT.md` — в SQS-репозитории, закоммичен и запушен (`5fa34c2`). - `doc/sqs-integration.md` — создан в IoT-репозитории, **не закоммичен** (untracked). - `2026-08-13-migration-to-managed.md` — также untracked в IoT-репо. - Git IoT: HEAD `368ff06` (feature/replace-kafka-with-sqs), origin отстаёт на 1 коммит (HEAD не запушен: «fix(ingress): remove cert-manager + ssl-redirect»). ## 2. `doc/sqs-integration.md` — что важно для IoT (прочитан, суть) - shared-sqs: прод v0.1.35, все тесты зелёные (api 22/22, sdk 15/15, FIFO/DLQ e2e), нагрузка 168 591 операция — 0 сервисных ошибок. - Внешний endpoint: `https://sqs.containerk8s.dev.nubes.ru` (регион us-east-1). - Внутренний endpoint (поды того же кластера Nubes, realm iot-naeel): `http://containerk8s.f1ffb134-7d16-45bd-8bef-69f6ec8ab33c.svc.cluster.local:4100`. - Проблемы ПЛАТФОРМЫ (не сервиса): 1. Таймауты каждые 31–33с на внешнем пути (~5.5% запросов без ответа 30с). Доказано tcpdump; внутри кластера потерь нет (port-forward 24977 раундов, 0 сбоев). 2. MSS=1448 при MTU 1400 → тела >~1400 байт виснут ~51с (PMTUD сломан). Тикет Nubes подготовлен (`SQS-service/doc/thinking/nubes-ticket.md`). - Рекомендации интеграции: AWS SDK + override endpoint; главная — внутренний адрес (обходит шлюз полностью); ретраи ≥3, read_timeout ≥30с (для внешнего пути); сообщения до ~1300 байт; VisibilityTimeout 30с+; FIFO требует MessageGroupId (dedup 5 мин); DLQ через RedrivePolicy; лимит 50 очередей на тенанта. - Креды детерминированы из email: tenantID `t-`+sha256(email)[:8], AccessKey `SSAK-`+sha256(email)[:12], SecretKey sha256(email+":shared-sqs:secret-key:v1"). - Блокер прода — только тикет Nubes (для интернет-клиентов); для внутренней интеграции блокеров нет. ## 3. Как сейчас развёртывается IoT (факты из репозитория) - Код полностью на Go 1.25, модуль `gitea.services.ngcloud.ru/Nail/IoT`. - Один образ Docker Hub `naeel/iot-operator:v0.2.6` (distroless), три бинарника: `/iot-operator`, `/mqtt-bridge`, `/sqs-consumer`. - Собственный k8s кластер `iot-naeel`, namespace `sless`, API `185.247.187.149:6443`. - Деплой с ВМ: `ssh naeel@5.172.178.213`, каталог `/home/naeel/terra/IoT`, `kubectl apply -f deployments/k8s/` (kubeconfig на ВМ, токен ~24ч). - Компоненты: - `iot-operator` — controller-manager (CRD IoTDevice) + REST API :9090; - `iot-mqtt-bridge` — EMQX → SQS SendMessage; - `iot-sqs-consumer` — SQS → Postgres (long poll 20с, delete после записи); - EMQX 5.5.1 — MQTT-брокер (HTTP auth → operator). - Секреты (ns sless): `iot-bridge-credentials`, `iot-sqs-credentials` (`SQS_ENDPOINT=https://qu.kube5s.ru` — старый внешний адрес, устарел), `iot-postgres-secret` (managed PG, `...svc.cluster.local:5432/sqsdb`). - Ingress: устройства по `wss://iot.kube5s.ru/mqtt`. - Миграция на managed Node.js (план от 13.08) — НЕ выполнена; Node.js-кода в репо нет. ## 4. Обсуждение: HTTP-контейнер vs Managed Node.js (вывод этой сессии) - Вывод AI: HTTP-контейнер (как у shared-sqs) лучше: Go сохраняется целиком, Dockerfile готов, схема доказана shared-sqs, внутренняя сеть без таймаутов. Managed Node.js = полный rewrite (aedes, Express, @aws-sdk/client-sqs, pg) — запасной. - Открытый риск контейнера: поддержка WebSocket upgrade на платформенном ingress не проверена (устройства ходят по wss). - Устройства в любом варианте ходят через внешний шлюз Nubes — проблемы шлюза (5.5% таймаутов, MSS) остаются риском для wss в обоих вариантах. ## 5. Чтение SQS-репозитория (`/home/naeel/nubes/SQS-service`) — выяснено - **План Node.js фактически отменён.** `doc/2026-08-13-migration-to-nubes.md`: «Код не меняется вообще. Только инфраструктура». - shared-sqs мигрировал в **«Простой HTTP контейнер» (nubes_http)** через deck-UI, realm `iot-naeel`. Домен `sqs.containerk8s.dev.nubes.ru`, `/health` OK. - Технические факты платформы (из HISTORY 13–14.08): - Контейнер = k8s deployment `containerk8s`, namespace = UUID инстанса (`f1ffb134-7d16-45bd-8bef-69f6ec8ab33c`), контейнер в поде называется `app`, порт 4100. - Внутренний DNS: `containerk8s..svc.cluster.local:4100`. - Внешний: `*.containerk8s.dev.nubes.ru`, ingress/TLS встроены в контейнер. - Образ — ТОЛЬКО публичный Docker Hub (Gitea/GHCR приватные платформа не тянет). - Обновление образа — уникальным тегом (`latest` кэшируется зеркалом `mirror.k8s.ngcloud.ru`); через `kubectl set image deployment/containerk8s app=...` (правки через kubectl не откатываются — ownerReferences нет). - Env vars — в deck-UI; Managed Redis — `redisk8s..svc.cluster.local:6379`. - JWT-валидация: `https://lk-api-gateway.ngcloud.ru/api/v1/svc` (deck-api*.ngcloud.ru — ЛЕГАСИ, не использовать). - Long-running работает: SQS long-poll 20с; HTTP-соединение через ingress держится ~150с (не режется). - **WebSocket в SQS-истории не упоминается вообще** — поддержка wss на платформе не проверялась. Единственный реальный риск контейнерного пути для IoT. ## 6. Вывод и следующий шаг - Путь миграции IoT (кандидат): «Простой HTTP контейнер» в realm `iot-naeel`, Go без переписывания; убрать operator/CRD → таблица `iot_devices` в Postgres; bridge и consumer остаются Go. - Первая проверка перед стартом: WebSocket upgrade (wss) через платформенный ingress — тестовый контейнер с WS-эндпоинтом + `wscat`. - ЖДЁМ решения пользователя по пути миграции. --- ## 7. Создан ws-probe — тестовый контейнер для проверки wss **Команда пользователя:** «делай» (создать пробник + залить образ на Docker Hub; для запуска в deck-UI нужен путь до образа). **Что сделано** (все шаги): 1. Создан каталог `ws-probe/` в IoT-репозитории: - `main.go` — Go echo-сервер на `gorilla/websocket`: `GET /health` (JSON status+version), `GET /ws` (echo + ping каждые 20с, read-deadline 60с, сбрасывается pong'ами — мёртвые соединения закрываются), `GET /` (HTML). Без кредов, без внешних зависимостей. - `Dockerfile` — multi-stage golang:1.25 → distroless/static:nonroot, порт 8080 (меняется env `PORT`), версия через ldflags. - `Makefile` — `docker-build`/`docker-push`, `VERSION=v0.1.0`, `IMAGE=naeel/iot-ws-probe`. - `go.mod`/`go.sum` — отдельный модуль (gorilla/websocket v1.5.3), чтобы не тащить зависимость в основной go.mod IoT. 2. `.gitignore` — добавлен `ws-probe/ws-probe` (сборочный бинарник). 3. Локальные проверки: `go vet` OK; smoke: `/health` → `{"status":"ok","version":"v0.1.0"}`; WS-апгрейд → `HTTP/1.1 101 Switching Protocols` (Sec-WebSocket-Accept корректный). 4. Docker: логин в Docker Hub под `naeel` активен (проверен `docker info`). 5. Образ собран и запушен (публичный): - **`naeel/iot-ws-probe:v0.1.0`** (и `:latest`), - digest `sha256:dc029be3e79fb37f15ce23477096e340ab181b96c0132dc2e443f341e36f0688`, - размер 10.9MB. 6. Коммиты: `27cb40e` (ws-probe), `2a7ecd2` (HISTORY). Пуш НЕ делался (не просили). **Инструкция для deck-UI («Простой HTTP контейнер»):** - Образ: **`naeel/iot-ws-probe:latest`** — стабильный путь БЕЗ уникального тега. ⛔ ПРАВИЛО (от пользователя): в deck-UI путь к образу фиксируется при создании и НЕ редактируется — с тегом `:v0.1.0` мы не смогли бы поменять версию. Обновление версии — новым пушем в `latest` + redeploy. ⚠️ Оговорка: зеркало платформы кэширует `latest` (случай shared-sqs) — если redeploy подтянет старый digest, запасной путь: `kubectl set image deployment/containerk8s app=naeel/iot-ws-probe:<новый-уникальный-тег>`. - Env vars: не нужны (порт 8080 — дефолт; при необходимости `PORT`). - Никаких кредов не требуется. **Критерии проверки wss после деплоя** (будут применены): - `curl -i -H "Connection: Upgrade" -H "Upgrade: websocket" ...` → 101; - `wscat -c wss://<домен>/ws` → подключение, echo, соединение живёт 5–10 мин; - переподключения стабильны; ping/pong проходят. **Следующий шаг:** пользователь создаёт контейнер в deck-UI с этим образом — далее тест wss по критериям выше. --- ## 8. Контейнер задеплоен в deck-UI — тест wss (16.08, ~07:26 GMT+03) **Контейнер:** `https://testiot.containerk8s.dev.nubes.ru/` (создан пользователем в deck-UI, образ `naeel/iot-ws-probe:latest`). **Результаты проверок (первые):** 1. `GET /health` → `{"status":"ok","version":"v0.1.0"}` — под стянул наш образ. 2. `GET /` → HTML-страница ws-probe (200). 3. **WebSocket upgrade через платформенный ingress → `HTTP/1.1 101 Switching Protocols`**, `Sec-WebSocket-Accept` корректный, HSTS на месте. (В выводе curl первая строка `HTTP/1.1 200 Connection established` — локальный CONNECT-прокси машины, ответ 101 пришёл от платформы.) 4. **`wscat -c wss://.../ws -x "probe-echo-1"` → echo вернулось, exit 0.** Двусторонний обмен работает. **КЛЮЧЕВОЙ ВЫВОД:** платформа Nubes («Простой HTTP контейнер») пропускает WebSocket upgrade — wss для устройств возможен, путь контейнера подтверждён. **Длительный тест стабильности** (запущен 08:26:10 по `date` = 07:26 GMT+03): - скрипт `/tmp/ws-stability-test.py`: соединение 10 мин, echo каждые 10с, ping/pong обе стороны (клиент ping_interval=25, сервер ping 20с), лог с таймстемпами. Результат будет дописан ниже.