doc: README.md, CHAT_SUMMARY + REGISTRY_OVERVIEW → HISTORY

This commit is contained in:
“Naeel”
2026-08-09 07:22:36 +04:00
parent f3df103bb3
commit 3aca89ea60
3 changed files with 86 additions and 0 deletions
+199
View File
@@ -0,0 +1,199 @@
# Chat Summary — Реестр Terraform-провайдера Nubes
> **Дата**: 2026-08-06
> **Тема**: Разбор архитектуры registry-сервера, план переноса с Go/K8s на Flask managed-сервис в облаке
> **Для нового чата**: прочитай этот файл — и ты в контексте
---
## 1. Что такое провайдер `nubes`
Кастомный Terraform-провайдер для облака NGCloud. Написан на Go (`~/tf_provider/provider/main.go`). Публикуется в собственном реестре `registry.kube5s.ru`.
**Terraform-конфиг (как у пользователя)**:
```hcl
terraform {
required_providers {
nubes = {
source = "registry.kube5s.ru/nubes-test/nubes"
version = "5.1.16"
}
}
}
provider "nubes" {
api_token = var.api_token
api_endpoint = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc"
# log_level = "debug" # none | info | debug
}
```
**Разбор адреса** `registry.kube5s.ru/nubes-test/nubes`:
- `registry.kube5s.ru` — домен реестра (DNS пользователя → IP балансировщика K8s)
- `nubes-test` — **namespace** внутри реестра (для тестовых версий)
- `nubes` — имя провайдера
**Namespace'ы реестра:**
| Namespace | Где используется |
|---|---|
| `nubes-test` | Тестовый стенд |
| `nubes-dev` | Dev-стенд |
| `nubes` | Прод (PROD) |
---
## 2. Где и как запущен реестр (текущее состояние)
### Подтверждено через SSH → ВМ → kubectl:
- **ВМ**: `naeel@5.172.178.213` (ключ `~/remote_dev/terraform/secrets/id_ed25519.txt`, или по умолчанию из `~/.ssh`)
- **Кластер**: `iot-naeel` (self-managed K8s, **личный кластер пользователя**)
- **Namespace**: `terra`
### Деплойменты:
| Компонент | Образ | Статус |
|---|---|---|
| `registry-server` | `naeel/terraform-registry-server:gpg-fix-2` | 1/1 Running |
| `terraform-operator` | `naeel/terraform-registry-operator:latest` | 1/1 Running |
| `cloud-dashboard` | `naeel/cloud-dashboard:v9.52` | 1/1 Running |
### Ingress `registry-ingress`:
- Хосты: `terra.k8c.ru`, **`registry.kube5s.ru`**
- TLS: `registry-kube5s-tls` (Ready)
- Балансировщик: `185.247.187.151`
### ENV `registry-server`:
```
REGISTRY_HOSTNAME = registry.kube5s.ru
S3_ENDPOINT = s3.msk-1.ngcloud.ru
S3_BUCKET = terraform-registry
S3_USE_SSL = true
```
### Проверка живого реестра (HTTP 200):
```
GET /.well-known/terraform.json → {"providers.v1":"/v1/providers/"}
GET /v1/providers/nubes-test/nubes/versions → версии 5.1.0 ... 5.1.16
```
---
## 3. Код реестра — `~/tf_registry`
- **Репозиторий**: `https://gitea.services.ngcloud.ru/Nail/tf_registry.git`
- **Ветка**: `master`
- **Язык**: Go
- **Структура**:
- `server/main.go` — **актуальный код** HTTP-сервера реестра
- `operator/` — Kubernetes Operator
- `k8s/`, `charts/` — манифесты деплоя
- `registrykeys/` — GPG-ключ
### Архитектура текущего реестра:
```
registry.kube5s.ru (DNS)
→ K8s Ingress (личный кластер iot-naeel)
→ Deployment registry-server (Go, Docker)
→ S3 bucket terraform-registry/
└── {REGISTRY_HOSTNAME}/nubes-test/nubes/{version}/
├── terraform-provider-nubes_{version}_{os}_{arch}.zip
├── ..._SHA256SUMS
└── ..._SHA256SUMS.sig
```
### Протокол (Terraform Registry Protocol v1):
| Эндпоинт | Назначение |
|---|---|
| `GET /.well-known/terraform.json` | Discovery |
| `GET /v1/providers/{ns}/{name}/versions` | Список версий и платформ |
| `GET /v1/providers/{ns}/{name}/{ver}/download/{os}/{arch}` | URL для скачивания |
| `GET /v1/proxy?url=...` | Прокси из S3 |
| `GET /docs/...` | Документация |
---
## 4. План: перенос реестра на Flask (managed-сервис в облаке)
### Проблема:
Кубер — **личный** кластер пользователя. Реестр должен быть **чисто облачным**, как managed-сервис (Flask или Node.js), который создаётся через UI облака.
### Выбор языка: **Flask (Python)**
- `boto3` — лучший S3-клиент
- Уже есть работающий Flask managed-сервис (`tfflaskcrud/`)
- Проще и короче, чем Node.js для этой задачи
### Новая архитектура:
```
registry.pythonk8s.dev.nubes.ru (managed-сервис, URL даёт облако)
→ Flask app (app.py)
→ S3 bucket terraform-registry/ (тот же)
```
### Что больше НЕ нужно:
- ❌ K8s-деплой `registry-server`
- ❌ K8s Ingress `registry-ingress`
- ❌ Сертификат `registry-kube5s-tls` + cert-manager
- ❌ Домен `registry.kube5s.ru` (заменяется на managed URL)
- ❌ Docker-образы для реестра
- ❌ Go-код для реестра
### План реорганизации Git-репозитория:
```
git checkout -b golang # сохранить Go-код в ветку golang
git checkout master # вернуться в master
# удалить всё лишнее
# оставить только app.py + requirements.txt + README.md
```
- **`master`** → Flask-реестр (основная ветка)
- **`golang`** → старый Go-код (архив, можно поправить и задеплоить при необходимости)
### Имя managed-сервиса: **`registry`**
```
https://registry.pythonk8s.dev.nubes.ru/
```
### Terraform-конфиг пользователя после миграции:
```hcl
source = "registry.pythonk8s.dev.nubes.ru/nubes-test/nubes"
```
### Файлы Flask-реестра:
```
tf_registry/
├── app.py # весь код (~300 строк)
├── requirements.txt # Flask, boto3, python-gnupg
└── README.md
```
---
## 5. Managed-сервисы в облаке
Пользовательские managed-сервисы (Flask, Node.js, Lucee) создаются через **UI облака** (не через Terraform). Terraform-провайдер `nubes` тоже умеет их создавать (`nubes_flask`, `nubes_nodejs`, `nubes_lucee`), но это вторичный способ.
---
## 6. Ключевые файлы и репозитории
| Что | Путь |
|---|---|
| Код registry-сервера (Go) | `~/tf_registry/server/main.go` |
| Код провайдера (Go) | `~/tf_provider/provider/main.go` |
| Git реестра | `https://gitea.services.ngcloud.ru/Nail/tf_registry.git` |
| Пример Flask managed-сервиса | `~/tf_provider/tfflaskcrud/site/app.py` |
| Пример Node.js managed-сервиса | `~/tf_provider/tfnodejscrud/server.js` |
| SSH-доступ к ВМ | `naeel@5.172.178.213` |
| Кластер | `iot-naeel`, namespace `terra` |
---
## 7. Следующие шаги (для нового чата)
1. Прочитать `~/tf_registry/server/main.go` (весь) — понять точную логику
2. Написать `app.py` — Flask-реестр с теми же эндпоинтами
3. Проверить синтаксис Python
4. Создать ветку `golang` из `master` и сохранить Go-код
5. Очистить `master`, оставить только Flask
6. Залить `app.py` в managed-сервис `registry` через UI облака
7. Проверить: `curl https://registry.pythonk8s.dev.nubes.ru/.well-known/terraform.json`
8. Обновить `source` в Terraform-конфигах пользователей
+198
View File
@@ -0,0 +1,198 @@
# Terraform Registry — Полное описание
> Этот документ — точка входа для нового чата/агента. Содержит всё необходимое для понимания, сопровождения и доработки реестра провайдера.
---
## Что это такое
Кастомный Terraform Registry Server для провайдера `nubes` (облако Nubes / ngcloud.ru).
Когда разработчик пишет в своём `.tf`:
```hcl
terraform {
required_providers {
nubes = {
source = "terra.k8c.ru/nubes/nubes"
version = "5.0.18"
}
}
}
```
...и выполняет `terraform init`, Terraform идёт к **этому** серверу за бинарниками провайдера.
---
## Структура папки
```
REGISTRY/
├── server/ — Go-код HTTP-сервера реестра (АКТУАЛЬНЫЙ)
├── operator/ — Kubernetes Operator (CRD TerraformProviderRelease) + старая копия server-кода в cmd/registry/
├── k8s/ — Kubernetes манифесты деплоя (namespace, ingress, deployment, service, TLS)
├── registrykeys/ — Go-модуль с публичным GPG-ключом (для верификации провайдера)
├── charts/ — Helm chart для деплоя registry-server
└── scripts/
└── build-and-push-registry-server.sh — сборка Docker-образа и push в registry
```
**Важно:** `server/` и `operator/cmd/registry/` — дублирующийся код. Актуальный и полный — только `server/main.go`. В `operator/cmd/registry/main.go` нет health-эндпоинтов и не удалены darwin-платформы. При правках менять только `server/`.
---
## Как работает registry-server
### Реализованный протокол
[Terraform Registry Protocol v1](https://developer.hashicorp.com/terraform/internals/provider-registry-protocol).
| Эндпоинт | Назначение |
|---|---|
| `GET /.well-known/terraform.json` | Discovery — говорит Terraform, где API реестра |
| `GET /v1/providers/{ns}/{name}/versions` | Список доступных версий и платформ |
| `GET /v1/providers/{ns}/{name}/{version}/download/{os}/{arch}` | URL для скачивания бинарника |
| `GET /v1/proxy?url=...` | Проксирование файлов из S3 (бинарники, SHA, GPG-сигнатура) |
| `GET /docs/{ns}/{name}/{version}/...` | Документация провайдера (статический HTML из S3) |
| `GET /healthz` | Health probe для Kubernetes |
| `GET /readyz` | Readiness probe для Kubernetes |
### Как определяются версии
Сервер листит S3 bucket в поиске файлов вида:
```
<hostname>/<namespace>/<name>/<version>/terraform-provider-<name>_<version>_linux_amd64.zip
```
Из имён файлов парсит версию и платформы. Поддерживаемые платформы: `linux_amd64`, `linux_arm64`, `windows_amd64`.
### Переменные окружения
| Переменная | Default | Назначение |
|---|---|---|
| `REGISTRY_HOSTNAME` | `localhost:8080` | Домен реестра (используется в URL ответов) |
| `S3_ENDPOINT` | — | Хост S3 без схемы, например `s3.msk-1.ngcloud.ru` |
| `S3_ACCESS_KEY` | — | S3 access key |
| `S3_SECRET_KEY` | — | S3 secret key |
| `S3_BUCKET` | `terraform-registry` | Имя бакета |
| `S3_USE_SSL` | — | Если `true` — HTTPS (в коде Secure: true захардкожено) |
### S3 структура бакета
```
terraform-registry/ ← бакет
└── terra.k8c.ru/
└── nubes/
└── nubes/
└── 5.0.18/
├── terraform-provider-nubes_5.0.18_linux_amd64.zip
├── terraform-provider-nubes_5.0.18_windows_amd64.zip
├── terraform-provider-nubes_5.0.18_SHA256SUMS
└── terraform-provider-nubes_5.0.18_SHA256SUMS.sig
docs/
└── nubes/
└── nubes/
└── 5.0.18/
└── index.html (и другие файлы документации)
```
---
## GPG-ключ
Terraform верифицирует подпись провайдера через GPG.
- Публичный ключ **встроен** в `server/main.go` (ASCII Armor, константа в коде).
- Также хранится в `registrykeys/public_key.go` (отдельный go-модуль).
- Приватный ключ — `secrets/private_key.asc` (НЕ в репо, gitignore).
**При ротации ключей:**
1. Сгенерировать новую пару `gpg --gen-key`
2. Обновить ASCII Armor в `server/main.go`
3. Пересобрать и передеплоить Docker-образ
4. Перезалить все артефакты провайдера, подписанные новым ключом
---
## Деплой в Kubernetes
### Кластер и namespace
- Namespace: `terra`
- Домен: `terra.k8c.ru` (планируемая миграция → `registry.nubes.ru`, см. `../docs/ops/DOMAIN_MIGRATION.md`)
- TLS: cert-manager с `letsencrypt-prod` issuer — **НЕ ТРОГАТЬ** сертификат руками!
### Что задеплоено
| Ресурс | Kind | Образ |
|---|---|---|
| `registry-server` | Deployment | `naeel/terraform-registry-server:gpg-key-20260208` |
| `registry-server` | Service | ClusterIP :8080 |
| `registry-ingress` | Ingress | host: `terra.k8c.ru` |
Credentials S3 — из секрета `s3-credentials` (ключи `access-key`, `secret-key`).
### Применение манифестов (только при смене конфигурации кластера)
```bash
kubectl apply -f k8s/operator/manifests/00-namespace.yaml
kubectl apply -f k8s/operator/manifests/00-rbac.yaml
kubectl apply -f k8s/operator/manifests/02-crd.yaml
kubectl apply -f k8s/operator/manifests/05-registry-server.yaml
```
### Диагностика (read-only)
```bash
kubectl -n terra get pods,svc,ingress,deploy
kubectl -n terra logs -l app=registry-server --tail=50
kubectl -n terra get certificate registry-tls -o yaml
```
---
## Сборка и публикация нового образа
Скрипт: `scripts/build-and-push-registry-server.sh`
```bash
cd REGISTRY
./scripts/build-and-push-registry-server.sh
```
Собирает Docker-образ из `server/` и пушит в Docker Hub (`naeel/terraform-registry-server:<tag>`).
После push нужно обновить тег образа в `operator/manifests/05-registry-server.yaml` и применить `kubectl apply`.
---
## Когда registry НЕ нужно трогать
Registry — stateless сервис. При выпуске новой версии провайдера (`nubes`) registry не меняется:
```
Новая версия провайдера:
1. go build → бинарники
2. devops/03_build_and_upload_provider.sh → бинарники в S3
3. devops/04_build_and_publish_docs.sh → документация в S3
✅ Registry автоматически начинает отдавать новую версию
❌ kubectl не нужен
❌ код registry не меняется
❌ Docker-образ не пересобирается
```
Registry пересобирается только если меняется **сам сервер**: новые эндпоинты, логика, ротация GPG-ключа.
---
## Связь с основным репо провайдера
Этот код был перемещён из основного репо `terraform/` в папку `REGISTRY/` для последующего выноса в отдельный репозиторий. Код провайдера и код реестра полностью независимы — нет общих go-модулей, нет импортов друг друга.
---
## Ограничения и правила работы
- **Ручные правки `operator/cmd/registry/`** — не делать, это устаревшая копия. Актуальный код — только `server/`.
- **Let's Encrypt cert-manager** (`letsencrypt-prod`) — не применять `kubectl apply` на Ingress-ресурсы без именённой необходимости (риск бана от CA).
- **docker build** — только с явного разрешения разработчика.
- **kubectl** — только read-only (`get`, `describe`, `logs`) без разрешения.
- **S3 credentials** — никогда не коммитить в репо. Только через секреты k8s или переменные окружения.