Files
IoT/HISTORY/2026-08-16-session-log.md
T

13 KiB
Raw Blame History

Журнал сессии — 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.<uuid-inst>.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.<uuid>.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с), лог с таймстемпами. Результат будет дописан ниже.