Edited at

無停止でnginxを手動upgradeする

More than 3 years have passed since last update.


無停止でnginxのupgradeを行う手順

無停止でnginxを新しいバージョンへアップグレードする手順です。

だいたいここに書いてあります。

http://nginx.org/en/docs/control.html#upgrade


作業内容

nginx 1.7.3 -> 1.9.9 へアップグレード


環境


  • OS

    CentOS 6.6

  • nginx1.7.3が起動している

    nginx.confなどがすでに存在

    nginx1.7.3 は ソースからインストールされている(/usr/local/nginx/以下)

  • php-fpm等は起動していない


作業はすべてrootユーザで実施します

kill/make install等でsudoが必要な場合があります。

rootユーザで実施するためその辺りは考慮していません。


nginx 1.9.9 のバイナリの用意

configureオプションは適当に。

# wget http://nginx.org/download/nginx-1.9.9.tar.gz

# tar zxf nginx-1.9.9.tar.gz
# cd nginx-1.9.9 ; pwd
# ./configure
# make
# make install

この状態では、まだアップグレードされていません。

# /usr/local/nginx/sbin/nginx -V

nginx version: nginx/1.7.3

この状態でmake upgradeすると自動で置き換わります。

すごいですね。


アップグレード手順

最初に手順だけをあげると下記となります。

# /usr/local/nginx/sbin/nginx -t

# kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
# kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin`
# kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
# /usr/local/nginx/sbin/nginx -V


挙動を見ていきます


  • アップグレード前の状態

    masterプロセスのpidは4388です。

# ps auxww | grep 'nginx'

root 4388 0.1 0.3 105792 6304 ? S 02:29 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/ngin /etc/nginx.conf
nginx 4389 0.0 0.1 106228 2836 ? S 02:29 0:00 nginx: worker process
nginx 4390 0.0 0.1 106228 2904 ? S 02:29 0:00 nginx: worker process
nginx 4391 0.0 0.1 106228 2884 ? S 02:29 0:00 nginx: worker process
root 4397 0.0 0.0 6388 680 pts/2 S+ 02:29 0:00 grep --color=auto nginx
#

1.config test

# /usr/local/nginx/sbin/nginx -t

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
#

2.USR2シグナル送信


  • 新しいバイナリのnginxプロセスが起動

  • アップグレード前nginxのpidファイルがnginx.pid.oldbinとなる

  • アップグレード後のnginxが処理を開始

# kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`

# ps auxwwf | grep 'ngin[x]'
root 4388 0.0 0.3 105792 6304 ? S 02:29 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/ngin /etc/nginx.conf
nginx 4389 0.0 0.1 106228 2836 ? S 02:29 0:00 \_ nginx: worker process
nginx 4390 0.0 0.1 106228 2904 ? S 02:29 0:00 \_ nginx: worker process
nginx 4391 0.0 0.1 106228 2884 ? S 02:29 0:00 \_ nginx: worker process
root 4464 0.0 0.3 103516 6240 ? S 02:31 0:00 \_ nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/etc/nginx.conf
nginx 4465 0.0 0.1 103944 2828 ? S 02:31 0:00 \_ nginx: worker process
nginx 4466 0.0 0.1 103944 2896 ? S 02:31 0:00 \_ nginx: worker process
nginx 4467 0.0 0.1 103944 2872 ? S 02:31 0:00 \_ nginx: worker process
#
#
# ls -la /usr/local/nginx/logs/nginx.pid*
-rw-r--r-- 1 root root 5 Feb 4 02:31 nginx.pid
-rw-r--r-- 1 root root 5 Feb 4 02:29 nginx.pid.oldbin
#

アップグレード後nginxのmasterプロセスが起動しています。pid4464のものになります。

アップグレード前nginxのmasterプロセス4388の方も起動しているのが分かります。


USR2を送ると


  • アップグレード後masterプロセスとアップグレード前masterプロセスが混在する事に

  • アップグレード後nginxのpid -> nginx.pid

  • アップグレード前nginxのpid -> nginx.pid.oldbin

以降、nginx.pid.oldbinへシグナルを送信することでアップグレード前nginxを、

nginx.pidへシグナルを送る事でアップグレード後nginxを操作できます。

3.WINCHシグナルの送信


  • アップグレード前masterプロセスがworkerプロセスを終了し、アップグレード後のnginxのみで処理を開始


# kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin`

#
# ps auxwwf | grep 'ngin[x]'
root 4388 0.0 0.3 105792 6304 ? S 02:29 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/ngin /etc/nginx.conf
root 4464 0.0 0.3 103516 6240 ? S 02:31 0:00 \_ nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/etc/nginx.conf
nginx 4465 0.0 0.1 103944 2828 ? S 02:31 0:00 \_ nginx: worker process
nginx 4466 0.0 0.1 103944 2896 ? S 02:31 0:00 \_ nginx: worker process
nginx 4467 0.0 0.1 103944 2872 ? S 02:31 0:00 \_ nginx: worker process
#

アップグレード前masterプロセスであるpid4388が存在し、workerプロセスが無くなっています。


WINCHシグナルを送ると

アップグレード前masterプロセスが管理下にあるworkerプロセスを終了させます。

この状態では、すべてのリクエストを新しいnginxが処理することになります。

この状態で、Web閲覧が不可能等である場合は切り戻す事になります。

切り戻し手順は後述します。

4.QUITシグナルをアップグレード前nginxに送信


  • アップグレード前nginxのマスタープロセスが完全に終了

# kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`

# ps auxwwf | grep 'ngin[x]'
root 4464 0.0 0.3 103516 6240 ? S 02:31 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/ngin /etc/nginx.conf
nginx 4465 0.0 0.1 103944 2828 ? S 02:31 0:00 \_ nginx: worker process
nginx 4466 0.0 0.1 103944 2896 ? S 02:31 0:00 \_ nginx: worker process
nginx 4467 0.0 0.1 103944 2872 ? S 02:31 0:00 \_ nginx: worker process
#
# ls -l /usr/local/nginx/logs/nginx.pid
-rw-r--r-- 1 root root 5 Feb 4 02:31 /usr/local/nginx/logs/nginx.pid
#
#
# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.9.9
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
#

アップグレード前のmasterプロセスが完全に終了しています。

これでアップグレードは完了となります。


切り戻し手段

途中で問題が発生した場合は切り戻す事になります。方法は2つです。


  • アップグレード前masterプロセスへHUPシグナルを送信

    アップグレード後masterプロセスを終了し、アップグレード前masterプロセスがworkerプロセスを作成します。


  • アップグレード後TERMシグナルを送信

    アップグレード前masterプロセスがアップグレード後masterプロセスの終了を検知すると、workerプロセスを作成します。


# kill -s HUP `cat /usr/local/nginx/logs/nginx.pid.oldbin`