diff --git a/2026-08-13-migration-to-managed.md b/2026-08-13-migration-to-managed.md new file mode 100644 index 0000000..960487c --- /dev/null +++ b/2026-08-13-migration-to-managed.md @@ -0,0 +1,224 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ план миграции (Node.js). ОТМЕНЁН. НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + +# Миграция IoT из Kubernetes → Managed Services (Nubes) +## Сессия 2026-08-13 + +--- + +## 1. Что изучили — текущая архитектура + +### Стек +- **Язык:** Go 1.25 +- **Паттерн:** Kubernetes Operator (controller-runtime) +- **Модуль:** `gitea.services.ngcloud.ru/Nail/IoT` +- **Docker Hub:** `naeel/iot-operator:v0.2.6` + +### Три бинарника в одном образе +| Бинарник | Роль | +|---|---| +| `cmd/iot-operator` | Controller-manager (CRD IoTDevice) + REST API :9090 | +| `cmd/mqtt-bridge` | MQTT (EMQX) → shared-SQS (AWS SDK v2) | +| `cmd/sqs-consumer` | shared-SQS → per-tenant Postgres | + +### Поток данных (текущий) +``` +IoT Device (MQTT CONNECT, username="{ns}_{deviceId}") + ↓ +EMQX 5.5.1 (HTTP auth/acl → iot-operator:9090/internal/mqtt/auth) + ↓ MQTT PUBLISH "{ns}/telemetry/{deviceId}" +iot-mqtt-bridge (подписка "+/telemetry/+") + ↓ AWS SDK SQS SendMessage +shared-SQS (namespace shared-sqs, очередь "iot-telemetry") + ↓ long polling (WaitTimeSeconds=20) +iot-sqs-consumer (at-least-once, DeleteMessage после успешной записи) + ↓ +Managed PostgreSQL 17 (per-tenant DB: tenant_{namespace}) + ↓ +REST API (iot-operator:9090) → Пользователь (UI/Terraform) +``` + +### Ключевые компоненты k8s +- **CRD IoTDevice** (`iot.kube5s.ru/v1alpha1`) — регистрация устройств +- **k8s Secret** `iot-{deviceId}` — хранит MQTT пароль (64 hex, crypto/rand) +- **OwnerReference** — каскадное удаление Secret при удалении IoTDevice +- **RBAC** — ClusterRole для чтения/записи IoTDevice + Secrets +- **Namespace = ID тенанта** — изоляция устройств и данных + +### Мультитенантность +- MQTT topic изоляция: `{ns}/telemetry/{deviceId}` — ACL на уровне EMQX +- Per-tenant Postgres DB: `tenant_{namespace}` (дефисы → подчёркивания) +- MQTT username: `{namespace}_{deviceId}` — глобально уникален +- `sync.Map` кэш `*sql.DB` per tenant — lazy init + +### Наблюдения / потенциальные проблемы +1. **`authTestMode = true`** в `middleware/auth.go` — тестовый режим включён в проде, JWT подпись не проверяется +2. **`ADMIN_STATS_TOKEN = "iot-admin-2026"`** захардкожен в YAML манифесте вместо Secret +3. Устаревшие файлы: `deployments/k8s/kafka.yaml`, `iot-kafka-consumer.yaml` (Kafka удалена, манифесты остались) +4. Bridge clientID `"sless-iot-bridge"` захардкожен и в bridge коде и в ACL логике +5. `examples/main.tf` и `handler.py` описывают устаревший поток (RabbitMQ/serverless) + +--- + +## 2. Почему хотим уйти из k8s + +- Цель: использовать только **managed services** облака Nubes +- Nubes предоставляет: **Managed Node.js, Flask, Lucee, PostgreSQL** +- Никаких VPS, никакого k8s — только managed-платформа +- SQS тоже **наш собственный сервис** (не сторонний облачный), работает сейчас в k8s, тоже надо вынести + +--- + +## 3. Принятые решения + +### Node.js — выбранный стек +| Задача | Node.js | +|---|---| +| REST API | Express/Fastify | +| MQTT-брокер | `aedes` (embedded, over WebSocket) | +| MQTT-клиент для publish | `mqtt` npm | +| SQS клиент | `@aws-sdk/client-sqs` | +| Postgres | `pg` npm | + +**Почему не Flask:** сложнее держать persistent MQTT и SQS polling в фоне +**Почему не Lucee:** не подходит для long-running background workers +**Почему Node.js — монолит:** bridge и consumer нельзя масштабировать независимо (один MQTT-клиент = одна подписка), смысла разделять нет + +### EMQX → aedes (embedded в Node.js) +- Managed Node.js открывает только HTTP/HTTPS порты +- MQTT over WebSocket = HTTP upgrade → работает на любой managed-платформе +- Устройства подключаются через `wss://` (уже сейчас так, через ingress emqx-ws-ingress.yaml) +- **aedes** — полноценный MQTT-брокер на Node.js, встраивается в Express HTTP-сервер +- Auth/ACL становится обычной функцией внутри того же процесса (быстрее, проще) + +### Мультитенантность сохраняется полностью +- `namespace` — просто строка в таблице `iot_devices` вместо k8s namespace +- Per-tenant Postgres DB остаётся (чистый SQL, без k8s) +- MQTT topic изоляция остаётся (`{ns}/telemetry/{deviceId}`) +- ACL по топику остаётся — просто функция вместо HTTP endpoint + +### k8s CRD/Secret → таблица в Postgres +```sql +CREATE TABLE iot_devices ( + namespace TEXT NOT NULL, + name TEXT NOT NULL, + device_id TEXT NOT NULL, + enabled BOOLEAN NOT NULL DEFAULT true, + mqtt_password TEXT NOT NULL, -- было в k8s Secret + metadata JSONB, + phase TEXT, + created_at TIMESTAMPTZ DEFAULT now(), + PRIMARY KEY (namespace, device_id) +); +``` + +--- + +## 4. Итоговая архитектура на Nubes Managed + +``` +IoT Device (wss://iot.example.ru/mqtt) + ↓ +Managed Node.js — IoT сервис + ├── aedes MQTT-брокер (over WebSocket, порт :3000/mqtt) + │ auth/acl → функция → таблица iot_devices в PG + │ on publish → SQS SendMessage + ├── SQS consumer (long polling, фоновый setInterval/async loop) + │ → per-tenant Postgres (tenant_{namespace}) + └── REST API (Express) + GET/POST /v1/namespaces/{ns}/iot/devices + GET /v1/namespaces/{ns}/iot/telemetry + POST /internal/mqtt/auth (совместимость, опционально) + GET /console (embedded HTML) + GET /iot-admin/stats + ↓ +Managed Node.js — shared-SQS сервис ← другие сервисы тоже + ↓ +Managed PostgreSQL — IoT данные +``` + +### Два managed Node.js сервиса +| Сервис | Назначение | +|---|---| +| **shared-SQS** | AWS SQS-совместимая очередь, multi-tenant, HTTP API | +| **iot-service** | aedes MQTT + REST API + SQS consumer + PG | + +--- + +## 5. Порядок миграции + +### ⚠️ Сначала shared-SQS, потом IoT + +**Причина:** IoT зависит от SQS. SQS независим — мигрирует первым. + +``` +Шаг 1: Вынести shared-SQS из k8s → Managed Node.js на Nubes +Шаг 2: Переписать IoT сервис на Node.js (aedes + REST + consumer) +Шаг 3: Деплой IoT на Managed Node.js на Nubes +Шаг 4: Отключить k8s деплой IoT +``` + +--- + +## 6. Детали для нового чата — shared-SQS миграция + +### Что сейчас +- SQS сервис живёт в `namespace: shared-sqs` в кластере `iot-naeel` +- Endpoint: `https://qu.kube5s.ru` +- Multi-tenant: tenant `iot-service` (id: `t-96afe7e9f781f6ca`), очередь `iot-telemetry` +- IoT использует: `SQS_ENDPOINT=https://qu.kube5s.ru`, `SQS_ACCESS_KEY`, `SQS_SECRET_KEY` +- Протокол: AWS SQS-совместимый (SendMessage, ReceiveMessage, DeleteMessage, GetQueueUrl, GetQueueAttributes) + +### Что нужно от нового SQS сервиса +- AWS SQS-совместимый HTTP API (те же методы что сейчас) +- Multi-tenant (разные access key / secret key для разных тенантов) +- Очереди создаются по имени (`GetQueueUrl` + `CreateQueue`) +- Long polling: `ReceiveMessage` с `WaitTimeSeconds` до 20 +- Хранение сообщений: in-memory или Postgres/Redis + +### Клиенты SQS в IoT коде +1. **mqtt-bridge** (`cmd/mqtt-bridge/main.go`): `SendMessage` при каждом MQTT сообщении +2. **sqs-consumer** (`cmd/sqs-consumer/main.go`): `ReceiveMessage` (polling) + `DeleteMessage` +3. **iot-admin-stats** (`internal/api/handler/iot_admin_stats_handler.go`): `GetQueueAttributes` для мониторинга + +### Env vars для IoT → SQS +``` +SQS_ENDPOINT=https://qu.kube5s.ru (поменяется на новый managed URL) +SQS_ACCESS_KEY=... +SQS_SECRET_KEY=... +SQS_QUEUE_NAME=iot-telemetry (default) +SQS_REGION=us-east-1 (default, не важен для self-hosted) +``` + +--- + +## 7. Что переписывается в IoT (Node.js) + +### Соответствие Go → Node.js + +| Go файл | Node.js файл | +|---|---| +| `cmd/iot-operator/main.go` | `src/index.js` (точка входа) | +| `internal/api/router.go` | `src/routes.js` | +| `internal/api/handler/iot_device_handler.go` | `src/handlers/devices.js` | +| `internal/api/handler/iot_telemetry_handler.go` | `src/handlers/telemetry.js` | +| `internal/api/handler/iot_admin_stats_handler.go` | `src/handlers/admin.js` | +| `internal/api/middleware/auth.go` | `src/middleware/auth.js` | +| `internal/storage/iotpg/iot_telemetry_store.go` | `src/storage/pg.js` | +| `cmd/mqtt-bridge/main.go` | встроен в `src/mqtt.js` (aedes) | +| `cmd/sqs-consumer/main.go` | встроен в `src/sqsWorker.js` | +| `controllers/iotdevice_controller.go` | **не нужен** (заменён CRUD в БД) | +| `api/v1alpha1/device_types.go` | **не нужен** (таблица iot_devices) | + +### npm зависимости +```json +{ + "dependencies": { + "express": "^4", + "aedes": "^0.51", + "websocket-stream": "^5", + "@aws-sdk/client-sqs": "^3", + "pg": "^8", + "uuid": "^9" + } +} +``` diff --git a/HISTORY/2026-08-16-session-log.md b/HISTORY/2026-08-16-session-log.md index 14ca592..85ac160 100644 --- a/HISTORY/2026-08-16-session-log.md +++ b/HISTORY/2026-08-16-session-log.md @@ -391,6 +391,9 @@ deployment-v0.2.3; 9 вопросов; формат «Ответ/Рекомен ## 11. Статус старого деплоя IoT — «зомби» (проверено 16.08) +> ⛔⛔⛔ ЛЕГАСИ — НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ при принятии решений. Раздел оставлен +> только как фиксация факта. Старый IoT для миграции значения не имеет. + **Проверка по вопросу «старый прод жив?» (факты):** 1. ns `sless` жив (125d). Все 4 deployment'а Running: `emqx`, `iot-mqtt-bridge`, `iot-operator`, `iot-sqs-consumer` (поды 117–125 дней без рестартов). @@ -411,3 +414,29 @@ deployment-v0.2.3; 9 вопросов; формат «Ответ/Рекомен **Отмена теста:** wss-тест к старому домену бессмыслен — точки входа нет. Старый деплой можно выключать после переключения (или по команде пользователя — сейчас НЕ трогаем). + +--- + +## 12. Пометка ЛЕГАСИ всего, что относится к старому IoT (16.08) + +**Команда пользователя:** «УБЕРИ ВСЁ, что касается старого IoT; стирать пока +не надо; ЧЁТКО пропиши везде, что это ЛЕГАСИ и НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ». + +**Сделано:** +1. В шапку каждого файла старого IoT добавлена пометка + «⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT ... НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ»: + - 15 документов в `doc/` (кроме `doc/sqs-integration.md` — актуален); + - `2026-08-13-migration-to-managed.md` (старый Node.js-план — отменён); + - все 8 манифестов `deployments/k8s/`; + - `config/crd/bases/iot.kube5s.ru_iotdevices.yaml`; + - `cmd/iot-operator/main.go`, `controllers/iotdevice_controller.go`, + `api/v1alpha1/device_types.go`, `api/v1alpha1/groupversion_info.go`; + - `Makefile` (старые k8s-цели); + - `examples/` (README.md, main.tf, handler.py). +2. Создан корневой `LEGACY.md` — реестр: что легаси, что актуально. +3. Раздел 11 этого журнала помечен «НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ». +4. Удалений НЕ производилось. + +**Актуальные файлы (НЕ легаси):** `HISTORY/`, `doc/sqs-integration.md`, +`ws-probe/`, Go-код `cmd/mqtt-bridge/`, `cmd/sqs-consumer/`, `internal/` +(переиспользуется в монолите). diff --git a/LEGACY.md b/LEGACY.md new file mode 100644 index 0000000..042074e --- /dev/null +++ b/LEGACY.md @@ -0,0 +1,29 @@ +# ⛔⛔⛔ ЛЕГАСИ — СТАРЫЙ IoT (k8s-деплой) + +С 2026-08-16 всё, что относится к СТАРОМУ IoT (деплой в собственном k8s, +оператор, CRD), — **ЛЕГАСИ**. **НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ** при принятии решений. +Не использовать, не ссылаться, не переносить в новую архитектуру без отдельной +команды. + +**Актуальное:** +- `HISTORY/2026-08-16-session-log.md` — состояние, диагностика, план миграции +- `doc/sqs-integration.md` — актуальная интеграция с shared-sqs + +## Помечено ЛЕГАСИ (в шапке каждого файла) + +- `deployments/k8s/` — все k8s-манифесты старого деплоя (8 файлов) +- `config/crd/` — CRD IoTDevice +- `cmd/iot-operator/`, `controllers/`, `api/v1alpha1/` — оператор (CRD-контроллер); + в новой архитектуре не используется (замена — таблица `iot_devices` в PG) +- `doc/` — все документы, кроме `doc/sqs-integration.md` +- `examples/` — старые примеры (RabbitMQ/serverless) +- `2026-08-13-migration-to-managed.md` — СТАРЫЙ план миграции (Node.js) — ОТМЕНЁН +- `Makefile` — старые цели (k8s deploy/install-crd) не использовать + +## НЕ легаси (актуально) + +- `HISTORY/2026-08-16-session-log.md` +- `doc/sqs-integration.md` +- `ws-probe/` +- `cmd/mqtt-bridge/`, `cmd/sqs-consumer/`, `internal/` — Go-код, переиспользуется + в новом монолите (после адаптации под платформу) diff --git a/Makefile b/Makefile index d1f6746..f249e7a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). Цели deploy/install-crd не использовать. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-12 # Makefile для IoT managed service. diff --git a/api/v1alpha1/device_types.go b/api/v1alpha1/device_types.go index 73057d0..d6f9629 100644 --- a/api/v1alpha1/device_types.go +++ b/api/v1alpha1/device_types.go @@ -1,3 +1,6 @@ +// ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (CRD-типы). В новой архитектуре заменяется таблицей iot_devices в PG. +// Актуальное: HISTORY/2026-08-16-session-log.md + // Создано: 2026-04-04 // Описание CRD IoTDevice — регистрация IoT-устройства в платформе sless. // Пользователь создаёт IoTDevice, контроллер автоматически генерирует MQTT-credentials diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go index a89d39e..48e5674 100644 --- a/api/v1alpha1/groupversion_info.go +++ b/api/v1alpha1/groupversion_info.go @@ -1,3 +1,6 @@ +// ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (CRD-типы). В новой архитектуре не используется. +// Актуальное: HISTORY/2026-08-16-session-log.md + // Создано: 2026-04-04 // groupversion_info.go — регистрация API group iot.kube5s.ru/v1alpha1. // ВАЖНО: группа намеренно отдельная от sless.kube5s.ru — при выносе IoT в diff --git a/cmd/iot-operator/main.go b/cmd/iot-operator/main.go index 908b57c..252220f 100644 --- a/cmd/iot-operator/main.go +++ b/cmd/iot-operator/main.go @@ -1,3 +1,6 @@ +// ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (оператор, CRD-контроллер). В новой архитектуре не используется. +// Актуальное: HISTORY/2026-08-16-session-log.md + // Создано: 2026-04-12 // main.go — точка входа IoT managed service. // Запускает controller-manager (IoTDevice CRD) и REST API сервер (порт 9090) в одном процессе. @@ -92,9 +95,9 @@ func main() { // REST API handler h := &handler.Handler{ - K8s: mgr.GetClient(), - Scheme: mgr.GetScheme(), - IoTPG: iotPGStore, + K8s: mgr.GetClient(), + Scheme: mgr.GetScheme(), + IoTPG: iotPGStore, Log: log, BridgeUsername: os.Getenv("MQTT_BRIDGE_USERNAME"), BridgePassword: os.Getenv("MQTT_BRIDGE_PASSWORD"), diff --git a/config/crd/bases/iot.kube5s.ru_iotdevices.yaml b/config/crd/bases/iot.kube5s.ru_iotdevices.yaml index 45ad7e5..613ffa7 100644 --- a/config/crd/bases/iot.kube5s.ru_iotdevices.yaml +++ b/config/crd/bases/iot.kube5s.ru_iotdevices.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (CRD/k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/controllers/iotdevice_controller.go b/controllers/iotdevice_controller.go index 2e63c79..10838e9 100644 --- a/controllers/iotdevice_controller.go +++ b/controllers/iotdevice_controller.go @@ -1,3 +1,6 @@ +// ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (CRD-контроллер). В новой архитектуре не используется. +// Актуальное: HISTORY/2026-08-16-session-log.md + // Создано: 2026-04-04 // iotdevice_controller.go — контроллер IoTDevice CRD. // Логика Reconcile: diff --git a/deployments/k8s/emqx-ws-ingress.yaml b/deployments/k8s/emqx-ws-ingress.yaml index 2ac0240..01fb4df 100644 --- a/deployments/k8s/emqx-ws-ingress.yaml +++ b/deployments/k8s/emqx-ws-ingress.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-12 # MQTT over WebSocket через Ingress с TLS termination. # Причина: порт 1883 заблокирован NSX-T Edge firewall на уровне облака. diff --git a/deployments/k8s/emqx.yaml b/deployments/k8s/emqx.yaml index eb9a391..3a01408 100644 --- a/deployments/k8s/emqx.yaml +++ b/deployments/k8s/emqx.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-12 # EMQX MQTT-брокер для IoT-сервиса (namespace: sless). # diff --git a/deployments/k8s/iot-kafka-consumer.yaml b/deployments/k8s/iot-kafka-consumer.yaml index 7a8c42b..e953117 100644 --- a/deployments/k8s/iot-kafka-consumer.yaml +++ b/deployments/k8s/iot-kafka-consumer.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой, Kafka). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-06 # Deployment iot-kafka-consumer — читает IoT телеметрию из Kafka → пишет в IoT Postgres. # diff --git a/deployments/k8s/iot-mqtt-bridge.yaml b/deployments/k8s/iot-mqtt-bridge.yaml index 779a50a..bd906dc 100644 --- a/deployments/k8s/iot-mqtt-bridge.yaml +++ b/deployments/k8s/iot-mqtt-bridge.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-04 # Изменено: 2026-04-12 (замена Kafka → shared-SQS) # Deployment iot-mqtt-bridge — MQTT→SQS мост для IoT. diff --git a/deployments/k8s/iot-operator.yaml b/deployments/k8s/iot-operator.yaml index 0e4cb1a..c3e1216 100644 --- a/deployments/k8s/iot-operator.yaml +++ b/deployments/k8s/iot-operator.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-12 # Deployment iot-operator — controller-manager (IoTDevice CRD) + REST API на :9090. # diff --git a/deployments/k8s/iot-postgres.yaml b/deployments/k8s/iot-postgres.yaml index 9f3edb9..68b8ffd 100644 --- a/deployments/k8s/iot-postgres.yaml +++ b/deployments/k8s/iot-postgres.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-05 # Изменено: 2026-04-12 (заменён self-hosted на managed Postgres через оператор) # diff --git a/deployments/k8s/iot-sqs-consumer.yaml b/deployments/k8s/iot-sqs-consumer.yaml index ca93981..c2fbb89 100644 --- a/deployments/k8s/iot-sqs-consumer.yaml +++ b/deployments/k8s/iot-sqs-consumer.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-12 # Deployment iot-sqs-consumer — читает IoT телеметрию из shared-SQS → пишет в IoT Postgres. # diff --git a/deployments/k8s/kafka.yaml b/deployments/k8s/kafka.yaml index daa02dd..4635dcf 100644 --- a/deployments/k8s/kafka.yaml +++ b/deployments/k8s/kafka.yaml @@ -1,3 +1,6 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой, Kafka). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. +# Актуальное: HISTORY/2026-08-16-session-log.md + # Изменено: 2026-04-06 (добавлен postStart hook для предсоздания топика iot.telemetry) # kafka.yaml — минимальный деплой Apache Kafka в KRaft mode (без Zookeeper). # Образ: apache/kafka (официальный, бесплатный). diff --git a/doc/api/endpoints-v0.2.3.md b/doc/api/endpoints-v0.2.3.md index fdd642d..50c64ed 100644 --- a/doc/api/endpoints-v0.2.3.md +++ b/doc/api/endpoints-v0.2.3.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT REST API — Полная документация (v0.2.3) > Дата: 2026-04-12 diff --git a/doc/api/endpoints.md b/doc/api/endpoints.md index b64d1c4..3c0daec 100644 --- a/doc/api/endpoints.md +++ b/doc/api/endpoints.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT API Endpoints ## Публичные (без auth) diff --git a/doc/architecture/current-v0.2.3.md b/doc/architecture/current-v0.2.3.md index e7062c7..4db4a70 100644 --- a/doc/architecture/current-v0.2.3.md +++ b/doc/architecture/current-v0.2.3.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT Managed Service — Актуальная архитектура (v0.2.3) > Дата: 2026-04-12 diff --git a/doc/architecture/overview.md b/doc/architecture/overview.md index 7454e7c..04cc8fa 100644 --- a/doc/architecture/overview.md +++ b/doc/architecture/overview.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT Managed Service — Архитектура ## Общая схема diff --git a/doc/decisions/2026-04-12-replace-kafka-with-sqs.md b/doc/decisions/2026-04-12-replace-kafka-with-sqs.md index c5a74e0..26188d2 100644 --- a/doc/decisions/2026-04-12-replace-kafka-with-sqs.md +++ b/doc/decisions/2026-04-12-replace-kafka-with-sqs.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # Решение: замена Kafka на shared-SQS **Дата:** 2026-04-12 diff --git a/doc/decisions/2026-04-12-separate-repo.md b/doc/decisions/2026-04-12-separate-repo.md index 90cbfaa..c25cdcb 100644 --- a/doc/decisions/2026-04-12-separate-repo.md +++ b/doc/decisions/2026-04-12-separate-repo.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # Решение: Вынос IoT в отдельную репу **Дата:** 2026-04-12 diff --git a/doc/deployment-v0.2.3.md b/doc/deployment-v0.2.3.md index 591dee7..2e06a37 100644 --- a/doc/deployment-v0.2.3.md +++ b/doc/deployment-v0.2.3.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT Managed Service — Актуальный деплой (v0.2.3) > Дата: 2026-04-12 diff --git a/doc/deployment.md b/doc/deployment.md index 6b2dc5a..c56bd65 100644 --- a/doc/deployment.md +++ b/doc/deployment.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT MVP — Инженерная документация деплоя > Создано: 2026-04-04 diff --git a/doc/iot-mvp-plan.md b/doc/iot-mvp-plan.md index 3c12526..66d9b24 100644 --- a/doc/iot-mvp-plan.md +++ b/doc/iot-mvp-plan.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT MVP — План реализации для Sonnet > **Автор плана**: GitHub Copilot (Claude Opus 4.6) diff --git a/doc/progress.md b/doc/progress.md index fff4fdc..f0bb8c1 100644 --- a/doc/progress.md +++ b/doc/progress.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT Managed Service — Трекер прогресса ## 2026-04-12: Перенос из sless в отдельную репу diff --git a/doc/run-and-test.md b/doc/run-and-test.md index a23d664..b99a780 100644 --- a/doc/run-and-test.md +++ b/doc/run-and-test.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT — Руководство по запуску и тестированию (v0.2.3) > Дата: 2026-04-12 diff --git a/doc/sqs-integration.md b/doc/sqs-integration.md new file mode 100644 index 0000000..8521079 --- /dev/null +++ b/doc/sqs-integration.md @@ -0,0 +1,70 @@ +# Интеграция IoT ↔ shared-sqs: состояние и рекомендации + +> Составлено 2026-08-16 на основе работ по сервису shared-sqs (SQS-совместимая +> очередь на платформе Nubes). IoT будет использовать shared-sqs так же, как +> сам shared-sqs использует managed-сервисы платформы. + +## 1. Что такое shared-sqs (кратко) + +- SQS-совместимая очередь (AWS API), Go, multi-tenant, форк GoAWS. +- Версия на проде: **v0.1.35**. +- Внешний 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` +- Реализовано: CreateQueue, GetQueueUrl, ListQueues, SendMessage(+Batch), + ReceiveMessage, DeleteMessage(+Batch), ChangeMessageVisibility(+Batch), + PurgeQueue, DeleteQueue, Get/SetQueueAttributes, TagQueue/Untag/List, + FIFO (порядок + dedup 5 мин), Dead Letter Queues (RedrivePolicy). +- Лимиты: 50 очередей на тенанта, сообщение до 256 КБ, Receive 1–10 сообщений. + +## 2. Что сделано и проверено (состояние на 16.08) + +- Все тесты зелёные: api_test 22/22, sdk_test 15/15, FIFO/DLQ e2e PASS. +- План проверок выполнен полностью (таймауты сервера, рестарты, long-poll, + CLI в нагрузке, память 2ч, граница лимита 50). +- Нагрузка: 168 591 операция без единой сервисной ошибки. +- Сравнение с Yandex YMQ: shared-sqs быстрее (p50 6–8мс из внутренней сети, + 89–90мс из интернета против 60–62мс / 138–150мс у YMQ). + +## 3. Известные проблемы ПЛАТФОРМЫ (не сервиса) + +1. **Таймауты каждые 31–33с на внешнем пути** (интернет → шлюз Nubes): ~5.5% + запросов не получают ответ 30с. Доказано серверным tcpdump: в момент сбоя + запрос не доходит до пода; внутри кластера потерь нет (port-forward — + 24977 раундов, 0 сбоев). Тикет в поддержку Nubes подготовлен. +2. **MSS=1448** на шлюзе при MTU пода 1400/underlay 1450: тела >~1400 байт + могут виснуть ~51с (PMTUD сломан). + +## 4. Рекомендации по интеграции IoT → shared-sqs + +1. **Использовать AWS SDK** (aws-sdk-go или boto3) с переопределением + endpoint'а. Не писать свой HTTP-клиент. +2. **Ходить по внутренней сети, если IoT на Nubes в том же кластере:** + внутренний URL из п.1 полностью обходит проблемный внешний шлюз — + таймаутов 31–33с и MTU-проблем там нет. Это главная рекомендация. +3. **Клиентские ретраи обязательны:** retries ≥ 3, read_timeout ≥ 30с + (для внешнего пути). При внутреннем пути достаточно дефолтов. +4. **Размер сообщений:** до ~1300 байт — безопасно всегда; большие тела — + только после фикса MSS шлюзом, либо бить на части. +5. **Receive:** VisibilityTimeout ставьте с запасом на обработку (30с+); + `ChangeMessageVisibility(0)` — мгновенный возврат в очередь; long-poll + (WaitTimeSeconds) поддерживается. +6. **FIFO:** обязателен `MessageGroupId`; dedup-окно 5 минут; порядок + гарантирован внутри группы. +7. **DLQ:** настраивается RedrivePolicy (`deadLetterTargetArn`, + `maxReceiveCount`); ARN DLQ должен быть tenant-scoped (как в тестах). +8. **Лимит:** 50 очередей на тенанта — держать список очередей под контролем. +9. **Мониторинг:** `/health` отдаёт `{"status":"ok","version":...}`; + метрики платформы — Grafana (как для остальных managed-сервисов). + +## 5. Аутентификация + +- Креды тенанта детерминированы: tenantID `t-`+sha256(email)[:8], + AccessKey `SSAK-`+sha256(email)[:12], + SecretKey sha256(email+":shared-sqs:secret-key:v1"). +- IoT получит свой тенант/креды через консоль Nubes (как другие сервисы). + +## 6. Что осталось до полного прода + +- Отправить тикет Nubes (таймауты шлюза + MSS) — единственный блокер для + интернет-клиентов. Для внутренней интеграции IoT блокеров нет. diff --git a/doc/testing-v0.2.6.md b/doc/testing-v0.2.6.md index 890dd21..a2c5d91 100644 --- a/doc/testing-v0.2.6.md +++ b/doc/testing-v0.2.6.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT — Отчёт по тестированию v0.2.5 / v0.2.6 > Дата: 2026-04-21 diff --git a/doc/thinking/2026-04-12.md b/doc/thinking/2026-04-12.md index 7b1ed3f..d8fad3c 100644 --- a/doc/thinking/2026-04-12.md +++ b/doc/thinking/2026-04-12.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (k8s-деплой). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # 2026-04-12 — GitHub Copilot (Claude Opus 4.6) ## Задача diff --git a/examples/README.md b/examples/README.md index ebd4ec3..7d4e6d4 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,3 +1,5 @@ +> ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (RabbitMQ/serverless). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # IoT MVP — E2E Demo ## Что делает этот пример diff --git a/examples/handler.py b/examples/handler.py index f50b0a1..41fa017 100644 --- a/examples/handler.py +++ b/examples/handler.py @@ -1,3 +1,4 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (RabbitMQ/serverless). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md """ Создано: 2026-04-04 handler.py — обработчик IoT-телеметрии для демонстрации IoT MVP. diff --git a/examples/main.tf b/examples/main.tf index bb1386f..a793b1c 100644 --- a/examples/main.tf +++ b/examples/main.tf @@ -1,3 +1,5 @@ +# ⛔⛔⛔ ЛЕГАСИ (2026-08-16) — СТАРЫЙ IoT (RabbitMQ/serverless). НЕ ПРИНИМАТЬ ВО ВНИМАНИЕ. Актуальное: HISTORY/2026-08-16-session-log.md + # Создано: 2026-04-04 # E2E Demo: IoT Device → MQTT → RabbitMQ → Serverless Function #