CloudWatch Logsのサブスクリプションフィルターを使ってKinesis経由でDatadogにNginxとアプリのログを飛ばしてみたんだけど、こんな簡単にできるのか。あとはコスト大丈夫か?問題ないってところだな。
— adachin👾SRE (@adachin0817) September 24, 2021
前回CloudWatch Logsを定期的にKinesis Data Firehose経由でS3に保存するようにTerraform化を行いましたが、日々の可観測性を高めるためにECSのNginxのアクセスログ、アプリケーションログ、RDSのスロークエリログなどを日々モニタリングできればさらに分析可能とのことで、去年6月頃にDatadogへ簡単に転送できるようになったとのことなので試してみました。
Analyze logs with Datadog using Amazon Kinesis Data Firehose HTTP endpoint delivery
https://docs.datadoghq.com/ja/logs/
- 今回の構成
Amazon Kinesis Data Firehosから特定の外部サービスをサポートしたため、Datadog Logsへデータを転送できるようになりました。これによって今まではLambdaを書くことが必須でしたが、工数もかかることなく実装できるので早速Terraformやっていきましょう。
Terraform
- files/assume_role_policy/kinesis-datadog-policy.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:GetBucketLocation", "s3:GetObject", "s3:ListBucket", "s3:ListBucketMultipartUploads", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::adachin.logs", "arn:aws:s3:::adachin.logs/*" ] } ] } |
- files/assume_role_policy/kinesis-datadog.json
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "firehose.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } |
- files/assume_role_policy/kinesis_basic_role_policy.json
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "Version": "2008-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "logs.ap-northeast-1.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } |
- iam.tf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
## Kinesis-Datadog resource "aws_iam_role" "kinesis_datadog_role" { name = "kinesis_datadog_role" assume_role_policy = file("files/assume_role_policy/kinesis-datadog.json") } resource "aws_iam_policy" "kinesis_datadog_policy" { name = "kinesis_datadog_policy" description = "kinesis_datadog_policy" policy = file("files/assume_role_policy/kinesis-datadog-policy.json") } resource "aws_iam_role_policy_attachment" "kinesis_datadog_role_attach" { role = aws_iam_role.kinesis_datadog_role.name policy_arn = aws_iam_policy.kinesis_datadog_policy.arn } ## Cloudwatchlogs-Kinesis resource "aws_iam_role" "cloudwatchlogs_kinesis_role" { name = "cloudwatchlogs_kinesis_role" assume_role_policy = file("files/assume_role_policy/kinesis_basic_role_policy.json") } resource "aws_iam_role_policy_attachment" "cloudwatchlogs_kinesis_role_attach" { role = aws_iam_role.cloudwatchlogs_kinesis_role.name policy_arn = "arn:aws:iam::aws:policy/AmazonKinesisFirehoseFullAccess" } |
- kinesis.tf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#kinesis-datadog resource "aws_kinesis_firehose_delivery_stream" "kinesis_datadog" { name = "kinesis_datadog" destination = "http_endpoint" s3_configuration { role_arn = aws_iam_role.kinesis_datadog_role.arn bucket_arn = aws_s3_bucket.adachin-logs.arn buffer_size = 5 buffer_interval = 300 compression_format = "GZIP" } http_endpoint_configuration { url = "https://aws-kinesis-http-intake.logs.datadoghq.com/v1/input" name = "Datadog Log" access_key = var.access_key buffering_size = 4 buffering_interval = 60 role_arn = aws_iam_role.kinesis_datadog_role.arn s3_backup_mode = "FailedDataOnly" request_configuration { content_encoding = "GZIP" common_attributes { name = "env" value = "production" } } } lifecycle { ignore_changes = [http_endpoint_configuration["access_key"] ] } } resource "aws_cloudwatch_log_subscription_filter" "ecs_app_cloudwatchlogs_kinesis_datadog" { name = "cloudwatchlogs_kinesis_datadog" role_arn = aws_iam_role.cloudwatchlogs_kinesis_role.arn count = length(var.kinesis_datadog_cloudwatch_logs_group) log_group_name = element(var.kinesis_datadog_cloudwatch_logs_group, count.index) filter_pattern = "" destination_arn = aws_kinesis_firehose_delivery_stream.kinesis_datadog.arn distribution = "Random" } |
- variables.tf
1 2 3 4 5 6 |
variable "kinesis_datadog_cloudwatch_logs_group" { default = [ "/ecs/app", "/aws/rds/cluster/hoge/slowquery" ] } |
kinesis自体の信頼関係ポリシーは必ず logs.ap-northeast-1.amazonaws.com
とリージョンを指定しないと以下のエラーが出てしまうため気をつけましょう。
Could not deliver test message to specified Firehose stream. Check if the given Firehose stream is in ACTIVE state.
FirehoseでのS3 backupですが、Datafogへ配信しようとするすべてのデータまたはエラーデータをバックアップすることができます。今回はエラーのみを指定しました。次にFirehoseの設定ですが、TerraformではHTTP Endpoint (e.g. New Relic) Destinationを利用してDatadogのAPIから取得するように設定しています。APIキーはignore_changesしていますが、AWS KMSを利用したほうがより安全です。Datadogへの反映バッファ時間は60秒に反映するよう指定しています。(ほとんどデフォルト)
確認
Nginxとアプリケーションログは同じCloudWatch Logs名で出力してしまっているので一緒ですが、フィルタリングすれば問題ありません。またDatadog LogsからNginxのステータスコードやアプリログのErrorからアラート設定すればSlack通知もできるので非常に捗りそうです!プラスヘルスチェックのアクセスログはオフらないとな…
まとめ
今までAWSのコンソールにログインして確認という手間がなくなったので、非常に重宝しそうだなと率直に感じました。コストですが、Proプランであれば1MBで$1なのと、7日間しかログが残らないので安いかと思います。が、大量のNginxのアクセスログなど連携してしまうと月$1000くらいかかるので注意しましょう。ログの分析方法としては他にもやり方はたくさんありますが、ぜひ参考にしてみてください!
https://dev.classmethod.jp/articles/firehose-datadog-logs/
0件のコメント