Вопрос или проблема
В данный момент я мигрирую внутреннее приложение с docker на podman и мне приходится немного “умнеть”.
Каждый пользователь, обращающийся к приложению, должен иметь настроенные upstream и location, И контейнер podman должен быть запущен. Из-за природы приложения мы не можем гарантировать, что контейнер podman для пользователя будет действительно запущен в любой момент, хотя у нас будут определения для nginx location и upstream.
Пример директивы upstream выглядит следующим образом:
upstream goober_one_area {
server goober_one_container:8080;
}
А location выглядит так:
location /goober_one {
rewrite /goober_one/(.*) /$1 break;
proxy_pass http://goober_one_area;
proxy_intercept_errors on;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
#proxy_set_header X-Forwarded-Proto $scheme;
# Поддержка WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Accept-Encoding gzip;
proxy_redirect off;
}
Когда goober_one_container
не запущен, я, конечно, получаю [emerg] 1#1: host not found in upstream "goober_one_container:8080" in /etc/nginx/conf.d/environments/goober_one.upstream.conf:2
. Это имеет смысл.
Чтобы исправить это, идея заключалась в том, чтобы создать приложение flask с одним представлением, которое будет использоваться как резервное, так что, если хост не может быть найден в upstream, оно просто перейдет к этому приложению flask, которое предоставит информацию о ситуации. Я настроил это в своем файле docker-compose.yml, который я запускаю через podman compose, и эта часть работает нормально, но изменение определения upstream на:
upstream goober_one_area {
server goober_one_container:8080;
server fallback:8080 backup;
}
не приносит результатов. Несмотря на то, что fallback:8080
запущен, доступен и служит предпосылкой для запуска nginx, он просто обращается к goober_one_container:8080
и прекращает выполнение.
Как мне заставить это перейти к следующему серверу, когда основной контейнер недоступен?
Ответ или решение
Чтобы обеспечить надежность работы вашего приложения с использованием Nginx и Podman, необходимо правильно настроить обработку запросов к upstream-серверам, особенно когда основной сервер недоступен. Давайте разберем, как это сделать.
Проблема
Согласно вашему описанию, Nginx не может разрешить имя хоста goober_one_container:8080
, если контейнер не запущен, что приводит к ошибке. При этом, у вас уже есть доступный резервный сервер fallback:8080
, который вы хотели бы использовать в случае недоступности основного сервера.
Решение
Для того чтобы настроить Nginx на использование резервного сервера, необходимо внести изменения в конфигурацию. Однако, важно понимать, что резервный сервер, обозначенный как backup
, будет использован только в том случае, если все другие серверы в upstream не доступны из-за ошибки, а не из-за того, что Nginx не может их разрешить.
Когда Nginx пытается разрешить имя хоста goober_one_container
, если контейнер не работает, это приводит к ошибке, и Nginx не сможет даже начать.
Шаги по исправлению
-
Замена имени хоста: Убедитесь, что неверные конфигурации, такие как имя контейнера, действительно разрешаются до запуска Nginx. Вы можете использовать IP-адрес контейнера или локальный адрес, если он доступен.
-
Настройка конфигурации upstream:
Замена вашегоupstream
блока на следующее:upstream goober_one_area { server goober_one_container:8080; server fallback:8080 backup; }
-
Обработка исключений:
Ваша конфигурация location должна быть дополнена следующими директивами:location /goober_one { rewrite /goober_one/(.*) /$1 break; proxy_pass http://goober_one_area; proxy_intercept_errors on; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; proxy_next_upstream_tries 3; proxy_next_upstream_timeout 10s; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; # Поддержка WebSocket proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Accept-Encoding gzip; proxy_redirect off; error_page 502 = @fallback; } location @fallback { proxy_pass http://fallback:8080; }
Пояснение
-
Ошибка 502: Если
goober_one_container
недоступен, Nginx будет возвращать ошибку 502. С директивойerror_page
выставляем страницу замены, которая указывает на резервный серверfallback
. -
Обработка запросов: Это настроит Nginx так, что в случае ошибки 502 запрос автоматически перенаправляется на резервный сервер.
Заключение
С вышеописанными изменениями, вы сможете обеспечить обработку запросов к резервному серверу в случае сбоя основного. Это значительно повысит надежность вашего приложения. Тем не менее, важно тестировать изменения в контролируемой среде, прежде чем развертывать их в продакшене, чтобы убедиться в их правильности.
Дополнительно, рассмотрите возможность мониторинга состояния ваших контейнеров и автоматического их перезапуска для повышения общей доступности вашего приложения.