Datadog × API Gateway × Lambdaでプロセスの再起動を自動化する
MMMサーバサイドエンジニアの柳沼です。
お世話になっております。
ようやく北海道も暑くなってきました。
前回に引き続いてDatadogで書いてみます。
シンプルなホスト監視だけでなく、ちょっとトリッキーなこともやってみようということで、LambdaをDatadogと組み合わせてみます。
今回のゴールは、 EC2ノード上で走っているはずのnginxプロセスが止まっていた場合、自動で再起動する
ことにしてみます。
アーキテクチャ
こんな感じで作ってみます。
EC2の準備
EC2を普通に作ります。
PENDING
から RUNNING
に変わったら、ホストにsshして、nginxとDatadogのエージェントをインストールしていきます。
接続先のアドレスは環境によって変わります。
pemファイルはインスタンスを作った時のものです。
chmod 600 ~/.ssh/datadog_lambda_test_yagi.pem
ssh ec2-user@xxx.xxx.xxx.xx -i ~/.ssh/datadog_lambda_test_yagi.pem
nginxインストール
sudo yum install nginx
そして、Datadogのエージェントをインストールします。前回の記事 を御覧ください。
また、nginxのプロセス監視は、設定が必要なため以下のようにします。
sudo cp /etc/dd-agent/conf.d/process.yaml.example /etc/dd-agent/conf.d/process.yaml
sudo vi /etc/dd-agent/conf.d/process.yaml
ファイルの最下部に
- name: nginx
search_string: ['nginx']
と書くことで、nginxプロセスの監視ができます。
編集後は必ず
sudo /etc/init.d/datadog-agent restart
で、エージェントの再起動をしてください。
API Gatewayを作成
API Gatewayは簡単にWeb APIが作成できるAWSのマネージドサービスです。
AWSコンソールの、 API Gateway
-> 新しいAPIの作成
から作っていきます。
API名は、任意の名前で大丈夫ですが、今回は datadog_lambda_test_api
としました。
次にリソースを作っていきます。 アクション
-> リソースの作成
で、APIへのリソース(エンドポイント)を作ります。
次にメソッドを作ります。メソッドはHTTPメソッドです。
きちんとしたAPI設計は今回はせず、単にPOSTで作ってみます。
先程作ったリソースを選択した状態で、 アクション
-> メソッドの作成
で作ることができます。
統合タイプ
には Lambda関数
を選択します。 Lambda関数
に関数名を入力したいところですが、まだ関数を作っていないので、作ります。
Lambdaファンクションを作成
BluePrintには Blank Function
を選んでおきます。
トリガーは API Gateway
を選択して、先程作成したAPIを選んでおいてください。
今回はPython 2.7で書いていきます。ソースコードはこんな感じです。
import boto3
import paramiko
def lambda_handler(event, context):
s3_client = boto3.client('s3')
# Download pem from S3 bucket
s3_client.download_file('lambda.datadog.test',
'datadog_lambda_test_yagi.pem', '/tmp/datadog_lambda_test_yagi.pem')
key = paramiko.RSAKey.from_private_key_file("/tmp/datadog_lambda_test_yagi.pem")
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
host=event['your IP']
print "Connecting to " + host
client.connect( hostname = host, username = "ec2-user", pkey = key )
print "Connected to " + host
commands = [
"sudo service nginx stop",
"sudo service nginx start"
]
for command in commands:
print "Executing {}".format(command)
stdin , stdout, stderr = c.exec_command(command)
print stdout.read()
print stderr.read()
return
{
'message' : "script completed."
}
importしているboto3は、aws cliを使うためのライブラリです。
SSHクライアントに paramikoを使っています。
commands
の部分に、好きなコマンドを書くことで、SSHした後にそのコマンドを実行することができます。
また、ご覧の通り、pemファイルをS3から取得しています。これはこの後でやっていきます。
LambdaファンクションをPythonで書く時、 paramiko
のような外部ライブラリを使うときは、インラインコーディングができません。
pipでライブラリをインストールして、zipに固めてアップロードする必要があります。デプロイパッケージの作成 (Python)を参考にしました。
ここまでできれば、Lambdaファンクションが完成します。ファンクション名をAPI Gateway側に設定しておきます。
S3にpemを置いておく
説明が前後しましたが、上記のPythonソースのように、EC2にアクセスするためのpemファイルを置いておく必要があります。
バケットの作成・pemのアップロードをしておきます。バケット名・パスがソースコードと一致するようにしておきます。
アップロード後です。
Datadogのアラート設定
最後に、Datadogからnginxプロセスを監視して、プロセスが落ちていたらAPIを叩く、という設定をします。
Datadogコンソールから Integrations
-> Webhook
を選択します。
エンドポイントはAPI Gatewayをデプロイした後に表示されるので、リソースを含めて書きます。
アラートは Monitors
-> process
から設定します。
pick a process
に process:nginx
を選択、アラート通知先に先程作成したWebhookを選択します。
これで最初の図の通り、準備が全て完了しました。
もう一度見ておきます。
動作確認
動作確認してみます。
EC2ノードに入ってnginxを止めてみましょう。
$ ps aux | grep nginx
root 24345 0.0 0.1 58104 1020 ? Ss 06:00 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 24347 0.0 0.3 58476 3952 ? S 06:00 0:00 nginx: worker process
ec2-user 24349 0.0 0.2 110456 2192 pts/0 S+ 06:00 0:00 grep --color=auto nginx
nginxプロセスをkillして少し待ちます。
CloudWatchのログに
{
'message' : "script completed."
}
と出て、nginxも無事に再起動していれば、無事成功です。
まとめ
今回はプロセス再起動でしたが、ホストにSSH接続してコマンドが打てるということは、事実上なんでもできるということです。
今後もDatadogを使ったソリューションをガンガン試していきたいと思います!
また、AWS LambdaやDatadogを用いた監視については、以下のぺージでも紹介しています。ぜひご覧ください。
参考
- Scheduling SSH jobs using AWS Lambda
- paramiko を使って Python で SFTP/SCPを行う
- デプロイパッケージの作成 (Python)
- AWS Lambda 関数の API GatewayAPI を作成する