169 lines
5.9 KiB
Markdown
169 lines
5.9 KiB
Markdown
# tf_registry — Архитектура и рабочий процесс
|
||
|
||
## Что такое этот реестр
|
||
|
||
Собственный реестр Terraform-провайдеров по протоколу HashiCorp Provider Registry Protocol.
|
||
Позволяет публиковать и распространять кастомные Terraform-провайдеры без HashiCorp Registry.
|
||
|
||
**Текущий URL:** `https://go-registry.containerk8s.dev.nubes.ru`
|
||
|
||
---
|
||
|
||
## Как это работает
|
||
|
||
### Загрузка провайдера (пользователь)
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
nubes = {
|
||
source = "go-registry.containerk8s.dev.nubes.ru/nubes-test/nubes"
|
||
version = "5.1.16"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Terraform сам делает:
|
||
1. `GET /.well-known/terraform.json` → узнаёт API-путь
|
||
2. `GET /v1/providers/nubes-test/nubes/versions` → список версий и платформ
|
||
3. `GET /v1/providers/.../download/linux/amd64` → JSON с URL для скачивания
|
||
4. Скачивает zip, проверяет SHA256, проверяет GPG-подпись
|
||
5. Всё — провайдер установлен
|
||
|
||
Никакой аутентификации не нужно.
|
||
|
||
---
|
||
|
||
## S3-структура
|
||
|
||
Все данные хранятся в S3 (`terraform-registry`). Никакой БД нет.
|
||
|
||
```
|
||
{префикс}/{namespace}/{name}/{version}/
|
||
├── terraform-provider-{name}_{ver}_{os}_{arch}.zip — бинарник провайдера
|
||
├── terraform-provider-{name}_{ver}_SHA256SUMS — контрольные суммы
|
||
└── terraform-provider-{name}_{ver}_SHA256SUMS.sig — GPG-подпись сумм
|
||
|
||
docs/{namespace}/{name}/{version}/
|
||
├── index.html — документация провайдера
|
||
└── ... — любые статические файлы
|
||
```
|
||
|
||
**Важно:** префикс (первая часть пути в S3) сейчас — `registry.kube5s.ru` (временный хардкод).
|
||
Планируется либо сменить на свой домен, либо убрать префикс совсем.
|
||
|
||
---
|
||
|
||
## GPG-подпись
|
||
|
||
### Зачем
|
||
Terraform требует, чтобы SHA256SUMS были подписаны GPG. Это гарантирует, что провайдер не подменён.
|
||
|
||
### Как работает
|
||
1. **Приватный ключ** — хранится у того, кто заливает провайдер (`secrets/private_key.asc`)
|
||
2. **Публичный ключ** — вшит в код реестра (`gpg_key.go` → `/v1/providers/.../download` отдаёт его)
|
||
3. Terraform при `init` сверяет подпись SHA256SUMS с публичным ключом
|
||
|
||
### Текущие ключи
|
||
| Key ID | Роль |
|
||
|---|---|
|
||
| `3EC4673EB798238A` | Основной (текущий) |
|
||
| `CB3A0DF161ECC416` | Legacy (старый) |
|
||
|
||
Оба отдаются в `signing_keys.gpg_public_keys` — Terraform пробует каждый.
|
||
|
||
---
|
||
|
||
## Как залить новый провайдер
|
||
|
||
### Скрипт `build-provider.sh`
|
||
|
||
Находится в `server/build-provider.sh`. Делает:
|
||
1. Компилирует Go-провайдер под linux/windows/darwin × amd64
|
||
2. Упаковывает в zip
|
||
3. Генерирует SHA256SUMS
|
||
4. Импортирует приватный GPG-ключ из `secrets/private_key.asc`
|
||
5. Подписывает SHA256SUMS
|
||
6. Заливает zip + SHA256SUMS + .sig в S3
|
||
|
||
### Требования
|
||
```bash
|
||
# Переменные окружения
|
||
S3_ENDPOINT=s3.msk-1.ngcloud.ru
|
||
S3_ACCESS_KEY=...
|
||
S3_SECRET_KEY=...
|
||
S3_BUCKET=terraform-registry
|
||
|
||
# GPG
|
||
secrets/private_key.asc # приватный ключ для подписи
|
||
|
||
# Исходники провайдера
|
||
universal_rebuild/ # директория с Go-кодом провайдера
|
||
```
|
||
|
||
### Запуск
|
||
```bash
|
||
VERSION=5.1.17 ./server/build-provider.sh
|
||
```
|
||
|
||
---
|
||
|
||
## Документация
|
||
|
||
Эндпоинт `/docs/{ns}/{name}/{ver}/...` отдаёт статику из S3:
|
||
```
|
||
docs/{ns}/{name}/{ver}/index.html
|
||
```
|
||
|
||
Работает как статический веб-сервер: HTML, CSS, JS, изображения — всё, что положишь в `docs/` в S3.
|
||
Логика поиска (1:1 с Go-кодом):
|
||
1. Точный путь (`docs/ns/name/ver/style.css`)
|
||
2. Если нет расширения — `{путь}/index.html`
|
||
3. Fallback — `docs/ns/name/ver/index.html`
|
||
|
||
---
|
||
|
||
## Эндпоинты
|
||
|
||
| Метод | URL | Ответ |
|
||
|---|---|---|
|
||
| GET | `/` | HTML с версией |
|
||
| GET | `/.well-known/terraform.json` | `{"providers.v1":"/v1/providers/"}` |
|
||
| GET | `/v1/providers/{ns}/{name}/versions` | JSON: id, versions[], warnings |
|
||
| GET | `/v1/providers/{ns}/{name}/{ver}/download/{os}/{arch}` | JSON: download_url, shasum, GPG ключи |
|
||
| GET | `/v1/proxy?bucket=...&key=...` | Стриминг файла из S3 |
|
||
| GET | `/docs/{ns}/{name}/{ver}/...` | Статика из S3 |
|
||
| GET | `/healthz`, `/readyz` | `"ok"` 200 |
|
||
|
||
---
|
||
|
||
## CI/CD
|
||
|
||
```bash
|
||
# Сборка образа
|
||
docker build -t gitea.services.ngcloud.ru/nail/tf_registry:latest .
|
||
|
||
# Пуш в Gitea Docker Registry
|
||
docker push gitea.services.ngcloud.ru/nail/tf_registry:latest
|
||
|
||
# Редеплой — через UI modify (меняет только CPU/memory/replicas, подхватывает :latest)
|
||
```
|
||
|
||
---
|
||
|
||
## Платформы
|
||
|
||
Детектятся по имени zip-файла:
|
||
- `_darwin_amd64.zip` → macOS Intel
|
||
- `_linux_amd64.zip` → Linux
|
||
- `_windows_amd64.zip` → Windows
|
||
|
||
---
|
||
|
||
## Текущие проблемы
|
||
|
||
1. **S3_PREFIX** — хардкод `registry.kube5s.ru` (TODO в коде)
|
||
2. **modify** — нельзя менять `jsonEnv` в UI (надо просить devops)
|
||
3. **Домен** — `go-registry` вместо `registry` (можно пересоздать)
|