From e1804c9b97a37dbb49add06cac2697d39825bb33 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Sun, 11 Oct 2026 19:21:12 +0300 Subject: [PATCH] =?UTF-8?q?fix(deploy):=20MQTT=5FHOST=20=3D=20containerk8s?= =?UTF-8?q?.=20(=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=20=D0=BF=D0=BB?= =?UTF-8?q?=D0=B0=D1=82=D1=84=D0=BE=D1=80=D0=BC=D1=8B=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B7=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20?= =?UTF-8?q?resource=5Fname)=20+=20=D1=80=D0=B0=D0=B7=D0=B1=D0=BE=D1=80=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20iot-service=20(PG:?= =?UTF-8?q?=20=D0=B2=D0=BB=D0=B0=D0=B4=D0=B5=D0=BB=D0=B5=D1=86=20=D1=82?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=B8=D1=86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HISTORY/2026-10-11-session-log.md | 55 +++++++++++++++++++++++++++++++ deploy/terraform/resources.tf | 10 ++++-- doc/nubes-deploy-checklist.md | 13 +++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/HISTORY/2026-10-11-session-log.md b/HISTORY/2026-10-11-session-log.md index fd2f451..25b1a72 100644 --- a/HISTORY/2026-10-11-session-log.md +++ b/HISTORY/2026-10-11-session-log.md @@ -91,3 +91,58 @@ остался в состоянии `not created` после неудачного apply и держит имя. По документации платформы такие инстансы через API не удаляются — удалять вручную в ЛК (deck). `terraform state list` пуст (в state ничего не записалось). + +## 6. Второй `terraform apply` — падение iot-service и РАЗБОР через кластер + +Инстанс-блокер был удалён в ЛК владельцем (`3bdaef8e…` → 404). Повторный apply: +EMQX создался и работает, `nubes_http.iot_service` упал через ~10 мин: +`Приложение не запустилось. Производится полный откат установки. Ошибка: +jlib.k8s [correctReplicaActive] | Под(ы) не работают: 'containerk8s' (Deployment)`, +затем таймаут клиента 600 с. Namespace iot-service откатан и удалён. + +Разбор (kubeconfig `~/.kube/config` → кластер `iot-naeel`, контекст +`tazetdinovn@gmail.com@iot-naeel`): + +1. **Причина падения — PG, а не образ.** Эфемерный диагностический под + (`kubectl run iot-diag-bad`, env — как в tfvars, удалён после проверки): + ``` + level=ERROR msg="devices store" err="store: init schema: pq: must be owner of table iot_devices (42501)" + exit=1 reason=Error + ``` + Приложение падает на `CREATE UNIQUE INDEX IF NOT EXISTS` (`internal/service/store/open.go:64` + + SQL на `:29`): таблица уже существует и принадлежит ДРУГОЙ роли. +2. **Владелец.** В БД `iotdb` инстанса `509145c3…` таблицы `iot_devices`, + `iot_devices_pkey`, `idx_iot_devices_ns_device`, `tenant_credentials` принадлежали + роли **`iot_service`** (создана 2026-08-16, пароль утерян — нет ни в vault + платформы, ни в `IoT/pg.key`). Роль `iotservice` из tfvars — не владелец и без + прав: `has_table_privilege('iotservice','iot_devices','SELECT')=false`. + Данные: `iot_devices` 26 строк (в т.ч. `__bridge/iot-bridge`), `tenant_credentials` 31. +3. **Вторая ошибка (сработала бы следующей).** `MQTT_HOST` из + `local.emqx_internal_host` = `iot-emqx..svc.cluster.local` — **NXDOMAIN**. + Service в namespace платформы называется `containerk8s`: + `containerk8s..svc.cluster.local` → 10.98.42.138 ✅ (проверено `getent hosts` + изнутри пода EMQX; тот же формат — `HISTORY/2026-08-16-session-log.md:824`). + +### Исправление (2026-10-11) + +- **PG** (через `psql` в поде `postgresqlk8s-0`, роль `postgres`): + `BEGIN; ALTER TABLE public.iot_devices OWNER TO iotservice; ALTER TABLE public.tenant_credentials + OWNER TO iotservice; ALTER INDEX public.iot_devices_pkey OWNER TO iotservice; + ALTER INDEX public.idx_iot_devices_ns_device OWNER TO iotservice; COMMIT;` + Пароли не менялись, БД не создавались, env EMQX не менялся. +- `deploy/terraform/resources.tf` — `emqx_internal_host` → `containerk8s.` + (было `resource_name`). + +### Перепроверка после правки (обязательна) + +- Владельцы в PG: все 4 объекта → `iotservice` ✅ +- DDL приложения под `iotservice` по TCP (`sslmode=require`), ровно тот же SQL: + `CREATE TABLE … / CREATE UNIQUE INDEX IF NOT EXISTS …` → `exit=0`, без 42501 ✅ +- Данные целы: `iot_devices` 26 строк, `tenant_credentials` 31 ✅ +- Диагностический под `iot-diag-ok` с `MQTT_HOST=containerk8s.`: `devices store ready`, + `bridge device ensured`, `telemetry store ready`, `bridge: MQTT connected`, + `bridge: subscribed filter=+/telemetry/+`; `/health`=200, `/ready`=200 `{"status":"ready"}` ✅ +- `terraform validate` Success, `terraform plan` = **1 to add, 0 to change, 0 to destroy** + (EMQX не меняется — его env правки не требует); `terraform console local.emqx_internal_host` + = `containerk8s.0d09ee82-c8f9-458f-88a3-89571e5676ed.svc.cluster.local` ✅ +- Диагностические поды удалены, в ns EMQX остались только `containerk8s` и `vmagent`. diff --git a/deploy/terraform/resources.tf b/deploy/terraform/resources.tf index 460e29d..4e333dd 100644 --- a/deploy/terraform/resources.tf +++ b/deploy/terraform/resources.tf @@ -6,9 +6,13 @@ locals { # Внутренний адрес EMQX-контейнера (для bridge внутри кластера). - # Формат Nubes: ..svc.cluster.local. - # Если окажется иным — переопредели var.mqtt_host (см. ЛК → инстанс EMQX). - emqx_internal_host = "${nubes_http.iot_emqx.resource_name}.${nubes_http.iot_emqx.state_out.instanceUid}.svc.cluster.local" + # ⚠️ Service в namespace платформы ВСЕГДА называется `containerk8s`, НЕ + # resource_name. Проверено в кластере iot-naeel (2026-10-11): + # containerk8s..svc.cluster.local → 10.98.42.138 ✅ + # iot-emqx..svc.cluster.local → NXDOMAIN ❌ + # (тот же формат зафиксирован в HISTORY/2026-08-16-session-log.md:824). + # Если окажется иным — переопредели var.mqtt_host. + emqx_internal_host = "containerk8s.${nubes_http.iot_emqx.state_out.instanceUid}.svc.cluster.local" mqtt_host = var.mqtt_host != "" ? var.mqtt_host : local.emqx_internal_host } diff --git a/doc/nubes-deploy-checklist.md b/doc/nubes-deploy-checklist.md index b2a728e..80cea60 100644 --- a/doc/nubes-deploy-checklist.md +++ b/doc/nubes-deploy-checklist.md @@ -58,6 +58,17 @@ Env (все — при создании, потом не меняются): После создания — записать **UUID namespace EMQX** (нужен в `MQTT_HOST`). +⚠️ Внутренний Service в namespace платформы называется **`containerk8s`**, НЕ `iot-emqx` +(проверено 2026-10-11): +- `containerk8s..svc.cluster.local` → резолвится ✅ +- `iot-emqx..svc.cluster.local` → NXDOMAIN ❌ + +⚠️ Роль-владелец таблиц: в БД `iotdb` таблицы `iot_devices`/`tenant_credentials` были созданы +ролью `iot_service` (деплой 2026-08-16). Приложению нужен ВЛАДЕЛЕЦ (иначе +`store: init schema: pq: must be owner of table iot_devices (42501)` → под падает, платформа +откатывает установку). Владение передано роли `iotservice` 2026-10-11: +`ALTER TABLE public.iot_devices OWNER TO iotservice;` + `tenant_credentials` + индексы. + ## 3. iot-service-контейнер (создаётся ВТОРЫМ) Образ: `gitea.services.ngcloud.ru/nail/iot-service:v0.1.13`, порт из EXPOSE = `9090`. @@ -75,7 +86,7 @@ Env (обязательные — секреты; необязательные | `SQS_ENDPOINT` | `https://sqs.sinefo.ru` (не дефолт: shared-sqs НЕ в кластере, а на ВМ 213) | | `SQS_QUEUE_NAME` | `iot-telemetry` (дефолт) | | `SQS_DLQ_NAME` | `iot-telemetry-dlq` (дефолт) | -| `MQTT_HOST` | `` | +| `MQTT_HOST` | `containerk8s..svc.cluster.local` (см. предупреждение в шаге 2) | | `MQTT_PORT` | `8083` (дефолт) | | `AUTH_TEST_MODE` | `false` |