Обновление Nginx без потери клиентских подключений

Nginx – это популярный веб-сервер и обратный прокси-сервер с высокой производительностью. В этом руководстве речь пойдёт о том, как обновить исполняемые файлы Nginx, не теряя клиентских подключений.

Требования

Для выполнения руководства нужен не-root пользователь с правами sudo и предварительно установленный сервер Nginx.

Чтобы создать пользователя с правами sudo и установить Nginx, читайте:

Для Ubuntu 14.04:

Для CentOS 7:

Как обновляется Nginx?

Работа Nginx состоит в создании master-процессов при запуске сервисов. В свою очередь главный сервис запускает ещё один или больше рабочих процессов, которые обрабатывают клиентские подключения. Получая определенные сигналы от администратора, Nginx будет выполнять некоторый ряд действий. Именно эти сигналы администратора предоставляют возможность легко обновить сервер Nginx или его настройки, не теряя при этом клиентских подключений.

Некоторые скрипты сервисов, предоставленные дистрибутивом, позволяют использовать эту функцию при обычном обновлении пакета. Однако выполненное вручную обновление обеспечивает большую гибкость и позволяет проверять обновления, чтобы быстро вернуться к предыдущей версии пакета в случае возникновения каких-либо проблем. Также это позволяет легко обновить сервер Nginx, установленный из исходного кода (или же другим способом, который не поддерживает этой функции).

Для этого используются сигналы:

  • USR2: запускает новый набор главных и рабочих процессов, не затрагивая ранее запущенные процессы.
  • WINCH: останавливает процессы, связанные с главным процессом Nginx.
  • HUP: говорит главному процессу Nginx перечитать конфигурационный файл и заменить рабочие процессы новой конфигурации. Если отправить этот сигнал более старому главному процессу, то он создаст рабочие процессы согласно старым конфигурациям.
  • QUIT: выключает главный процесс и его рабочие процессы.
  • TERM: быстро прерывает главный процесс и его рабочие процессы.
  • KILL: убивает главный процесс и его рабочие процессы.

Обнаружение PID процесса Nginx

Чтобы отправлять сигналы различным процессам сервера, нужно знать PID (Process Identification Number, идентификатор) целевого процесса. Его можно узнать двумя способами.

Можно использовать утилиту ps, а затем найти в результате Nginx с помощью grep. Этот простой способ позволяет найти главные и рабочие процессы.

ps aux | grep nginx
root     10846  0.0  0.3  47564  3280 ?        S    13:26   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    10847  0.0  0.1  47936  1908 ?        S    13:26   0:00 nginx: worker process
user     10961  0.0  0.0 112640   964 pts/0    S+   13:53   0:00 grep --color=auto nginx

PID процессов находится во втором столбце. Красным выделен PIDискомого процесса. Последняя строка сообщает, что главный процесс Nginx выведен в первой строке.

Также PID главного процесса Nginx можно вывести из содержимого файла /run/nginx.pid.

cat /run/nginx.pid
10846

Если на сервере запущено два главных процесса Nginx, боле старый процесс будет перемещён в /run/nginx.pid.oldbin.

Запуск новых процессов Nginx

Чтобы приступить к обновлению исполняемого файла, нужно обновить двоичный файл. Метод обновления этого файла зависит от метода установки Nginx (с помощью менеджера пакетов или из исходного кода)

Когда новый бинарный файл на месте, запустите второй набор главных и рабочих процессов, которые используют новый исполняемый файл.

Для этого нужно отправить сигнал USR2 на ранее найденный PID процесса.

sudo kill -s USR2 10846

Примечание: Этот условный PID нужно заменить своим идентификатором.

Кроме того, обнаружить и использовать PID целевого процесса можно непосредственно во время отправки сигнала:

sudo kill -s USR2 `cat /run/nginx.pid`

Проверьте текущие процессы, чтобы убедиться, что второй набор процессов успешно запущен:

ps aux | grep nginx
root     10846  0.0  0.3  47564  3280 ?        S    13:26   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    10847  0.0  0.1  47936  1908 ?        S    13:26   0:00 nginx: worker process
root     11003  0.0  0.3  47564  3132 ?        S    13:56   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    11004  0.0  0.1  47936  1912 ?        S    13:56   0:00 nginx: worker process
user     11031  0.0  0.0 112640   960 pts/0    S+   14:01   0:00 grep --color=auto nginx

Также можно видеть, что оригинальный файл /run/nginx.pid был перемещён в /run/nginx.pid.oldbin, а PID нового master-процесса записан в /run/nginx.pid:

tail -n +1 /run/nginx.pid*
==> /run/nginx.pid <==
11003
==> /run/nginx.pid.oldbin <==
10846

Теперь сигналы можно отправлять любому из этих главных процессов, указывая соответствующий PID.

На данный момент оба набора процессов работают и могут обслуживать запросы клиентов. Первый набор использует оригинальный исполняемый и конфигурационный файл Nginx, а второй набор использует более новые версии этих файлов. Они могут продолжать работать вместе. Теперь можно приступать к обновлению веб-сервеера Nginx.

Отключение старого набора процессов

Чтобы начать переход к новому набору процессов, сначала нужно остановить рабочие процессы оригинального главного процесса (то есть устаревший набор процессов). Оригинальные рабочие процессы закончат обработку всех своих текущих соединений, а затем остановятся.

Чтобы остановить эти процессы, нужно отправить сигнал WINCH их главному процессу.

sudo kill -s WINCH `cat /run/nginx.pid.oldbin`

Таким образом обработка клиентских запросов полностью перейдёт к рабочим процессам нового набора. Оригинальный главный процесс всё ещё будет запущен, но при этом у него не будет рабочих процессов:

ps aux | grep nginx
root     10846  0.0  0.3  47564  3280 ?        S    13:26   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
root     11003  0.0  0.3  47564  3132 ?        S    13:56   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    11004  0.0  0.1  47936  1912 ?        S    13:56   0:00 nginx: worker process
user     11089  0.0  0.0 112640   964 pts/0    R+   14:13   0:00 grep --color=auto nginx

Это позволяет проверить новые рабочие процессы, поскольку сейчас они принимают соединения изолированно, оставляя возможность вернуться к старой версии исполняемого файла, если что-то пойдёт не так.

Результаты и дальнейшие действия

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

Дальнейшие действия полностью зависят от результатов проверки.

Завершение перехода

В случае успешного обновления завершите переход.

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

sudo kill -s QUIT `cat /run/nginx.pid.oldbin`

После этого устаревший главный процесс будет остановлен, и в работе останется только новый набор процессов Nginx. Обновление бинарного файла Nginx успешно завершено, при этом все клиентские соединения остались на месте.

Восстановление старого бинарного файла

Если новые рабочие процессы во время проверки столкнулись с ошибкой, нужно возобновить старые конфигурации и бинарные файлы. Это можно сделать в текущей сессии.

Для восстановления старых рабочих процессов нужно отправить сигнал HUP. Как правило, при получении этого сигнала главный процесс Nginx перечитывает конфигурационные файлы и запускает новые рабочие процессы. Однако если сигнал отправлен старому главному процессу, он просто запустит новые рабочие процессы, используя оригинальные конфигурации:

sudo kill -s HUP `cat /run/nginx.pid.oldbin`

Теперь на сервере снова запущены два набора процессов:

ps aux | grep nginx
root     10846  0.0  0.3  47564  3280 ?        S    13:26   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
root     11003  0.0  0.3  47564  3132 ?        S    13:56   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    11004  0.0  0.1  47936  1912 ?        S    13:56   0:00 nginx: worker process
nginx    19918  0.0  0.1  47936  1900 ?        S    14:47   0:00 nginx: worker process
user     19920  0.0  0.0 112640   964 pts/0    R+   14:48   0:00 grep --color=auto nginx

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

sudo kill -s QUIT `cat /run/nginx.pid`

Теперь все запросы полностью обрабатываются оригинальным набором процессов.

ps aux | grep nginx
root     10846  0.0  0.3  47564  3280 ?        S    13:26   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    19918  0.0  0.1  47936  1900 ?        S    14:47   0:00 nginx: worker process
user     19935  0.0  0.0 112640   964 pts/0    R+   14:50   0:00 grep --color=auto nginx

PID главного процесса переместится в файл /run/nginx.pid.

Если предложенные выше инструкции не сработали по какой-либо причине,  попробуйте послать новому главному процессу сигнал TERM, который инициирует его отключение.Это должно остановить новый master-процесс и все его рабочие процессы, автоматически возобновляя старый master-процесс и инициируя его рабочие процессы.

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

Вернувшись к старой версии бинарного файла, помните о том, что загруженная ранее новая версия всё ещё находится на сервере. Удалите версию, содержащую ошибки, и перезапустите Nginx, вернувшись к старой версии.

Tags: , ,

Добавить комментарий