こんにちは。プロダクト事業部のまつもとです。
最近、AWS Batchを利用したのですが、ログ出力で格闘してしまいました。
(単純に、fluentdとかの検証が間に合っていないだけなんですが。)
今回採用した方法など、ご紹介致します。
AWS Batchログ
AWS Batchでは、実行するシェルなどの標準出力がCloudWatch Logsへ出力されます。デフォルトでは標準出力がawslogs ログドライバーによりCloudWatch Logsへ転送されます。
AWS Batchでサポートされているロギングドライバは awslogs
, fluentd
, gelf
, json-file
, journald
, splunk
, syslog
と、かなり豊富です。
参考: https://docs.aws.amazon.com/batch/latest/APIReference/API_LogConfiguration.html
AWS Batch ログで困ったこと
今回バッチで稼働させたいのは、PHPで組まれた結構規模の大きなシステムバッチで、標準出力には対応してはおらず、非常に意味のあるログを色々な場所(各種ディレクトリ)にファイル出力する仕様でした。そこで今回、ログ出力をなんとかしてCloudWatch Logsに連携するやり方をあれやこれやと検討しました。
検討その1:標準出力をなんとかして使う
まず、PHP側のロギングドライバを標準出力に変更しようと検討しましたが、利用しているフレームワークの制約などがあり、変更不可能と判断して断念しました。
なので、まずはPHPが相手にするログファイルを標準出力に置き換えてやろうとしました。
ln -sf /dev/stdout /var/log/output1_log
ln -sf /dev/stdout /var/log/output2_log
結果はうまく行きませんでした。
そもそもシステムバッチは色々な意味のログを色々な場所に出力しています。それらが、syslog一本に集約されると、後々必要な情報が探し辛くなるかと思い、断念しました。
検討その2:fluentdでフィルタリング
こちらは、複数の場所に吐き出すログをフィルタリングして収集してくれるので、今回の要件にハマりそうな気がしてたんですが、結局一箇所に集約された時に、なんのログかを判断するためのタグ付けなどを頑張る必要があり、こちらも断念しました。
最終案:EC2のボリュームをマウントしてCloudWatchLogs-Agent使う
今回は、こちらの方法を採用しました。
- 起動はCloudWatch Eventsでタイマー起動します。
- 起動されたAWS Batdhは、起動テンプレートに従って、EC2環境を構築します。
EC2構築時に、CloudWatch-LogsのAgentの設定をUserDataを利用して設定します。 - ECSの起動時に、EC2のCloudWatch Logsに連携するディレクトリをマウントして起動するように設定します。
この設定を行うことで、ECS内で出力されたログファイルは全て、EC2上のロググループに出力され、ログファイルの内容はEC2がCloudWatch Logsへ転送するようになりました!
AWS Batchに指定する起動テンプレートのUserDataのTIPS
https://docs.aws.amazon.com/ja_jp/batch/latest/userguide/launch-templates.html に書かれている通り、MIME マルチパートファイル形式で記述する必要があります。
通常の起動テンプレート違う箇所はここだけです。
サンプルでは、パラメータストアからログ定義を取得して反映してます。
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="
--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"
#!/bin/bash
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:AmazonCloudWatch-Linux -s
--==MYBOUNDARY==--
デメリット
バッチが複数起動した場合、ログファイルが混在する
現状は、起動するECSが一つのみなのでまだ問題ではないですが、今後、高負荷になってECSが複数稼働するようになった場合、各ECSのログが一箇所に出力されてしまい、並行実行時は逆にログを検証することができなくなってしまいます。
並行実行も考えて、手間ではありますが fluentd
を検討する方が良い気がしています。
最後に
AWS Batchを初めて触り、色々試行錯誤した内容を恥ずかしながら書いてみました。
今後もAWSで設定した内容など書いて行こうかと思っています。