.pm2との付き合い方
これはなに
AWS EC2 インスタンスの上にNode.js Webアプリケーションを構築しました。
Node.jsアプリの起動管理にpm2を採用したけど、.pm2
の扱いに工夫が必要だったので知見をメモしておく。
はじめに
はじめにpm2と.pm2について。
pm2とは
PM2 は、アプリケーションを 24 時間 365 日オンラインで管理および維持するのに役立つデーモン プロセス マネージャーです。
https://pm2.keymetrics.io/
PM2自体を永続的に起動し続けるためにはOS側で対応が必要です。
.pm2とは
- pm2を起動(
pm2 start app.js
)した時に生成されるpidやログ等が保管されるフォルダ
前提
PM2自体を永続的に起動し続ける手段としてsystemdサービスを採用します。
systemdサービスはpm2 startup systemd
コマンドを使って作成します。
本編
PM2を永続化する時の困りごとと解決策をセットで記載します。
.pm2の置き場所
.pm2の置き場所について。
仕組みと困りごと
- pm2を起動(
pm2 start app.js
)すると.pm2フォルダが作成される
その中にpidファイルやログが保管される - .pm2はpm2コマンドを実行したユーザのホームディレクトリに作成される
ec2-userでコマンドを実行した場合は/home/ec2-user/.pm2
に作成される
pm2で起動したアプリの状態を確認するコマンドとしてpm2 status
があるが、これはホームディレクトリか環境変数(PM2_HOME)で指定された場所から.pm2ディレクトリを探し、見つけた.pm2ディレクトリに保管されている情報をもとにステータスを表示する。
例えばec2-userユーザでpm2を起動(pm2 start app.js
)してログアウト。その後、julietユーザがログインしてpm2 status
を実行しても同じサーバで動いているnodejsアプリは表示されない。
解決策
PM2_HOME環境変数と/etc/environment
を活用する。
.pm2フォルダはPM2_HOME環境変数の中に作成される。
どのユーザでEC2にログインしても共通のPM2_HOME環境変数が設定されている状態を実現すれば解決できる。
具体的な手順は以下の通り。
/etc/environment にPM2_HOMEを定義する。
ここにexport PM2_HOME=/opt/app/.pm2
と記載しておけば、どのユーザでログインしても共通の.pm2
を参照するためpm2 statusで状況を確認することができる。
同じ機能を提供する/etc/profileもあるが、これはBashなどのシェルを起動した時だけ読み込まれるため、コマンド実行アカウントにより読み込まれない可能性がある。
systemdサービスを作成する pm2 startup
仕組みと困りごと
PM2自体を永続的に起動し続ける手段としてsystemdサービスを採用します。
systemdサービスはpm2 startup systemd
コマンドを使って作成します。
pm2 startup の --hp <home-path>
について。
pm2 startup
は --hp
に何も指定しないと$HOME
の値を参照する。
例えばこれを起動スクリプト等でrootユーザで実行すると、systemdから起動してくる時の.pm2は/root/.pm2
となる。
この値は当初定めた/opt/app/.pm2
と異なるため、systemctl restart
を実行すると、.pm2を参照することができず起動しない。
解決策
pm2 startup
を起動する時は下記例の通り.pm2を削除したパスを指定する。
# $PM2_HOMEは```/etc/environment```で設定済
HOME=$(dirname $PM2_HOME)
pm2 startup systemd -u <user> --hp $HOME
.pm2のアクセス権設定
仕組みと困りごと
.pm2はpm2を起動(pm2 start app.js
)したユーザのアクセス権で作成される。
そのため、「.pm2の置き場所」に記載した解決策で複数ユーザがpm2コマンドを実行できるようにした場合pm2 status
でステータスを見ることはできるけど、pm2 restart all
等のプロセスを操作するコマンドが権限不足で実行できない。
解決策
pm2を起動(pm2 start app.js
)を実行した後、chown -R user:wheel $PM2_HOME
しておく。
例えば、EC2(実際はAuto Scalingで構成する)にpm2を構成する場合は以下の通り。
systemdをセットアップする起動テンプレート(Launch Template)のシェルは以下の通り作成する。
function setupPM2(){
echo setupPM2
# PM2_HOME環境変数を読み込んで設定する
source /etc/environment
# systemd設定を行う
# このコマンドでpm2-ec2-user.serviceというサービスが作成&有効化される
HOME=$(dirname $PM2_HOME)
pm2 startup systemd -u ec2-user --hp $HOME
# アプリフォルダに移動
cd /opt/app
# pm2 startを実行してアプリを起動する
pm2 start ecosystem.config.js --env $NODE_ENV
# 上記で作成したpm2-ec2-user.serviceは.pm2フォルダの内容を参照して起動する
# pm2 startした結果を保存する
pm2 save
# 起動テンプレートはrootユーザで実行されるため、所有者をec2-user:wheelに変更する
chown -R ec2-user:wheel /opt/app
}
Discussion