Files
tf_registry/REGISTRY_OVERVIEW.md
T

199 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 или переменные окружения.