Ingress возвращает 502: проверяем путь от контроллера до приложения
В браузере открывается 502, хотя Pod приложения выглядит Running. Этот код часто возвращает прокси, который не получил корректный ответ upstream, но точный смысл и журнал зависят от реализации контроллера. Сначала установим, какой компонент сформировал ответ, затем пройдём путь до процесса приложения. Изменение аннотаций другого контроллера только добавит шума.
Находим Ingress и его исполнителя
kubectl -n demo get ingress api -o yaml
kubectl get ingressclass
kubectl -n demo describe ingress apiСопоставьте ingressClassName с controller у IngressClass и установленным компонентом. Kubernetes Ingress описывает маршруты, но сам не принимает HTTP-трафик. Перед ним может находиться внешний балансировщик или CDN, тоже способный вернуть 502. Сохраните время запроса, host, path и доступный request ID; по ним найдите запись в журнале фактического прокси.
Проверьте совпадение Host и path с правилом. Запрос к IP без нужного Host может попасть в default backend и проверять совсем другой маршрут. Для HTTPS важен также SNI, поэтому простая подстановка IP в URL не воспроизводит исходное обращение. Если внешний адрес известен, curl --resolve позволяет сохранить имя URL и выбрать IP.
curl --resolve api.example.com:443:203.0.113.10 --max-time 5 https://api.example.com/readyzДомен и адрес здесь — заполнители. Не отключайте проверку TLS ради получения любого HTTP-кода: иначе вы поменяете условия проверки. Сначала убедитесь, что запрос доходит до ожидаемого контроллера и что его журнал содержит именно этот host и путь.
Проверяем связь правила с Service
В Ingress backend service.port относится к порту Service, а не напрямую к containerPort приложения. Следующая пара показывает согласованное направление 80 → 8080:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api
namespace: demo
spec:
ingressClassName: example-controller
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: api
namespace: demo
spec:
selector: {app: api}
ports:
- port: 80
targetPort: 8080example-controller нужно заменить существующим классом. Обычный backend Service находится в namespace самого Ingress. Посмотрите EndpointSlice Service: появились ли адреса ожидаемых Pod, верен ли порт и готовы ли цели. Отсутствие целей может давать разные HTTP-коды у разных контроллеров, поэтому нельзя считать 502 точным доказательством пустого списка.
kubectl -n demo get service api -o yaml
kubectl -n demo get endpointslice -l kubernetes.io/service-name=api -o yaml
kubectl -n demo get pods -l app=api -o wideПроверяем тот же сетевой источник
Если цели корректны, попробуйте запрос к Pod IP и Service из разрешённого диагностического контейнера в сетевом контексте контроллера. Запрос из рабочего namespace приложения может проходить, а ingress-контроллер из другого namespace — блокироваться NetworkPolicy. Если в самом контейнере контроллера нет shell или curl, используйте согласованный диагностический способ; не устанавливайте пакеты в него на месте.
Connection refused обычно направляет к сокету и порту приложения, timeout — к сети, блокировкам или зависшему обработчику, ошибка TLS upstream — к согласованию протокола. Эти признаки нужно читать в журнале контроллера. Проверьте, действительно ли backend слушает HTTP на 8080: некоторые конфигурации ожидают HTTPS и требуют специфической настройки контроллера. Аннотации разных реализаций не взаимозаменяемы.
Возвращаемся к обычному запросу
Проверьте адрес прослушивания приложения: сервер только на 127.0.0.1 внутри Pod недоступен по Pod IP. Также посмотрите завершение старых Pod во время rollout: прокси мог попытаться использовать уже закрытый сокет. Увеличение тайм-аута не исправит неверный targetPort или протокол. Меняйте тот участок, который подтвердили прямой проверкой.
После исправления повторите исходный HTTPS-запрос с теми же host и path и проверьте журнал backend. Успешный /readyz ещё не гарантирует работу тяжёлого API-метода, поэтому отдельно повторите исходную операцию. Итоговая запись должна называть компонент, вернувший 502, фактическую цель и причину отказа соединения; правило backend Ingress помогает связать эти наблюдения в один маршрут.
Ещё по теме
- DNS в Kubernetes отвечает медленно: проверяем CoreDNS, search и ndots
- Forbidden в Kubernetes: проверяем ServiceAccount, Role и RoleBinding
Продолжить изучение
Хотите увереннее разворачивать приложения и разбирать сбои в кластере? Сети, конфигурация, хранилища и обновления входят в программу «Kubernetes с нуля до PRO».
Продолжить на практике
- Kubernetes с нуля до PRO ↗
Разворачивайте и сопровождайте приложения в Kubernetes: от первого Pod до релизов, сетей, хранилищ, масштабирования и диагностики. Итоговый проект — сервис с базой данных, мониторингом и проверенным откатом.
