Выберите продукт

Kubernetes Ingress: 413 Request Entity Too Large — увеличиваем лимит загрузки в Nginx Ingress и на backend

Ошибка 413 Request Entity Too Large при загрузке файлов через Kubernetes Ingress обычно появляется из‑за лимитов на размер тела запроса в Nginx Ingress Controller, внешнем прокси или на backend. Разберём, как найти слой-источник 413 и безопасно поднять лимит.
Kubernetes Ingress: 413 Request Entity Too Large — увеличиваем лимит загрузки в Nginx Ingress и на backend

Ошибка 413 Request Entity Too Large при загрузке файлов через Kubernetes Ingress — типичная ситуация: приложение «умеет» принимать большие файлы, но один из прокси-слоёв по дороге режет запрос по лимиту client_max_body_size (или аналогу). В кластере слоёв часто несколько: внешний балансировщик, nginx ingress controller, сервисная сетка/sidecar-прокси, а дальше ещё и ваш backend (Nginx/Apache/Node/PHP/FastAPI и т. д.).

Ниже — практичный разбор: как понять, где именно возникает 413, какие настройки отвечают за лимит загрузки, какие аннотации Nginx Ingress использовать (включая nginx.ingress.kubernetes.io/proxy-body-size), и как проверить, что лимит увеличился там, где нужно.

Что означает 413 и почему в Kubernetes это «слоёный пирог»

413 Request Entity Too Large означает: сервер (или прокси перед ним) отказывается принимать тело запроса, потому что оно превышает допустимый размер. Для загрузок это почти всегда POST/PUT с большим Content-Length или chunked-upload.

Типовой маршрут в Kubernetes выглядит так:

Клиент → (Cloud LB / reverse proxy) → Ingress Controller → Service → Pod → (внутренний прокси/приложение)

Лимит может стоять на любом звене. Важно: если поднять лимит только на ingress-слое, но дальше (внутри pod’а) есть свой Nginx/Apache/приложение с меньшим лимитом, вы всё равно получите ошибку, просто «чуть позже» по цепочке.

Быстрая диагностика: кто именно отдаёт 413

1) Смотрим ответ и заголовки

Часто Nginx отдаёт типовую HTML-страницу ошибки и заголовок Server: nginx. Но это не доказательство, что виноват именно Ingress: Server может совпадать и у внешнего прокси, и у внутреннего Nginx в pod’е.

curl -i -X POST https://example.com/upload -F file=@big.iso

Если запрос слишком большой, вы увидите 413. Дальше — ищем, где он возник: по логам и по «наличию следов» запроса на каждом слое.

2) Проверяем логи Nginx Ingress Controller

Найдите namespace и pod контроллера (часто ingress-nginx), затем посмотрите логи за последние минуты:

kubectl -n ingress-nginx get pods
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller --since=10m

Если лимит сработал на ingress-слое, в логах Nginx обычно видно сообщение вида:

client intended to send too large body

Если в логах ingress «тишина», но клиент стабильно получает 413, вероятны два сценария: 413 возвращает внешний балансировщик/прокси перед кластером или backend (например, Nginx внутри pod’а).

3) Проверяем логи backend

Посмотрите логи pod’а приложения (или внутреннего веб-сервера, если он есть):

kubectl -n app get pods
kubectl -n app logs pod/my-app-7c9d6b6b6f-abcde --since=10m

Если у вас внутри pod’а Nginx, то 413 может быть именно от него — и тогда настройки Ingress сами по себе не помогут.

Схема слоёв, где может возникать 413: внешний прокси, Ingress, backend

Самая частая причина: лимит в Nginx Ingress Controller

В Nginx лимит на размер тела запроса задаёт директива client_max_body_size. В мире Ingress её обычно настраивают аннотацией nginx.ingress.kubernetes.io/proxy-body-size.

Проверьте ваш Ingress и добавьте аннотацию на нужный хост/путь:

kubectl -n app get ingress my-app -o yaml

Пример Ingress (как текст). Обратите внимание на nginx.ingress.kubernetes.io/proxy-body-size:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: app
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app
            port:
              number: 80

Значения задаются в единицах Nginx: k, m, g. Практика: начинайте с реалистичного предела (например, 20–100 МБ), а не с «безлимита».

Как убедиться, что аннотация реально применена

Ingress Nginx генерирует конфиг автоматически. После изменения Ingress контроллер должен подхватить обновления. Чтобы убедиться, что лимит попал в конфиг нужного виртуального хоста, можно вывести полный конфиг и найти свой server-блок по домену:

kubectl -n ingress-nginx exec -it deploy/ingress-nginx-controller -- nginx -T

В выводе проверьте, что для вашего хоста присутствует client_max_body_size с ожидаемым значением.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Глобальный лимит: ConfigMap контроллера против аннотаций

Иногда удобнее задавать лимит «по умолчанию» для всего контроллера, а аннотациями переопределять только исключения. Это делается через ConfigMap ingress-nginx.

Логика простая:

  • ConfigMap — базовые значения «для всех».
  • Аннотации — точечная настройка конкретного Ingress.

На практике лимит тела запроса чаще держат именно в аннотации nginx.ingress.kubernetes.io/proxy-body-size, потому что она привязана к конкретному приложению и снижает риск случайно «разрешить всем грузить всё».

Если у вас мульти-tenant кластер, избегайте глобального снятия ограничений: большие тела запросов увеличивают риск DoS по памяти/диску и делают нагрузку менее предсказуемой.

Не забудьте про backend: Nginx/Apache/приложение тоже может резать

Даже если Ingress пропускает 100 МБ, backend может вернуть ошибку на своей стороне. Дальше — самые частые места.

Если внутри pod’а тоже Nginx

Проверьте конфигурацию внутреннего Nginx: там тоже может быть client_max_body_size. Типовая ловушка: Ingress подняли до 50m, а внутри pod’а остался более низкий лимит.

Пример (как текст):

server {
  listen 80;
  client_max_body_size 50m;
  location / {
    proxy_pass http://127.0.0.1:8080;
  }
}

Если внутренний Nginx используется как sidecar/reverse-proxy — лимит нужно поднять и там.

Если backend — PHP-FPM

В PHP-стеке ограничения обычно задают upload_max_filesize и post_max_size. Иногда это проявляется не как 413, а как 400/500 (зависит от связки и обработки ошибок), поэтому важно смотреть логи приложения и PHP-FPM.

Совет по эксплуатации: согласуйте лимиты на всех уровнях, иначе можно получить частичные загрузки, обрывы и неочевидные ошибки в приложении.

Если backend — Node.js / Java / Python

У многих фреймворков и библиотек есть свои лимиты на body/multipart:

  • Node.js/Express: ограничения middleware (например, для multipart).
  • Spring Boot: multipart limits.
  • Django/Flask/FastAPI: ограничения middleware/ASGI/WSGI и настройки сервера (gunicorn/uvicorn).

Поднимайте лимит синхронно: Ingress → внутренний прокси (если есть) → приложение.

Особый случай: 413 от внешнего балансировщика или прокси перед кластером

Если перед Kubernetes стоит внешний Nginx/HAProxy/балансировщик облака, 413 может прилетать ещё до Ingress. Типовые признаки:

  • в логах ingress-controller нет следов запроса;
  • в ответе видны заголовки/страница внешнего прокси;
  • ошибка воспроизводится даже при обращении к другому Ingress.

Тогда лимит нужно поднимать и на внешнем уровне (для внешнего Nginx это снова client_max_body_size).

Проверка после изменений: как убедиться, что всё работает

1) Тестируем реальный размер

Сделайте тестовый файл нужного размера и отправьте через curl. Например, на Linux:

fallocate -l 60M test.bin
curl -i -X POST https://example.com/upload -F file=@test.bin

Если 413 ушла — это только половина успеха. Убедитесь, что загрузка действительно дошла до приложения и корректно обработалась: проверьте логи, итоговый объект/файл, checksum (если применимо).

2) Следим за таймаутами при больших файлах

Большие загрузки часто упираются не только в лимит размера, но и в таймауты (медленный канал, долгий TLS, перегруз upstream). Если после поднятия лимита вы начали видеть 504/499 — это уже другая ветка диагностики: таймауты ingress, таймауты upstream, буферизация и скорость чтения тела.

Если вы выбираете контроллер/архитектуру ingress под разные сценарии, полезно сравнить варианты в статье какой Ingress-контроллер выбрать: Traefik, Nginx или HAProxy.

Проверка 413 через curl и просмотр логов контроллера Ingress

Про безопасность и эксплуатацию: почему «поставить безлимит» — плохая идея

Сильно завышенный лимит (или попытка сделать «без ограничений») в Kubernetes почти всегда аукнется:

  • ростом потребления памяти на ingress-нодах при параллельных загрузках;
  • дополнительной нагрузкой на сеть и диски (если есть временные файлы/буферизация);
  • сложностями с защитой от намеренных «заливок».

Практичный подход: ставьте лимит чуть выше реальной потребности, а для «тяжёлых» сценариев (видео, архивы, бэкапы) используйте отдельную архитектуру загрузки: прямую загрузку в объектное хранилище по pre-signed URL, chunked/resumable upload на уровне приложения, выделенный домен/ingress с отдельными политиками.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Чеклист: где проверять лимиты при 413

  1. Внешний прокси/балансировщик перед кластером: есть ли там лимит тела запроса (для Nginx это client_max_body_size).

  2. Nginx Ingress Controller: аннотация nginx.ingress.kubernetes.io/proxy-body-size на Ingress (или дефолты через ConfigMap, если вы так стандартизируете).

  3. Внутренний reverse-proxy в pod’е (если есть): client_max_body_size (или аналог в Apache/Envoy).

  4. Сам backend: лимиты multipart/body у фреймворка и рантайма.

  5. Валидация: логи ingress + логи приложения + тестовый upload на нужный размер.

Типовые значения и практические рекомендации

Часто встречаемые ориентиры:

  • админка CMS с загрузкой медиа: 20–100 МБ;
  • импорт/экспорт данных: 50–200 МБ (но лучше делать асинхронно);
  • крупные файлы: отдельный контур загрузки, а не «увеличить лимит везде».

Если вы ведёте несколько проектов в одном кластере, удобнее стандартизировать лимиты: базовый небольшой и точечные исключения аннотациями. Так Ingress не превращается в «воронку», куда можно залить что угодно.

Заключение

413 Request Entity Too Large в Kubernetes почти никогда не лечится «одной магической настройкой»: нужно точно определить слой, который режет запрос, и согласованно поднять лимит на этом слое и ниже по цепочке. Для Nginx Ingress ключевой инструмент — аннотация nginx.ingress.kubernetes.io/proxy-body-size, которая в итоге управляет client_max_body_size в сгенерированном конфиге.

Если помимо Ingress у вас есть внешний прокси, уделите внимание ещё и доменной/SSL-части (сертификаты, HSTS, миграции домена), чтобы избежать неожиданных обрывов при загрузках и редиректах: см. переезд домена: 301, HSTS и SSL без потерь. Для проектов в продакшене это часто всплывает одновременно с настройкой ingress.

Если проект крутится на своих серверах и вы строите кластер под себя, удобнее держать ingress и приложения на выделенных ресурсах, чтобы лимиты и нагрузка были предсказуемыми: для этого обычно берут VDS под Kubernetes-ноды и отдельные ingress-узлы.

Поделиться статьей

Вам будет интересно

Linux: Read-only file system (ro) — почему ext4/XFS внезапно становятся только для чтения и как восстановить OpenAI Статья написана AI (GPT 5)

Linux: Read-only file system (ro) — почему ext4/XFS внезапно становятся только для чтения и как восстановить

Файловая система внезапно стала read-only (ro): приложения падают, обновления не ставятся, данные не пишутся. Разберём, что вызыва ...
CAA и ACME: как DNS ограничивает выпуск SSL (issue/issuewild) и что ломает Let's Encrypt OpenAI Статья написана AI (GPT 5)

CAA и ACME: как DNS ограничивает выпуск SSL (issue/issuewild) и что ломает Let's Encrypt

CAA-записи в DNS задают, какие центры сертификации могут выпускать сертификаты для домена. Разберём теги issue/issuewild, как CA и ...
PostgreSQL: could not access status of transaction (wraparound) — диагностика и восстановление OpenAI Статья написана AI (GPT 5)

PostgreSQL: could not access status of transaction (wraparound) — диагностика и восстановление

Ошибка «could not access status of transaction» в PostgreSQL часто идёт рядом с XID wraparound: растёт age(datfrozenxid), autovacu ...