Files
tf_registry/HISTORY/direct-S3-load.md
T
2026-09-01 12:24:23 +03:00

291 lines
10 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.
Список задач обновлен
Проверялись следующие endpoint’ы registry:
```text
https://tf-registry.containerk8s.services.ngcloud.ru/.well-known/terraform.json
```
Результат: `HTTP 200`
```json
{"providers.v1":"/v1/providers/"}
```
Список версий:
```text
https://tf-registry.containerk8s.services.ngcloud.ru/v1/providers/nubes-test/nubes/versions
```
Результат: `HTTP 200`
Опубликованы:
```text
5.0.1
5.0.2
5.0.3
5.0.4
5.0.5
5.1.17
```
Download metadata для `5.0.5`:
```text
https://tf-registry.containerk8s.services.ngcloud.ru/v1/providers/nubes-test/nubes/5.0.5/download/linux/amd64
```
Результат: `HTTP 200`, ответ около `8 KB`, содержит:
```text
filename:
terraform-provider-nubes_5.0.5_linux_amd64.zip
download_url:
https://tf-registry.containerk8s.services.ngcloud.ru/v1/proxy?key=...
```
Фактический proxy URL:
```text
https://tf-registry.containerk8s.services.ngcloud.ru/v1/proxy?key=tf-registry.containerk8s.services.ngcloud.ru%2Fnubes-test%2Fnubes%2F5.0.5%2Fterraform-provider-nubes_5.0.5_linux_amd64.zip
```
Проверка proxy:
```text
HTTP: 200
Content-Type: application/octet-stream
Content-Length: 13083236
```
Но фактически за 40 секунд скачалось только:
```text
20983 байт
```
и затем:
```text
curl: (28) Operation timed out
```
Дополнительно проверялись:
```text
nubes-test/nubes:5.1.17
nubes/nubes:2.0.6
```
На них результат такой же: metadata отдается быстро, а ZIP через `/v1/proxy` обрывается примерно на `18–23 KB`.
Проверялся также заголовок:
```text
Range: bytes=0-1023
```
и диапазон из середины файла:
```text
Range: bytes=1048576-1049599
```
Proxy игнорирует `Range`, отвечает `HTTP 200` и снова начинает отдавать весь файл, после чего передача зависает.
Проверка DNS:
```text
getent hosts tf-registry.containerk8s.services.ngcloud.ru
```
Результат:
```text
5.172.178.231
```
Также проверялся Kubernetes API:
```text
kubectl get ingress -A
kubectl get pods -A
kubectl get svc -A
kubectl get deploy -A
kubectl get configmap -A
```
Но текущий kubeconfig не имеет credentials:
```text
the server has asked for the client to provide credentials
Unauthorized
```
Итог: API registry и metadata работают. Проблемный участок:
```text
/v1/proxy -> S3 object -> HTTP streaming через Kubernetes
```
Именно там большой ZIP возвращается с `HTTP 200`, но поток фактически обрывается на десятках килобайт.
Список задач обновлен
Read
Read memory
Read , lines 1 to 80
Read , lines 1 to 80
Read , lines 1 to 80
Теперь у меня есть контекст по drhider. Давай сравню симптомы:
Read
Read
## Анализ: сравнение проблем drhider и registry
### Проблема в drhider (решена)
| Аспект | Детали |
|--------|--------|
| Симптом | POST из браузера → тело запроса обрывалось на ~64КБ (HTTP 000, ~10с) |
| Направление | **Входящий** трафик: браузер → кластер |
| Корень | Managed-кластер, шлюз ingress обрывает тела входящих запросов >64КБ |
| Решение | Браузер PUT файл на ВМ-буфер (обходит шлюз) → Flask тянет с ВМ (egress, без лимита) |
### Проблема в registry (сейчас)
| Аспект | Детали |
|--------|--------|
| Симптом | `GET /v1/proxy?key=...` → HTTP 200 мгновенно, но данные обрываются на 18–23 КБ |
| Направление | **Исходящий** трафик: кластер → Terraform клиент |
| Корень | Тот же кластерный шлюз, но теперь режет **streaming-ответ** (буферизация / flush-лимит) |
### Это та же проблема?
**Да, вероятно одна и та же инфраструктура** (`services.ngcloud.ru` — managed Nubes, тот же managed-кластер что и `pythonk8s.dev.nubes.ru`). Только направление противоположное:
- drhider: шлюз режет входящее тело
- registry: шлюз режет исходящий stream большого файла
Дополнительный признак: у вас есть ещё одна задокументированная проблема — HTTP/2 резал git push к gitea (тот же шлюз, тот же паттерн). Range-запросы игнорируются — тоже поведение промежуточного буферизующего прокси.
---
### Применим ли обход через ВМ?
**Да, но схема зеркальная.** В drhider проблема была на входе — данные шли в кластер. Здесь проблема на выходе — данные идут из кластера к Terraform.
**Варианты обхода:**
**Вариант A — Redirect на S3 pre-signed URL (чище всего)**
`/v1/proxy` вместо стриминга генерирует временную pre-signed S3 ссылку и возвращает `302 Location: <s3-presigned-url>`. Terraform следует редиректу и скачивает ZIP напрямую с S3, минуя кластерный шлюз полностью.
```
Terraform → /v1/proxy?key=... → 302 Location: https://s3.../object?X-Amz-Expires=...
Terraform → S3 напрямую → 200 + 13MB ✅
```
Terraform `go-getter` (используется в `terraform init`) редиректы поддерживает.
**Вариант B — Redirect на ВМ-прокси**
Если S3 не публичный / нет pre-signed URL — `/v1/proxy` отдаёт `302` на эндпоинт ВМ (`contracts.kube5s.ru/tf-proxy?key=...`). ВМ скачивает файл с S3 и стримит Terraform клиенту. ВМ находится вне шлюза managed-кластера.
**Вариант C — Через download_url в metadata (самое прозрачное)**
Вместо того чтобы `download_url` указывал на `/v1/proxy` внутри кластера — указывать сразу на S3 pre-signed URL или ВМ-прокси. Не нужно менять `/v1/proxy` вообще.
---
### Рекомендация
Вариант A или C — наиболее чистые. Смотреть, есть ли доступ к S3 с кредами для pre-signed URL из кода registry. Если есть — минимальное изменение: в `/v1/proxy` заменить стриминг на `redirect(presigned_url, 302)`.
Нужно смотреть код registry (`/v1/proxy` handler) чтобы подтвердить технически — он в этом же репозитории или в отдельном?
Создано задач: 3
Список задач обновлен
Read
Read
Read
Read
Read
Read
Read
Картина полная. Вот анализ:
---
## Диагностика: та же проблема, другая сторона
**Код проблемы — `proxy.go`, `proxyHandler`:**
```go
obj, _ := s3Client.GetObject(ctx, bucketName, key, ...)
io.Copy(w, obj) // ← Kubernetes шлюз режет этот stream
```
Тот же managed-кластер (`containerk8s.services.ngcloud.ru` — Nubes), тот же шлюз. В drhider он резал входящие тела >64KB. Здесь режет исходящий stream с S3 (~18–23KB — это первый буфер ответа, который шлюз успел пропустить до блокировки).
`Content-Length: 13083236` выставляется, но данных доходит ~20KB — шлюз буферизует и не флашит остаток.
---
## Решение: presigned URL redirect
`minio-go` уже импортирован, он умеет генерировать pre-signed URL:
```go
// вместо GetObject + io.Copy:
presigned, err := s3Client.PresignedGetObject(ctx, bucketName, key, 15*time.Minute, url.Values{})
http.Redirect(w, r, presigned.String(), http.StatusFound)
```
Terraform следует 302. Terraform client скачивает ZIP **напрямую с S3**, кластерный шлюз больше не участвует.
Это затрагивает только `proxy.go` — 1 файл, примерно 10 строк замены.
`ShasumsURL` и `ShasumsSignatureURL` тоже идут через `/v1/proxy` — они маленькие (<10KB), работают и сейчас, но с redirect тоже будут работать корректно.
---
## План
**Файл:** server/proxy.go
**Изменение:** в `proxyHandler` — убрать `GetObject` / `Stat` / `io.Copy` / установку заголовков, заменить на `PresignedGetObject` + `http.Redirect 302`. Добавить `"net/url"` в imports.
**Верификация:**
1. `go build `nubes`.` — компиляция
2. `curl -v 'https://...registry.../v1/proxy?key=...' -L` — должен получить 302, затем скачать 13MB полностью
3. `terraform init` в тестовом проекте с этим провайдером
Делать?
Создано задач: 4
НИЧЕГО НЕ ДЕЛАЙ. КРАТКО ОТВЕТ ДАВАЙ - это надо менять код регистри ? и всё ?
10:03
Да. Только server/proxy.go — заменить стриминг на redirect к pre-signed S3 URL. Больше ничего.