From cf2789be760e57bcae658f85793a30ea27076b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Tue, 1 Sep 2026 12:24:23 +0300 Subject: [PATCH] 1 --- HISTORY/direct-S3-load.md | 290 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 HISTORY/direct-S3-load.md diff --git a/HISTORY/direct-S3-load.md b/HISTORY/direct-S3-load.md new file mode 100644 index 0000000..4debf01 --- /dev/null +++ b/HISTORY/direct-S3-load.md @@ -0,0 +1,290 @@ +Список задач обновлен + +Проверялись следующие 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: `. 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. Больше ничего. +