Files
IoT/doc/deployment-v0.2.3.md
T
Naeel 907aaad100 docs: полная документация v0.2.3 — архитектура, API, деплой, тестирование
Новые файлы:
- doc/architecture/current-v0.2.3.md — актуальная архитектура
- doc/api/endpoints-v0.2.3.md — полная документация REST API
- doc/deployment-v0.2.3.md — инструкция деплоя v0.2.3
- doc/run-and-test.md — руководство по запуску и E2E тесту

Обновлено:
- doc/progress.md — секция документации
- doc/thinking/2026-04-12.md — лог мышления
2026-04-12 18:36:12 +03:00

9.7 KiB
Raw Blame History

IoT Managed Service — Актуальный деплой (v0.2.3)

Дата: 2026-04-12 Образ: naeel/iot-operator:v0.2.3 Ветка: feature/replace-kafka-with-sqs Кластер: iot-naeel Автор: GitHub Copilot (Claude Opus 4.6)


Обзор

Три бинарника из одного Docker-образа naeel/iot-operator:v0.2.3:

Бинарник Deployment Назначение
/iot-operator iot-operator Controller-manager (IoTDevice CRD) + REST API :9090
/mqtt-bridge iot-mqtt-bridge MQTT (EMQX) → shared-SQS bridge
/sqs-consumer iot-sqs-consumer shared-SQS → Postgres pipeline

Плюс:

  • EMQX 5.5.1 — MQTT-брокер (отдельный образ emqx/emqx:5.5.1)

Кластер

Параметр Значение
Имя iot-naeel
API https://185.247.187.149:6443
Ingress IP 185.247.187.151
DNS iot.kube5s.ru → 185.247.187.147
Namespace sless
kubeconfig ~/.kube/config на ВМ (токен 24ч, обновлять через auth.k8s.ngcloud.ru)

Секреты (namespace sless)

Перед первым деплоем создать 3 секрета:

1. iot-bridge-credentials (MQTT bridge → EMQX)

kubectl create secret generic iot-bridge-credentials -n sless \
  --from-literal=MQTT_USERNAME="iot-bridge-internal" \
  --from-literal=MQTT_PASSWORD="<пароль bridge>"

Используется:

  • iot-operator — для проверки bridge auth в /internal/mqtt/auth (env: MQTT_BRIDGE_USERNAME, MQTT_BRIDGE_PASSWORD)
  • iot-mqtt-bridge — для подключения к EMQX (envFrom: secretRef)

2. iot-sqs-credentials (shared-SQS)

kubectl create secret generic iot-sqs-credentials -n sless \
  --from-literal=SQS_ENDPOINT="https://qu.kube5s.ru" \
  --from-literal=SQS_ACCESS_KEY="SSAK-a9964f2723bc6d347f48d153" \
  --from-literal=SQS_SECRET_KEY="<secret_key>"

Используется:

  • iot-mqtt-bridge — для SendMessage
  • iot-sqs-consumer — для ReceiveMessage + DeleteMessage

3. iot-postgres-secret (Managed PostgreSQL)

kubectl create secret generic iot-postgres-secret -n sless \
  --from-literal=IOT_PG_DSN="postgres://super:<password>@postgresqlk8s-master.dc5db45d-f8b4-4fd0-ad33-ec4dd017f2d5.svc.cluster.local:5432/sqsdb?sslmode=disable"

Используется:

  • iot-sqs-consumer — для записи телеметрии в per-tenant DB

Процедура деплоя (пошагово)

Все команды выполнять на ВМ через SSH

ssh -i ~/.ssh/id_ed25519 naeel@5.172.178.213
cd /home/naeel/terra/IoT

0. Сборка образа (если код менялся)

docker build --no-cache -t naeel/iot-operator:v0.2.3 .
docker push naeel/iot-operator:v0.2.3

1. CRD (один раз, cluster-wide)

kubectl apply -f config/crd/bases/iot.kube5s.ru_iotdevices.yaml

2. EMQX

kubectl apply -f deployments/k8s/emqx.yaml
kubectl apply -f deployments/k8s/emqx-ws-ingress.yaml

3. Postgres secret (один раз)

kubectl apply -f deployments/k8s/iot-postgres.yaml

4. SQS secret (один раз)

kubectl get secret iot-sqs-credentials -n sless
# Если нет — создать (см. секцию Секреты выше)

5. Bridge credentials (один раз)

kubectl get secret iot-bridge-credentials -n sless
# Если нет — создать (см. секцию Секреты выше)

6. Operator

kubectl apply -f deployments/k8s/iot-operator.yaml
kubectl rollout status deployment/iot-operator -n sless

7. MQTT Bridge

kubectl apply -f deployments/k8s/iot-mqtt-bridge.yaml
kubectl rollout status deployment/iot-mqtt-bridge -n sless

8. SQS Consumer

kubectl apply -f deployments/k8s/iot-sqs-consumer.yaml
kubectl rollout status deployment/iot-sqs-consumer -n sless

9. Проверка

kubectl get pods -n sless
# Ожидаемый результат:
# emqx-xxx              1/1 Running
# iot-operator-xxx      1/1 Running
# iot-mqtt-bridge-xxx   1/1 Running
# iot-sqs-consumer-xxx  1/1 Running

kubectl logs -n sless deployment/iot-operator --tail=5
kubectl logs -n sless deployment/iot-mqtt-bridge --tail=5
kubectl logs -n sless deployment/iot-sqs-consumer --tail=5

Обновление образа (rollout)

# 1. Собрать новый образ
docker build --no-cache -t naeel/iot-operator:v0.2.4 .
docker push naeel/iot-operator:v0.2.4

# 2. Обновить тег во ВСЕХ трёх YAML
sed -i 's/v0.2.3/v0.2.4/g' deployments/k8s/iot-operator.yaml \
  deployments/k8s/iot-mqtt-bridge.yaml \
  deployments/k8s/iot-sqs-consumer.yaml

# 3. Применить
kubectl apply -f deployments/k8s/iot-operator.yaml
kubectl apply -f deployments/k8s/iot-mqtt-bridge.yaml
kubectl apply -f deployments/k8s/iot-sqs-consumer.yaml

# 4. Проверить
kubectl get pods -n sless -w

ВАЖНО: Если образ с тем же тегом — Kubernetes не скачает новый (кэш на нодах). Всегда менять тег.


Компоненты: env vars

iot-operator

Переменная Значение Источник
MQTT_BRIDGE_USERNAME iot-bridge-internal Secret iot-bridge-credentials (key: MQTT_USERNAME)
MQTT_BRIDGE_PASSWORD (пароль) Secret iot-bridge-credentials (key: MQTT_PASSWORD)

iot-mqtt-bridge

Переменная Значение Источник
MQTT_BROKER_URL tcp://emqx.sless.svc:1883 YAML env
SQS_QUEUE_NAME iot-telemetry YAML env
SQS_REGION us-east-1 YAML env
MQTT_USERNAME iot-bridge-internal Secret iot-bridge-credentials
MQTT_PASSWORD (пароль) Secret iot-bridge-credentials
SQS_ENDPOINT https://qu.kube5s.ru Secret iot-sqs-credentials
SQS_ACCESS_KEY SSAK-... Secret iot-sqs-credentials
SQS_SECRET_KEY (secret) Secret iot-sqs-credentials

iot-sqs-consumer

Переменная Значение Источник
SQS_QUEUE_NAME iot-telemetry YAML env
SQS_REGION us-east-1 YAML env
SQS_ENDPOINT https://qu.kube5s.ru Secret iot-sqs-credentials
SQS_ACCESS_KEY SSAK-... Secret iot-sqs-credentials
SQS_SECRET_KEY (secret) Secret iot-sqs-credentials
IOT_PG_DSN postgres://... Secret iot-postgres-secret

Managed PostgreSQL

Параметр Значение
Версия PostgreSQL 17
Host postgresqlk8s-master.dc5db45d-f8b4-4fd0-ad33-ec4dd017f2d5.svc.cluster.local
Port 5432
User super
DB sqsdb
Тип Managed (оператор в другом namespace)

Per-tenant изоляция: для каждого namespace создаётся отдельная DATABASE tenant_{namespace} с таблицей iot_telemetry.


shared-SQS (очередь)

Параметр Значение
Endpoint https://qu.kube5s.ru
Tenant iot-service (ID: t-96afe7e9f781f6ca)
Очередь iot-telemetry
Протокол AWS SQS API (AWS SDK compatible)

Версии образов (история)

Версия Дата Изменения
v0.2.3 2026-04-12 Bridge auth fix (BridgeUsername/BridgePassword), debug logs
v0.2.2 2026-04-12 Bridge auth (первая попытка, проблема с табами)
v0.2.1 2026-04-12 Bridge auth (проблема IsSuperuser field)
v0.2.0 2026-04-12 Kafka->SQS, managed PG, новый кластер iot-naeel
v0.1.69 2026-04-06 Kafka Async write fix (1000/1000 тест)
v0.1.68 2026-04-06 Kafka pipeline (bridge->Kafka->consumer->Postgres)
v0.1.50 2026-04-04 Первый IoT: controller + API + mqtt-bridge (RabbitMQ)

Известные ошибки и решения (v0.2.x)

mqtt-bridge: MQTT connect timeout / CrashLoopBackOff

Симптом: bridge не подключается к EMQX, логи "MQTT connect timeout"

Причина: EMQX вызывает /internal/mqtt/auth при CONNECT. Bridge username iot-bridge-internal не содержит _ -> MQTTAuth парсит namespace_deviceId -> ошибка -> deny -> EMQX возвращает not_authorized -> bridge retry 30с -> выглядит как timeout.

Решение (v0.2.3): В Handler добавлены поля BridgeUsername/BridgePassword. MQTTAuth проверяет bridge credentials ДО парсинга namespace_deviceId. Если username совпадает — allow.

Docker image cache на k8s нодах

Симптом: после docker push новый образ не используется, pod стартует со старым кодом.

Причина: imagePullPolicy=Always работает, но если тег не изменился Kubernetes может использовать кэш ноды.

Решение: Всегда менять тег при пересборке (v0.2.1 -> v0.2.2 -> v0.2.3 и т.д.)

EMQX: required_field node.cookie/node.data_dir

Симптом: EMQX CrashLoopBackOff при первом старте

Причина: EMQX 5.x требует явных node.cookie и node.data_dir

Решение: В emqx.conf (ConfigMap) обязательны:

node { name = "emqx@127.0.0.1", cookie = "...", data_dir = "/opt/emqx/data" }

После изменения ConfigMap: kubectl rollout restart deployment/emqx -n sless