Datadog × API Gateway × Lambdaでプロセスの再起動を自動化する

MMMサーバサイドエンジニアの柳沼です。
お世話になっております。
ようやく北海道も暑くなってきました。

前回に引き続いてDatadogで書いてみます。
シンプルなホスト監視だけでなく、ちょっとトリッキーなこともやってみようということで、LambdaをDatadogと組み合わせてみます。

今回のゴールは、 EC2ノード上で走っているはずのnginxプロセスが止まっていた場合、自動で再起動する ことにしてみます。

アーキテクチャ

こんな感じで作ってみます。

EC2の準備

EC2を普通に作ります。

PENDING から RUNNING に変わったら、ホストにsshして、nginxとDatadogのエージェントをインストールしていきます。
接続先のアドレスは環境によって変わります。
pemファイルはインスタンスを作った時のものです。

1
chmod 600 ~/.ssh/datadog_lambda_test_yagi.pem
1
ssh ec2-user@xxx.xxx.xxx.xx -i ~/.ssh/datadog_lambda_test_yagi.pem

nginxインストール

1
sudo yum install nginx

そして、Datadogのエージェントをインストールします。前回の記事 を御覧ください。

また、nginxのプロセス監視は、設定が必要なため以下のようにします。

1
sudo cp /etc/dd-agent/conf.d/process.yaml.example /etc/dd-agent/conf.d/process.yaml
1
sudo vi /etc/dd-agent/conf.d/process.yaml

ファイルの最下部に

1
- 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で書いていきます。ソースコードはこんな感じです。

1
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 processprocess:nginx を選択、アラート通知先に先程作成したWebhookを選択します。

これで最初の図の通り、準備が全て完了しました。
もう一度見ておきます。

動作確認

動作確認してみます。
EC2ノードに入ってnginxを止めてみましょう。

1
$ 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のログに

1
{
    'message' : "script completed."
}

と出て、nginxも無事に再起動していれば、無事成功です。

まとめ

今回はプロセス再起動でしたが、ホストにSSH接続してコマンドが打てるということは、事実上なんでもできるということです。
今後もDatadogを使ったソリューションをガンガン試していきたいと思います!

MMMのDatadogを使った監視ソリューションについてのお問合わせはこちら からどうぞ。

参考

このエントリーをはてなブックマークに追加