У меня возникают проблемы с настройкой глобального балансировщика нагрузки GCP, используя GKE, NGINX (обслуживание фронтенда React) и бэкенд Flask. Балансировщик нагрузки постоянно возвращает 503 No Healthy Upstream
, хотя сервисы, похоже, работают корректно внутри кластера.
Настройка:
- Фронтенд: React, обслуживаемый через NGINX
- Бэкенд: Flask (Python 3.11), работающий на GKE
- Балансировщик нагрузки: Глобальный HTTP(S) балансировщик нагрузки GCP с SSL
Проблема:
Несмотря на то, что всё выглядит функциональным внутри кластера, балансировщик нагрузки продолжает отмечать мои экземпляры бэкенда как нездоровые, что приводит к ошибке 503. Выполнение curl для бэкенд-сервиса изнутри кластера работает без проблем, но балансировщик нагрузки неправильно передает трафик.
Детали конфигурации:
Конфигурация NGINX:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri /index.html;
}
location /health {
proxy_pass http://backend-service.default.svc.cluster.local:80/health;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
}
Dockerfile для NGINX/Фронтенда:
# Стадия 1: Построение приложения React
FROM node:16-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . ./
RUN npm run build
# Стадия 2: Обслуживание через NGINX
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Dockerfile для бэкенда (Flask):
FROM python:3.11-slim
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
EXPOSE 80
CMD ["gunicorn", "--bind", "0.0.0.0:80", "run:app"]
Service YAML (Бэкенд):
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: backend
status:
loadBalancer:
ingress:
- ip: 1.2.3.4
Что я уже попробовал:
-
Проверки работоспособности:
- Проверки работоспособности настроены на обращение к
/health
на порту 80, и они работают внутри кластера (200 OK
). - Внешние проверки работоспособности от балансировщика нагрузки терпят неудачу, отмечая все экземпляры как нездоровые.
- Проверки работоспособности настроены на обращение к
-
Правила брандмауэра:
- Правила входящего трафика настроены для разрешения входящего трафика на портах 80 и 443 от всех IP.
-
Конфигурация SSL:
- SSL-сертификат выдан и активен для домена.
- Обращение к HTTPS конечной точке напрямую приводит к ошибке
503
с сообщениемno healthy upstream
.
-
Тестирование внутри кластера:
- Обращение к бэкенд-сервису из фронтенд-пода работает без проблем:
kubectl exec -it frontend-pod -- curl http://backend-service.default.svc.cluster.local/health {"status":"ok"}
-
DNS и SSL:
- Домен настроен с использованием GCP Cloud DNS, указывающим на правильный IP (1.2.3.4).
- SSL-сертификат успешно выдан для домена.
Текущее поведение:
- Внутренние проверки работоспособности от GCP продолжают терпеть неудачу.
- Обращение к бэкенд-сервису изнутри кластера работает, но балансировщик нагрузки считает экземпляры нездоровыми.
- Любая попытка доступа к сервису извне через балансировщик нагрузки приводит к ошибке 503 (
no healthy upstream
).
Вопросы:
- Почему балансировщик нагрузки постоянно отмечает бэкенд как нездоровый, даже несмотря на то, что внутренние проверки работоспособности проходят?
- Существует ли конкретная настройка GKE или балансировщика нагрузки, которую я могу пропустить?
- Как я могу решить проблему
503 No Healthy Upstream
с этой конфигурацией?
Ответ
Ваш вопрос касается проблемы с GCP глобальным балансировщиком нагрузки, который постоянно возвращает ошибку 503 (No Healthy Upstream) в вашем окружении GKE с использованием NGINX для фронтенда и Flask для бэкенда. Давайте разберёмся с вашей конфигурацией и вероятными причинами проблемы.
Причины проблемы и их решение
-
Проблемы с проверкой состояния:
- Поскольку вы сообщаете, что внешние проверки состояния от балансировщика нагрузки не проходят, вам следует убедиться, что проверки состояния настроены правильно. Проверьте URL, на который совершает запрос балансировщик. Он должен точно соответствовать тому, что вы используете в вашем приложении (например,
/health
). - Убедитесь, что ваш маршрут
/health
не защищён аутентификацией или требует специфических заголовков, которые могут блокировать запросы от балансировщика.
- Поскольку вы сообщаете, что внешние проверки состояния от балансировщика нагрузки не проходят, вам следует убедиться, что проверки состояния настроены правильно. Проверьте URL, на который совершает запрос балансировщик. Он должен точно соответствовать тому, что вы используете в вашем приложении (например,
-
Настройки сервиса Kubernetes:
- Убедитесь, что ваш сервис, обозначенный как
LoadBalancer
, правильно настроен для работы с вашими контейнерами Flask. Попробуйте добавитьtargetPort
вService
YAML для проверки, чтобы убедиться, что он указывает на действительно используемый порт в вашем контейнере Flask. Если вы используете 80 вEXPOSE
вашего Dockerfile, это должно сработать, но стоит дважды проверить.
- Убедитесь, что ваш сервис, обозначенный как
-
Firewall и маршрутизация:
- Убедитесь, что у вас есть правила брандмауэра, позволяющие входящий трафик на нужные порты (80 и 443). Вы можете использовать следующее:
gcloud compute firewall-rules create allow-http --direction=INGRESS --priority=1000 --network=default --action=ALLOW --rules=tcp:80 --source-ranges=0.0.0.0/0 gcloud compute firewall-rules create allow-https --direction=INGRESS --priority=1000 --network=default --action=ALLOW --rules=tcp:443 --source-ranges=0.0.0.0/0
- Убедитесь, что у вас есть правила брандмауэра, позволяющие входящий трафик на нужные порты (80 и 443). Вы можете использовать следующее:
-
SSL конфигурация:
- Если вы используете SSL с балансировщиком и у вас проблемы с ним, попробуйте временно отключить SSL и проверить, решит ли это проблему 503. Это поможет изолировать, является ли проблема связанной с подключением HTTPS.
- Проверка логов:
- Проверьте логи вашего приложения Flask и NGINX, чтобы найти ошибки, которые могут помочь диагностировать проблему. Логи могут содержать подсказки о том, почему запросы не обрабатываются должным образом.
Защита от ошибок 503 No Healthy Upstream
- Настройка проверок состояния:
Убедитесь, что проверки состояния настроены на правильный маршрут. Пример настройки может выглядеть следующим образом:
healthCheck:
type: HTTP
port: 80
requestPath: /health
checkIntervalSec: 10
timeoutSec: 5
healthyThreshold: 2
unhealthyThreshold: 2
- Обеспечение доступности Flask сервера:
Убедитесь, что ваш Flask сервер работает и слушает на порту, на который настроен балансировщик нагрузки.
Заключение
Следуя вышеописанным шагам, вам следует провести тесты на каждом уровне (проверки от GCP, правильная конфигурация NGINX, настройки сервиса Kubernetes) для диагностики и устранения проблемы. Если всё ещё не удаётся устранить проблему, имеет смысл проверить официальную документацию GCP и GKE на предмет несовпадений в версиях или дополнительных настроек, которые могут потребоваться для вашей конкретной конфигурации.