クライアント接続を切断せずにNginxをインプレースでアップグレードする方法
紹介
Nginxは、世界で最も人気のあるサイトの多くを提供するために使用される強力なウェブサーバーおよびリバースプロキシです。このガイドでは、クライアント接続を失うことなく、Nginx実行ファイルをそのままアップグレードする方法を示します。
前提条件
このガイドを始める前に、サーバーに非ルートユーザーを持ち、sudo 権限が設定されている必要があります。また、Nginx がインストールされている必要もあります。
最初のサーバーセットアップガイドに従って、Ubuntu 22.04 用のサーバーを設定し、そのサーバーに Nginx をインストールできます。
アップグレードの仕組み
Nginxは、サービスが開始されるとマスタープロセスを生成することによって動作します。マスターサービスは、実際のクライアント接続を処理する1つ以上のワーカープロセスを生成します。Nginxは、システムから特定の低レベルの信号を受信したときに特定のアクションを実行するように設計されています。これらの信号を使用することで、クライアント接続を失うことなく、Nginxまたはその設定をそのままアップグレードする機会を提供します。
Nginxが提供するインストールおよびアップグレードスクリプトは、Nginxを起動、停止、再起動する際にこれらの信号を送信するように設計されています。しかし、これらの信号を手動で送信することにより、アップグレードを監査し、問題が発生した場合に迅速に元に戻すことができます。また、ソースからNginxをインストールした場合や、パッケージマネージャにサービスの構成を依存していない場合には、優雅にアップグレードするオプションも提供されます。
次の信号が使用されます:
USR2: これにより、古いセットに影響を与えずに新しいマスター/ワーカープロセスのセットが生成されます。WINCH: これは、Nginxマスタープロセスに関連するワーカーインスタンスを優雅に停止するように指示します。HUP: これはNginxのマスタープロセスに対して、設定ファイルを再読み込みし、新しい設定に従ったワーカープロセスに置き換えるように指示します。古いマスターと新しいマスターが両方稼働している場合、古いマスターにこれを送信すると、その元の設定を使用してワーカーが生成されます。QUIT: これはマスターとそのワーカーを優雅にシャットダウンします。TERM: これはマスターとそのワーカーの迅速なシャットダウンを開始します。KILL:これにより、マスターとそのワーカーがクリーンアップなしですぐに強制終了されます。
NginxプロセスのPIDを見つける
さまざまなプロセスに信号を送るためには、ターゲットプロセスのPIDを知っている必要があります。これを見つける方法は2つあります。
まず、psユーティリティを使用し、その後、結果の中からNginxをgrepします。これにより、マスタープロセスとワーカープロセスを見ることができます:
- ps aux | grep nginx
outputroot 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
sammy 16688 0.0 0.1 221928 1164 pts/0 S+ 21:48 0:00 grep --color=auto nginx
2番目の強調表示された列には、選択されたプロセスのPIDが含まれています。最後の列は、最初の結果がNginxマスタープロセスであることを明確にしています。
マスタ Nginx プロセスの PID を見つける別の方法は、/run/nginx.pid ファイルの内容を出力することです:
- cat /run/nginx.pid
output16653
もし二つのNginxマスタープロセスが動作している場合、古い方は/run/nginx.pid.oldbinに移動されます。
新しいNginxマスター/ワーカーセットを生成する
優雅に更新する最初のステップは、実際にNginxパッケージおよび/またはバイナリを更新することです。これは、パッケージマネージャーを使うかソースインストールを通じて、あなたのNginxインストールに適した方法で行ってください。
新しいバイナリが配置された後、新しい実行ファイルを使用する2番目のマスター/ワーカープロセスのセットを生成できます。
これを行うには、あなたが問い合わせたPID番号に直接USR2信号を送信します(ここでは自分のNginxマスタープロセスのPIDに置き換えることを確認してください):
- sudo kill -s USR2 16653
または、PIDファイルに保存された値を直接コマンドに置き換えて読み取ることもできます。
- sudo kill -s USR2 `cat /run/nginx.pid`
実行中のプロセスを確認すると、現在、2セットのNginxマスターとワーカーがあることがわかります:
- ps aux | grep nginx
outputroot 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
root 16699 0.0 1.5 119164 12732 ? S 21:54 0:00 nginx: master process /usr/sbin/nginx
nginx 16700 0.0 0.9 151804 8008 ? S 21:54 0:00 nginx: worker process
sammy 16726 0.0 0.1 221928 1148 pts/0 R+ 21:55 0:00 grep --color=auto nginx
元の/run/nginx.pidファイルが/run/nginx.pid.oldbinに移動され、新しいマスタープロセスのPIDが/run/nginx.pidに書き込まれたことも確認できます:
- tail -n +1 /run/nginx.pid*
output==> /run/nginx.pid <==
16699
==> /run/nginx.pid.oldbin <==
16653
これらのファイルに含まれるPIDを使用して、いずれかのマスタープロセスに信号を送信できるようになりました。
現時点で、マスター/ワーカーの両方のセットは稼働中で、クライアントのリクエストに応じることができます。最初のセットはオリジナルのNginx実行ファイルと設定を使用しており、2番目のセットは新しいバージョンを使用しています。これらは並行して運用し続けることができますが、一貫性を保つために新しいセットへの移行を開始するべきです。
最初のマスターの労働者をシャットダウンする
新しいセットへの移行を始めるために、最初に行うべきことは、元のマスターのワーカープロセスを停止することです。元のワーカーはすべての現在の接続の処理を終えた後、終了します。
元のセットの作業者を停止するには、マスタープロセスにWINCH信号を送信します:
- sudo kill -s WINCH `cat /run/nginx.pid.oldbin`
これにより、新しいマスターのワーカーが新しいクライアント接続を単独で処理できるようになります。古いマスタープロセスはまだ動作していますが、ワーカーはありません。
- ps aux | grep nginx
outputroot 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
root 16699 0.0 1.5 119164 12732 ? S 21:54 0:00 nginx: master process /usr/sbin/nginx
nginx 16700 0.0 0.9 151804 8008 ? S 21:54 0:00 nginx: worker process
sammy 16755 0.0 0.1 221928 1196 pts/0 R+ 21:56 0:00 grep --color=auto nginx
これは、孤立して接続を受け入れる新しい作業者を監査できるようにします。
結果を評価し、次のステップを踏む
この時点で、問題の兆候がないことを確認するために、システムをテストおよび監査するべきです。新しいNginx実行ファイルがバグがなく、トラフィックを処理できることを保証するために、構成をこの状態のままにしておくことができます。
次のステップは、問題に直面するかどうかに完全に依存します。
アップグレードが成功した場合
新しいセットのワーカーに問題がなければ、古いマスタープロセスを安全にシャットダウンできます。そのためには、古いマスターにQUITシグナルを送ります:
- sudo kill -s QUIT `cat /run/nginx.pid.oldbin`
古いマスタープロセスは優雅に終了し、新しいNginxマスター/ワーカーのみが残ります。この時点で、クライアント接続を中断することなく、Nginxのインプレースバイナリ更新を成功裏に実行しました。
アップグレードが成功しなかった場合
新しい作業者のセットに問題があるように見える場合は、古い構成とバイナリに戻ることができます。これは、古いマスタープロセスをQUITしていない限り可能です。
これを行う最良の方法は、古いマスターのワーカーを再起動することで、HUP シグナルを送ることです。通常、NginxマスターにHUPシグナルを送ると、設定ファイルを再読み込みし、新しいワーカーを開始します。しかし、ターゲットが古いマスターである場合、元の動作している設定を使用して新しいワーカーを生成します:
- sudo kill -s HUP `cat /run/nginx.pid.oldbin`
今、あなたはマスター/ワーカーのプロセスの2つのセットに戻っているはずです:
- ps aux | grep nginx
outputroot 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
root 16699 0.0 1.5 119164 12732 ? S 21:54 0:00 nginx: master process /usr/sbin/nginx
nginx 16700 0.0 0.9 151804 8008 ? S 21:54 0:00 nginx: worker process
sammy 16726 0.0 0.1 221928 1148 pts/0 R+ 21:55 0:00 grep --color=auto nginx
最新のワーカーは古いマスターに関連付けられています。この時点で、両方のワーカーセットはクライアント接続を受け入れます。さて、新しくてバグのあるマスター プロセスとそのワーカーを QUIT シグナルを送信して停止させます。
- sudo kill -s QUIT `cat /run/nginx.pid`
あなたは昔の主人と作業員の元に戻るべきです:
- ps aux | grep nginx
outputroot 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
sammy 16688 0.0 0.1 221928 1164 pts/0 S+ 21:48 0:00 grep --color=auto nginx
元のマスターは、そのPIDのために/run/nginx.pidファイルを取り戻します。
もしこれが何らかの理由でうまくいかない場合は、新しいマスターサーバーにTERM信号を送信してみてください。これによりシャットダウンが開始されるはずです。これにより、新しいマスターとすべてのワーカーが停止し、古いマスターが自動的に切り替わってそのワーカープロセスを開始します。深刻な問題が発生し、バグのあるワーカーが終了しない場合は、それぞれにKILL信号を送ってクリーンアップすることができます。ただし、これは最後の手段として使用すべきであり、接続が切断されることになります。
古いバイナリに戻した後でも、システムに新しいバージョンがインストールされていることを忘れないでください。バグのあるバージョンを削除し、以前のバージョンに戻すことで、Nginxが再起動時に問題なく動作するようになります。
結論
今頃、あなたは機械を一つのNginxバイナリから別のものにシームレスに移行できるはずです。Nginxは、関係を保持しながら二つのマスター/ワーカーセットを処理する能力を持っており、これによりサーバーソフトウェアをサーバーマシンをオフラインにすることなくアップグレードすることができます。
