Files
SQS-service/doc/errors/65kb-payload-timeout-2026-04-11.md
T

136 lines
7.2 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.
# Error Log: 65KB+ Payload Timeout — 2026-04-11
## Update — 2026-04-12
После дополнительного расследования в кластере инцидент переклассифицирован.
### Финальный статус
- shared-sqs backend **не является** первичной причиной зависания;
- проблема локализована на стороне **platform ingress path**;
- конкретно: ingress controller штурвала **не применяет** `nginx.ingress.kubernetes.io/proxy-request-buffering: "off"`, хотя upstream ingress-nginx эту аннотацию поддерживает;
- часть других аннотаций при этом применяется корректно, значит речь не о полном игноре ingress-ресурса, а о selective handling/bug/platform override.
### Дополнительные подтверждения
1. Для host `qu.kube5s.ru` существует только один ingress — `shared-sqs-ingress`, значит это не конфликт нескольких ingress-объектов.
2. В объекте ingress аннотация `proxy-request-buffering: "off"` присутствует.
3. В итоговом `nginx.conf` для `qu.kube5s.ru` остаётся `proxy_request_buffering on;`.
4. В шаблоне контроллера `/etc/nginx/template/nginx.tmpl` директива не захардкожена; там используется значение `location.Proxy.RequestBuffering`, то есть проблема происходит до фазы рендеринга финального location config.
5. `server-snippet`/`configuration-snippet` нельзя считать рабочим обходным путём без platform-level изменений, так как snippet-аннотации контролируются `allow-snippet-annotations`, а по умолчанию этот режим отключён.
### Операционный вывод
Это **известное ограничение инфраструктуры**, а не дефект бизнес-логики shared-sqs.
### Итоговое решение
- hard-limit 32KB в код shared-sqs **не внедряется**;
- 32KB остаётся **практической рекомендацией** для AWS CLI/botocore-клиентов в текущей инфраструктуре;
- приоритет дальнейших работ по этой теме переносится с shared-sqs на platform ingress controller.
## Симптом
SendMessage с телом ≥64740 байт зависает на 10-52 секунды и возвращает ошибку (ConnectionClosedError / exit=254).
**Воспроизведение:**
```bash
# Генерим payload 65KB
python3 -c "print('A'*65536)" > /tmp/big.txt
# Отправляем через AWS CLI — зависает на ~52 секунды
aws --endpoint-url https://qu.kube5s.ru sqs send-message \
--queue-url "https://qu.kube5s.ru/TENANT_ID/QUEUE_NAME" \
--message-body "file:///tmp/big.txt"
```
## Диагностика
### 1. Сервер — OK
Port-forward (обход nginx): 65KB за 831ms. Сервер не виноват.
### 2. nginx ingress — частично виноват
`client_body_timeout: 10s` — nginx закрывает соединение если тело не пришло за 10 секунд.
### 3. Root Cause — botocore + urllib3 2.0 + TLS + Nagle
**urllib3 2.0** посылает headers и body двумя отдельными `send()`:
```
send#1: len=774 (headers)
send#2: len=65629 (body)
```
**botocore** ставит `socket_options=[]` → убирает `TCP_NODELAY` → Nagle ON.
**Body** шифруется TLS в 4 записи по ~16KB. Первые 3 уходят, 4-я **застревает** из-за Nagle + delayed ACK deadlock.
**nginx access.log:**
```
POST status=408 req_len=49926 bytes_sent=0 time=10.001s
```
Получено 49926 байт = headers(774) + 3 × TLS(~16384). Не хватает ровно 1 TLS-записи.
### 4. Порог
| Размер | Время | Статус |
|--------|-------|--------|
| 64000B | 825ms | ✅ |
| 64720B | 799ms | ✅ |
| 64740B | 30806ms | ❌ intermittent |
| 65536B | 51843ms | ❌ всегда |
### 5. Версии ПО
| Компонент | Версия |
|-----------|--------|
| nginx ingress | shturval-ingress-controller v1.12.6 |
| AWS CLI | v2.34.27 |
| AWS CLI Python | 3.14.3 (bundled) |
| System Python | 3.12.3 |
| System urllib3 | 2.0.7 |
| System botocore | 1.42.86 |
## Что пробовали
### Помогло частично:
- **ConfigMap `client-body-timeout: "120"`** — pip boto3 (Python 3.12) стал работать (84ms → 13ms)
- **ConfigMap `client-body-buffer-size: "2m"`** — применилось глобально
### Не помогло:
- **Аннотация `proxy-request-buffering: "off"`** — shturval controller не применяет
- **`server-snippet: client_body_timeout 120s;`** — применилось но AWS CLI всё равно зависает
- **TCP_NODELAY patch через monkey-patch** — нестабильно (1-й запрос fails)
## Решение
Кодовый hard-limit не вводим.
Практическое правило эксплуатации:
- для AWS CLI / botocore в текущей ingress-инфраструктуре безопасно ориентироваться на 32KB;
- протокольный лимит SQS остаётся 256KB;
- проблема 64KB+ описывается как platform ingress limitation.
См. [решение](../decisions/message-size-limit-2026-04-11.md).
## Статус
✅ Исследование завершено. Root cause локализован до platform ingress layer; изменение в коде shared-sqs не требуется.
## Внешние ссылки
Для следующего захода в проблему использовать эти ссылки как стартовые:
- Штурвал Community Edition, архитектура платформы:
https://docs.k8s.ngcloud.ru/2.12/docs/common/structure/
- ingress-nginx annotations:
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
- ingress-nginx configmap options:
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
- parser `proxy-request-buffering` в upstream ingress-nginx:
https://github.com/kubernetes/ingress-nginx/blob/main/internal/ingress/annotations/proxy/main.go
- e2e test `should turn off proxy-request-buffering`:
https://github.com/kubernetes/ingress-nginx/blob/main/test/e2e/annotations/proxy.go
Краткий смысл ссылок:
- Штурвал: подтверждает, что Nginx Ingress Controller является частью platform stack;
- ingress-nginx docs/source: подтверждают, что `proxy-request-buffering` — штатная поддерживаемая фича upstream, а значит текущее поведение похоже именно на platform-specific limitation/bug.