diff --git a/doc/progress.md b/doc/progress.md index 12a460d..8f2d2bc 100644 --- a/doc/progress.md +++ b/doc/progress.md @@ -1,6 +1,59 @@ # Прогресс разработки -Последнее обновление: 2026-04-06 21:00 МСК +Последнее обновление: 2026-04-07 14:30 МСК + +--- + +## 2026-04-07 — SQS Operator: переделка через Operator SDK + +### Цель +Managed SQS-совместимый сервис (ElasticMQ per-tenant) — Kubernetes оператор. + +### Что сделано (Opus) +1. ✅ Установлен operator-sdk v1.37.0 на VM +2. ✅ `operator-sdk init` — scaffold (Makefile, Dockerfile, config/, cmd/, PROJECT) +3. ✅ `operator-sdk create api --kind QueueService --group sqs --version v1alpha1` +4. ✅ CRD types заполнены — QueueServiceSpec (TenantID, MemoryMB, StorageMB, Persistence), QueueServiceStatus (Phase, Endpoint, SecretName, Message, ReadyAt) +5. ✅ Reconciler перенесён из ручного кода в `internal/controller/` (provision, checkReady, ensureHealthy, handleDeletion) +6. ✅ controller-gen обновлён до v0.17.0 (совместимость с Go 1.26.1) +7. ✅ `make generate` — deepcopy автогенерирован +8. ✅ `make manifests` — CRD YAML + RBAC ClusterRole из маркеров +9. ✅ `make build` — bin/manager 55MB, компиляция без ошибок +10. ✅ Коммит `66dcd99` + push + +### Что осталось (Sonnet) +- ⬜ Исправить Dockerfile (не копирует internal/config/ и internal/elasticmq/) +- ⬜ Docker build + push в pearlharbor registry +- ⬜ Обновить kubeconfig (протух) +- ⬜ make install (CRD в кластер) +- ⬜ make deploy (оператор в кластер) + env SQS_EXTERNAL_HOST + imagePullSecrets +- ⬜ Создать тестовый QueueService CR +- ⬜ Smoke test SQS API через curl + +### Ключевые решения +- Модель: инстанс на тенанта (ElasticMQ Native, ~30MB idle) +- Routing: path-based `sqs.kube5s.ru/sqs/{tenantId}` +- DNS: sqs.kube5s.ru → 185.247.187.147 (создан) +- Namespace: sless-fn-{tenantId} (существующий) +- Persistence: H2 на PVC + +### Структура sqs-operator/ +``` +sqs-operator/ +├── api/v1alpha1/ ← CRD types + deepcopy +├── cmd/main.go ← entry point +├── config/ ← kustomize (CRD, RBAC, manager) +├── internal/ +│ ├── config/ ← env config +│ ├── controller/ ← reconciler +│ └── elasticmq/ ← HOCON config + credentials +├── Makefile ← operator-sdk toolchain +├── Dockerfile ← multi-stage (NEEDS FIX) +└── PROJECT ← metadata +``` + +### План для Sonnet +Подробный план: `doc/sqs-operator-sonnet-plan.md` — 8 этапов с командами и проверками. --- diff --git a/doc/sqs-operator-sonnet-plan.md b/doc/sqs-operator-sonnet-plan.md new file mode 100644 index 0000000..91f07cd --- /dev/null +++ b/doc/sqs-operator-sonnet-plan.md @@ -0,0 +1,276 @@ +# SQS Operator — План для Sonnet (этап: сборка → деплой → тест) +# Дата: 2026-04-07 +# Подготовил: Claude Opus 4.6 +# Исполнитель: Claude Sonnet + +--- + +## Контекст + +SQS Operator переделан через Operator SDK v1.37.0. Код компилируется (`make build` OK). +Нужно: docker build → push в registry → deploy в кластер → создать тестовый QueueService → убедиться что ElasticMQ pod поднялся. + +**Ветка**: `sqs-operator` +**Последний коммит**: `66dcd99` — refactor через Operator SDK + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА (прочитай ПОЛНОСТЬЮ перед работой) + +1. **ВСЕ команды — ТОЛЬКО через SSH на VM**: + ``` + ssh -i /home/naeel/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no -o ConnectTimeout=10 naeel@5.172.178.213 КОМАНДА + ``` +2. **Файлы редактировать можно через VS Code** — папка `/home/naeel/remote_dev/sless` = mount VM `~/terra/sless/` +3. **НЕ запускать НИЧЕГО локально** — только SSH +4. **Всегда указывать timeout** в run_in_terminal +5. **Не делать без явной команды пользователя** — спрашивать, если непонятно +6. **kubeconfig протух** — перед kubectl нужно обновить. СПРОСИ ПОЛЬЗОВАТЕЛЯ как. +7. **Документировать каждый шаг** в doc/thinking/ и doc/progress.md + +--- + +## Этап 1: Исправить Dockerfile + +**Проблема**: Scaffold Dockerfile копирует только `internal/controller/`, но наш код также в: +- `internal/config/` — загрузка env конфига +- `internal/elasticmq/` — HOCON генератор + credentials + +**Файл**: `sqs-operator/Dockerfile` + +**Что менять**: добавить строки COPY для недостающих пакетов. После строки: +``` +COPY internal/controller/ internal/controller/ +``` +Добавить: +``` +COPY internal/config/ internal/config/ +COPY internal/elasticmq/ internal/elasticmq/ +``` + +**Проверка**: `make docker-build IMG=pearlharbor.registryk8s.services.ngcloud.ru/naeel/sqs-operator:v0.1.0` + +--- + +## Этап 2: Docker build + push + +```bash +cd ~/terra/sless/sqs-operator +make docker-build IMG=pearlharbor.registryk8s.services.ngcloud.ru/naeel/sqs-operator:v0.1.0 +make docker-push IMG=pearlharbor.registryk8s.services.ngcloud.ru/naeel/sqs-operator:v0.1.0 +``` + +Docker registry: `pearlharbor.registryk8s.services.ngcloud.ru` (уже залогинен - `docker login` возвращает OK). + +--- + +## Этап 3: Обновить kubeconfig + +**Сейчас kubectl не работает** — `the server has asked for the client to provide credentials`. + +**СПРОСИ ПОЛЬЗОВАТЕЛЯ** как обновить kubeconfig. Не пытайся обойти самостоятельно. + +--- + +## Этап 4: Установить CRD в кластер + +```bash +cd ~/terra/sless/sqs-operator +make install +``` + +Это применит `config/crd/bases/sqs.kube5s.ru_queueservices.yaml` в кластер. + +**Проверка**: +```bash +kubectl get crd queueservices.sqs.kube5s.ru +``` + +--- + +## Этап 5: Deploy оператора + +### 5a. Подготовить manager.yaml + +Kustomize namespace: `sqs-operator-system` (из `config/default/kustomization.yaml`). + +**Нужно проверить/настроить**: +1. IMAGE: заменить `controller:latest` на реальный registry image +2. ENV: добавить `SQS_EXTERNAL_HOST=sqs.kube5s.ru` в Deployment container env +3. ImagePullSecrets: если registry приватный, может понадобиться secret + +Команда деплоя через kustomize: +```bash +cd ~/terra/sless/sqs-operator +make deploy IMG=pearlharbor.registryk8s.services.ngcloud.ru/naeel/sqs-operator:v0.1.0 +``` + +### 5b. Добавить env SQS_EXTERNAL_HOST + +**ВАЖНО**: manager.yaml не содержит env SQS_EXTERNAL_HOST. Оператор крашнется без него. + +Варианты: +- **Вариант A** (рекомендуемый): Создать kustomize patch файл `config/manager/env_patch.yaml` +- **Вариант B**: Отредактировать `config/manager/manager.yaml` напрямую — добавить env + +Добавить в containers[0].env: +```yaml +env: +- name: SQS_EXTERNAL_HOST + value: "sqs.kube5s.ru" +``` + +### 5c. ImagePullSecrets + +Registry `pearlharbor.registryk8s.services.ngcloud.ru` — приватный. В namespace `sqs-operator-system` нужен secret: +```bash +kubectl create secret docker-registry pearlharbor-registry \ + --namespace=sqs-operator-system \ + --docker-server=pearlharbor.registryk8s.services.ngcloud.ru \ + --docker-username=admin \ + --docker-password= +``` + +Пароль для registry — проверь в `secrets/pearlharbor_registry.txt`. + +И добавить `imagePullSecrets` в manager.yaml. + +**Проверка**: +```bash +kubectl -n sqs-operator-system get pods +kubectl -n sqs-operator-system logs deployment/sqs-operator-controller-manager -c manager +``` + +Ожидаемый лог: `operator config loaded`, `starting manager`. + +--- + +## Этап 6: Тестирование — создать QueueService + +### 6a. Обновить sample CR + +Файл `config/samples/sqs_v1alpha1_queueservice.yaml` — сейчас пустой (scaffold). +Заполнить: +```yaml +apiVersion: sqs.kube5s.ru/v1alpha1 +kind: QueueService +metadata: + name: test-tenant-001 + namespace: sqs-operator-system +spec: + tenantId: "test001" + memoryMB: 64 + storageMB: 512 + persistence: true +``` + +### 6b. Применить +```bash +kubectl apply -f config/samples/sqs_v1alpha1_queueservice.yaml +``` + +### 6c. Наблюдение +```bash +# CR статус +kubectl get queueservices -A + +# Логи оператора +kubectl -n sqs-operator-system logs deployment/sqs-operator-controller-manager -c manager -f + +# Ресурсы тенанта (должны появиться в sless-fn-test001) +kubectl -n sless-fn-test001 get all,pvc,secret,ingress + +# ElasticMQ pod +kubectl -n sless-fn-test001 get pods -w +``` + +**Ожидаемый результат**: +- QueueService Phase: Pending → Provisioning → Ready +- В `sless-fn-test001`: + - Deployment `sqs-test001` — 1 pod Running + - Service `sqs-svc-test001` — ClusterIP:9324 + - Ingress `sqs-ing-test001` — sqs.kube5s.ru/sqs/test001 + - Secret `sqs-creds-test001` — accessKey/secretKey + - PVC `sqs-data-test001` + - ConfigMap `sqs-cfg-test001` + +--- + +## Этап 7: Smoke test SQS API + +```bash +# Получить credentials +ACCESS_KEY=$(kubectl -n sless-fn-test001 get secret sqs-creds-test001 -o jsonpath={.data.accessKey} | base64 -d) +SECRET_KEY=$(kubectl -n sless-fn-test001 get secret sqs-creds-test001 -o jsonpath={.data.secretKey} | base64 -d) + +# Создать очередь через curl (SQS API) +curl -k "https://sqs.kube5s.ru/sqs/test001/?Action=CreateQueue&QueueName=my-test-queue&Version=2012-11-05" \ + --user "$ACCESS_KEY:$SECRET_KEY" + +# Отправить сообщение +curl -k "https://sqs.kube5s.ru/sqs/test001/?Action=SendMessage&MessageBody=hello-world&Version=2012-11-05" \ + --user "$ACCESS_KEY:$SECRET_KEY" + +# Прочитать сообщение +curl -k "https://sqs.kube5s.ru/sqs/test001/?Action=ReceiveMessage&Version=2012-11-05" \ + --user "$ACCESS_KEY:$SECRET_KEY" +``` + +--- + +## Этап 8: Коммит + пуш + +```bash +git add -A && git commit -m "feat(sqs-operator): docker build, deploy, tested QueueService" +git push +``` + +--- + +## Справочная информация + +### Ключевые файлы +| Файл | Назначение | +|------|-----------| +| `api/v1alpha1/queueservice_types.go` | CRD Spec/Status с kubebuilder маркерами | +| `internal/controller/queueservice_controller.go` | Reconciler: provision, checkReady, handleDeletion | +| `internal/elasticmq/elasticmq_config.go` | HOCON конфиг ElasticMQ для тенанта | +| `internal/elasticmq/elasticmq_credentials.go` | Генератор accessKey/secretKey | +| `internal/config/sqs_operator_config.go` | Env конфиг: SQS_EXTERNAL_HOST, SQS_ELASTICMQ_IMAGE | +| `cmd/main.go` | Entry point (scaffold + config loading) | +| `config/crd/bases/sqs.kube5s.ru_queueservices.yaml` | Автосгенерированный CRD YAML | +| `config/rbac/role.yaml` | Автосгенерированный RBAC ClusterRole | +| `Makefile` | Operator SDK toolchain: manifests, generate, build, docker-build, deploy | +| `Dockerfile` | Multi-stage build (НУЖНО ИСПРАВИТЬ — см. этап 1) | + +### Reconciler фазы +``` +Pending → provision() → Provisioning → checkReady() → Ready + ↑ +Failed ← ensureHealthy() (pod down) recoverFromFailed() ←→ Ready +``` + +### Env переменные оператора +| Переменная | Обязательная | Default | Описание | +|-----------|-------------|---------|----------| +| SQS_EXTERNAL_HOST | ДА | — | Публичный хост: sqs.kube5s.ru | +| SQS_ELASTICMQ_IMAGE | нет | softwaremill/elasticmq-native:1.7.1 | Docker образ ElasticMQ | +| OPERATOR_NAMESPACE | нет | sless | Namespace оператора | + +### SSH +``` +ssh -i /home/naeel/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no -o ConnectTimeout=10 naeel@5.172.178.213 +``` + +### Docker registry +``` +pearlharbor.registryk8s.services.ngcloud.ru/naeel/sqs-operator:v0.1.0 +``` +Логин: admin, пароль в `secrets/pearlharbor_registry.txt` + +### Toolchain версии +- Go: 1.26.1 +- operator-sdk: v1.37.0 +- controller-gen: v0.17.0 +- controller-runtime: v0.17.3 +- Docker: 28.2.2