docs: обновление doc/ по итогам сессии 2026-03-08
This commit is contained in:
@@ -204,3 +204,44 @@
|
||||
- operator: `naeel/sless-operator:v0.1.6`
|
||||
- provider: `terra.k8c.ru/naeel/sless v0.1.4`
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — Переключение registry с Harbor на DockerHub
|
||||
|
||||
**Проблема:** Harbor (`pearlharbor.registryk8s.services.ngcloud.ru`) — внешний сервис облачного провайдера. Нестабилен: `/v2/` периодически зависает на 10+ секунд или возвращает 504. Kaniko не мог завершить push образа.
|
||||
|
||||
**Решение:** `REGISTRY_HOST=naeel` (DockerHub namespace). Образы функций пушатся как `naeel/sless-default-{namespace}-{name}:latest`.
|
||||
|
||||
**Реализация:**
|
||||
- `deployments/k8s/operator.yaml` — configmap `REGISTRY_HOST: "naeel"`
|
||||
- Secret `sless-registry-auth` уже содержал DockerHub credentials → дополнительных изменений не потребовалось
|
||||
|
||||
**Компромисс:** DockerHub — публичный registry. Образы функций пользователей публично видимы. Для production нужен приватный registry (Harbor, ECR, GCR и т.д.).
|
||||
|
||||
**Версии:**
|
||||
- operator: оператор не пересобирался, только configmap
|
||||
- commit: `b69f795`
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — FunctionJob polling вместо Owns watch
|
||||
|
||||
**Проблема:** `Owns(&batchv1.Job{})` в `SetupWithManager` не работает cross-namespace. Job создаётся в `sless-fn-{ns}`, FunctionJob — в user namespace. Watch никогда не срабатывал.
|
||||
|
||||
**Решение:** Убрать `Owns`. В `syncJobStatus` при Running статусе возвращать `ctrl.Result{RequeueAfter: 5 * time.Second}` — контроллер сам поллит k8s Job каждые 5 сек.
|
||||
|
||||
**Версии:**
|
||||
- operator: `naeel/sless-operator:v0.1.10`
|
||||
- commit: `461ac09`
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — code_hash: filesha256 вместо output_md5
|
||||
|
||||
**Проблема:** `hashicorp/archive v2.7.x` имеет баг: `output_md5` возвращает MD5 предыдущей версии zip. `output_sha` и `output_sha256` обновляются корректно.
|
||||
|
||||
**Решение:** `code_hash = filesha256("${path.module}/code/handler.js")` — хэшируется исходный файл напрямую.
|
||||
|
||||
**Правило проекта:** В `sless_function.code_hash` всегда использовать `filesha256(source_file)`, не `archive_file.output_md5`.
|
||||
|
||||
|
||||
@@ -131,6 +131,116 @@ deployment.Spec.Template.Annotations["kubectl.kubernetes.io/restartedAt"] = time
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — output_md5 archive провайдера не обновляется при изменении кода
|
||||
|
||||
**Проблема:** `terraform plan` показывал "No changes" даже после изменения JS-файла функции. Функция отдавала старый код.
|
||||
|
||||
**Причина:** `code_hash = data.archive_file.handler_http.output_md5` — атрибут `output_md5` в `hashicorp/archive v2.7.x` возвращает MD5 от **предыдущей** версии zip (баг порядка вычисления). `output_sha` и `output_sha256` от того же файла обновлялись корректно.
|
||||
|
||||
**Решение:** Заменить `output_md5` на `filesha256("${path.module}/code/handler.js")` — хэшируется исходный файл напрямую, минуя archive провайдер.
|
||||
|
||||
**Урок:** Не использовать `output_md5` из `archive_file`. Использовать `filesha256(source_file)`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — FunctionJob зависал в Running навсегда
|
||||
|
||||
**Проблема:** `terraform apply` висел на `sless_job.hello_run: Still creating...` бесконечно. k8s Job давно завершился (Complete), но FunctionJob оставался в `Running`.
|
||||
|
||||
**Причина:** `SetupWithManager` использовал `Owns(&batchv1.Job{})` для watch событий Job. Но Job создавался в namespace `sless-fn-default`, а FunctionJob в `default` — cross-namespace OwnerReference не работают в k8s. Reconcile после завершения Job никогда не вызывался.
|
||||
|
||||
**Решение:** Убрать `Owns(&batchv1.Job{})`. В `syncJobStatus` добавить `return ctrl.Result{RequeueAfter: 5 * time.Second}` когда Job ещё выполняется — polling каждые 5 сек.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — ImagePullBackOff: sless-registry-auth не копировался в sless-fn-*
|
||||
|
||||
**Проблема:** Pod функции падал с `ImagePullBackOff` — не мог скачать образ из registry.
|
||||
|
||||
**Причина:** `buildDeployment` в `function_controller.go` не устанавливал `imagePullSecrets` в PodSpec. Секрет `sless-registry-auth` существовал только в namespace `sless`, но не копировался в `sless-fn-default`.
|
||||
|
||||
**Решение:** Добавить `ensureRegistrySecret()` — копирует секрет из `sless` в `sless-fn-*` при каждом reconcile. В `buildDeployment` добавить `ImagePullSecrets`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — CrashLoopBackOff: Cannot find module handler.js
|
||||
|
||||
**Проблема:** Pod функции падал: `Cannot find module '/app/function/handler.js'`. Entrypoint был `handler-http.handle` (файл `handler-http.js`), а server.js искал хардкоженный `handler.js`.
|
||||
|
||||
**Причина:** `server.js` и `server.py` runtime-образов хардкодили имя модуля `handler`. Поле `SLESS_ENTRYPOINT` env var не использовалось.
|
||||
|
||||
**Решение:** `server.js` и `server.py` переписаны: парсят `SLESS_ENTRYPOINT` (формат `"module.funcName"`), динамически загружают нужный модуль. Runtime пересобран как `v0.1.1`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — Kaniko cache: пересобирал образ со старым server.js
|
||||
|
||||
**Проблема:** После исправления `server.js` kaniko продолжал собирать образы с **старым** server.js из кэша.
|
||||
|
||||
**Причина:** Base image тегирован как `:latest`. Kaniko кэшировал слои — `FROM naeel/sless-runtime-nodejs20:latest` не перечитывал обновлённый образ.
|
||||
|
||||
**Решение:** Новый тег базового образа `v0.1.1`. В `upload.go` изменить `runtimeBaseImage("nodejs20")` → `naeel/sless-runtime-nodejs20:v0.1.1`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — RBAC: secrets is forbidden: cannot list
|
||||
|
||||
**Проблема:** Оператор падал: `secrets is forbidden: User "system:serviceaccount:sless:sless-operator" cannot list resource "secrets"`.
|
||||
|
||||
**Причина:** В `rbac.yaml` для secrets были только `get;create`, нужны также `list;watch` для controller-runtime.
|
||||
|
||||
**Решение:** Добавить `list;watch` в ClusterRole для `resources: ["secrets"]`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — Harbor registry нестабилен (504 Gateway Timeout)
|
||||
|
||||
**Проблема:** Kaniko падал: `GET https://pearlharbor.registryk8s.services.ngcloud.ru/v2/: unexpected status code 504 Gateway Timeout`. Периодически `/v2/` зависал на 10+ секунд или не отвечал вовсе.
|
||||
|
||||
**Причина:** Harbor — внешний сервис облачного провайдера, нестабилен по независящим от нас причинам. Поведение не зависит от VPN.
|
||||
|
||||
**Решение:** Переключить `REGISTRY_HOST` с Harbor на DockerHub (`naeel`). Образы функций теперь пушатся как `naeel/sless-default-{namespace}-{name}:latest`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — Provider: inconsistent result — image_ref изменился после apply
|
||||
|
||||
**Проблема:** После `terraform apply` ошибка:
|
||||
```
|
||||
Provider produced inconsistent result after apply
|
||||
.image_ref: was cty.StringVal("pearlharbor..."), but now cty.StringVal("naeel/...")
|
||||
```
|
||||
|
||||
**Причина:** `image_ref` в схеме провайдера имел `UseStateForUnknown()`. При plan terraform брал значение из state (старый Harbor путь). После apply API возвращал новый DockerHub путь. Расхождение план vs результат.
|
||||
|
||||
**Решение:** Убрать `UseStateForUnknown()` с `image_ref`. Теперь `image_ref` = `(known after apply)` при каждом apply — честно отражает что значение неизвестно до сборки. Провайдер `v0.1.5`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — Provider: inconsistent result — phase Failed→Ready
|
||||
|
||||
**Проблема:**
|
||||
```
|
||||
Provider produced inconsistent result after apply
|
||||
.phase: was cty.StringVal("Failed"), but now cty.StringVal("Ready")
|
||||
```
|
||||
|
||||
**Причина:** При ошибке `WaitReady` (build failed) → `AddError` → `return`. `resp.State.Set` не вызывался → state не обновлялся → в state оставалось старое значение. Затем оператор замечал новый код, пересобирал → функция становилась Ready. Следующий `Read` возвращал `phase=Ready`, terraform видел расхождение.
|
||||
|
||||
**Решение:** Убрать `UseStateForUnknown()` с `image_ref` (связанный фикс). Для `phase` — `UseStateForUnknown()` оставлен, т.к. при нормальном flow `Ready→Ready` предсказуем.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-08 — Стейл-сервис hello-node блокировал proxy запросы
|
||||
|
||||
**Проблема:** `GET /fn/default/hello-node` возвращал `operation not permitted` — `dial tcp 10.100.77.255:8080: connect: operation not permitted`.
|
||||
|
||||
**Причина:** Сервис `hello-node` в `sless-fn-default` существовал 26h с ClusterIP `10.100.77.255` но без Deployment/Pod. iptables дропал пакеты на несуществующий endpoint.
|
||||
|
||||
**Решение:** `kubectl delete svc hello-node -n sless-fn-default`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-03-07 — Docker credStore: exec "docker-credential-desktop.exe"
|
||||
|
||||
**Проблема:** `docker push` падал с `exec: "docker-credential-desktop.exe": executable file not found`.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Прогресс разработки
|
||||
|
||||
Последнее обновление: 2026-03-07 (operator v0.1.5, provider v0.1.3)
|
||||
Последнее обновление: 2026-03-08 (operator v0.1.10, provider v0.1.5)
|
||||
|
||||
## Статусы: ✅ готово | 🔄 в процессе | ⏳ не начато
|
||||
|
||||
|
||||
Reference in New Issue
Block a user