今回はAWSの記事です。
- 記事を作ろうと思った経緯
- 前提
- 問題点
- 対策案
- 最後に
【AWS】【障害事例】CloudWatchLogsのサブスクリプションフィルターは適切に設定しましょう
記事を作ろうと思った経緯
これは筆者が人づてに聞いたトラブル事例です。
とあるシステムにおいて、CloudWatchLogsへ送信されたログをキャッチアップし
Lambdaへ転送して処理するロジックがありました。
Logs→Lambdaの処理自体は問題なく動作するのですが、
サブスクリプションフィルターの設定箇所が適切でなかった
(Lambdaのデバッグログも含む、同リージョンの全ロググループに設定してしまった)
ため、無限ループが発生してしまいました。
※こういうケースにおける発生コストは発見遅れなども合わさり、高額になりがちです。
今回はこういったケースに対する対策を考えていきたいと思います。
前提
対策を考える前に、まずはCloudWatchLogsのサブスクリプションフィルター機能
について紹介いたします。
ざっくり説明しますと、
(1)CloudWatchLogsに送られたログデータを
(2)「すべて、もしくは特定の条件に一致するか」チェックして、
(3)一致する場合はLambdaやkinesisなど後続処理へ転送する
機能です。
【AWS公式】ロググループレベルのサブスクリプションフィルター
【Quita】cloudwatch logs の サブスクリプションフィルタ とは
このサブスクリプションフィルター機能は、
運用などに取り込むことができる非常に強力な機能です。
ログ管理の仕組みをわざわざコストを払って購入しなくとも、AWS純正の機能によりログ収集や
ログトリガーとしたアラート発報など可能になる便利なツールです。
筆者も何か要件あれば積極採用しています。
割と枯れたテクニックになっていることもあり、
ちょっとググればたくさん記事が出て来るところもうれしいですね!
問題点
サブスクリプションフィルターは大変強力な機能なので、
設定箇所を間違えると悲惨なことになります。
CloudWatchLogsのロググループは様々なサービスからの出力ログが自動格納されていきます。
ログ格納できるサービスは沢山ありますが、よく目にするものをいくつかピックアップします。
- Lambdaのデバッグログ
- CloudTrailのログ記録
- SNSサービスのログ
- VPCフローログ
- CloudWatchAgentから送付されるEC2(サーバ)のログ
上記どれにでも仕掛けられてしまう融通の良さにより、かえって問題となることがあります。
取り扱う仕組み次第で、簡単に無限ループを作れてしまいます。
開発者目線
「無限ループを作れてしまう」と繰り返し記述しておりますが、
開発者目線では仕掛ける場所を間違える、過剰に設定をしてしまうといったことは
「根本的にあり得ない」のです。どうしてあり得ないのか?要因を考えてみました。
これ、筆者にとっても、なかなか耳の痛い内容が含まれています。
サブスクリプションフィルターの「威力」に対する誤認識
- フィルターは強力な「ツール」だが、適切な使いどころを考えずに使うと問題を引き起こす。
- 開発者目線では、サブスクリプションフィルターは「特定のログを特定の目的で処理する」ための必殺技のようなもの。全てのロググループに乱用することは効率が悪く、設計上想定しない。
- 例:格ゲーの「昇龍拳」は強力だが、適切なタイミングで使わないと隙が大きい。これを乱発する感覚は、熟練者にはピンとこない。
開発者は「目的」を重視しすぎる傾向がある
- サブスクリプションフィルターは「何を抽出するか」という目的がはっきりしているため、必要のないログにまで設定することを考えない。
- 開発者目線では、目的外のログを処理するのはリソースの無駄であり、そもそも非効率的で「やらないこと」として切り捨てがち。
実際の操作ミスや人為的エラーを過小評価している
- 開発者はコードや設定を理論的に考えるため、実際に「全ログにサブスクリプションフィルターを設定する」ような操作ミスが起こる可能性を軽視しがち。
- 例:将棋のプロが「わざと王手を放置するようなミスをするとは考えられない」と思う感覚に似ている。だが初心者には起こりうる。
サブスクリプションフィルターの「コスト」を軽視しがち
- 開発者目線では、サブスクリプションフィルターは「便利なツール」という認識が強く、そのコスト(Lambdaの無限ループやS3の膨大な保存容量)を十分に意識しない。
- 特にクラウド環境に慣れていると、リソースは「スケーラブルで無限に使える」と考える傾向がある。
チームの「作業文化」に依存するリスクを認識していない
- 開発者目線では、「意図しない設定変更が発生する可能性」自体を見落としがち。特に個人で開発している場合、他人が誤った設定をするリスクを考慮しない。
- チーム開発では「何を設定して良いかの共通認識」が必要だが、それが不十分な場合に問題が発生する。
- 例:誰かが昇龍拳コマンドを練習しているだけなのに、対戦中に連発して大きな隙を晒すような状況。
サブスクリプションフィルターが「簡単に設定可能」な点を過小評価
- サブスクリプションフィルターは、AWSマネジメントコンソールやCLIで簡単に設定可能なため、「手軽に試せる」ことで乱用リスクが高まる。
- 開発者目線では、「これほど簡単な設定が破滅的な結果を引き起こす可能性がある」というギャップを認識しにくい。
ログの運用設計が後回しになる傾向
- 開発者は、ログの運用よりも「システムの動作」に注力することが多いため、ログをどのように管理・仕分けするかという運用設計を軽視しがち。
- 例:昇龍拳を使うための理論や入力タイミングに集中しすぎて、試合全体の流れや足場の状況を忘れる。
対策案
Lambdaが意図せず仕分けをしないようにする
Lambdaが処理するログの出所を明確に識別し、想定外の入力を無視するコードを記述します。
- CloudWatchロググループ名のチェック
処理対象とするロググループをハードコードや環境変数で指定し、マッチしない場合は処理をスキップ。複数ある場合は環境変数を使う、DynamoDBなどで一見管理するのもGood! - ログの構造検証
サブスクリプションフィルター経由で送られるログデータが特定の形式(JSONなど)であることを確認し、不正な形式のログを処理しない。
コード内で特定名のロググループからのみ処理を受け付けるようにする対策は、歯止めとして有効と考えます。
同時に「受け付けなかった処理」においてもLambdaはコールされている前提となるため、
「受け付けなかった処理」の最後にSNS Publishを記述してEmail通知するなど、
即時異常を察知できる仕組みも検討するべきでしょう。
(これならメールボックス上爆裂するので即気づけますね💦)
IAMロールの権限制限
Lambda関数のIAMロールを必要最小限に絞ることで、意図しないロググループにアクセスする権限を制限します。
- Lambdaの権限で特定のCloudWatchロググループからのログしか処理できないように設定。
- 誤ったサブスクリプションフィルターが設定されても、IAMでアクセスが拒否される。
例えば本番環境に実装するLambdaのIAMロールに対する権限を見直し、
CloudWatchReadOnlyAccessなどの
「自分自身のデバッグログを出力できない」権限に変えておくなどすれば
少なくとも無限ループは回避できるでしょう。
※即時デバッグできなくなるのがデメリットです
CloudWatchアラームの活用
- メトリクスフィルターを使ってLambdaの呼び出し回数やエラー回数を監視。
- アラームを設定して、特定の閾値を超えた場合にSNS通知を送信。
設定例としては以下のような感じです。
ただ限定的な要件に対する対策になります。ないよりマシぐらいの感覚でしょうか。
アラートは発報されすぎるとだれも関心を持たなくなりますので、
不必要な出力を控える検討も重要です。(誰も気にしないのであれば仕掛ける意味がありません)
- Lambda呼び出し回数の監視
指定のしきい値(例:毎秒100回以上)を超えたらアラート。 - S3の格納オブジェクト数の監視
CloudTrailログやS3の「PutObject」イベントをトリガーにモニタリング。
AWS Budgetアラート
- コストの急増を即時キャッチする仕組み
AWS Budgetで予算アラートを設定し、予算の一定割合に達したら通知を受け取るようにします。- 通知の閾値は日次・週次で細かく設定。
- SNSやメールでリアルタイムに受信。
これもないよりマシ程度ではありますものの、視点を変えて確認する手段として有効と考えます。
ログ処理コードに安全装置を実装
- Lambda関数内に再エントリ防止機構を組み込む。
- 処理済みのイベントには特定のタグやメタデータを付加し、再処理をスキップ。
- DynamoDBやS3を利用して、処理済みイベントIDを記録・照合。
ワンランク上の対策といえます。ログ文頭に【処理済】などと付与されている場合は再処理しない等、
文字列を付与することでループを防ぐ手段ですね。
ただログと関係がない出力に対してはノーケアの可能性があるため、実際にはあまり効果がないかもしれません。
作業手順の自動化
- TerraformやCloudFormationでインフラをコード化し、設定ミスを防止。
- CI/CDパイプラインでレビューや承認プロセスを追加。
設定作業をコントロールしてしまえば、作業者の熟練度が低くてもトラブル発生しないだろうという
発想、つまりIac化してしまえ!という考え方です。
ただ長期的にはデメリットがあると思っていて、短期的には作業ミスがなくなると思いますものの
「仕組みを理解しない作業者が量産される」ことにつながってしまいます。
結果「開発者が離職すると誰もメンテナンスできなくなる」ので、
過去に開発した仕組みがオーパーツ化してしまいます。
※おそらく筆者が開発した自動化やログ処理等の仕組みは、
筆者が離職するとオーパーツ化すると思います。だれか引き継いでくれるのかな。。。
最後に
CloudWatchLogsのサブスクリプションフィルター機能は非常に強力なツールであり、
無限ループ発生を恐れて実装を避ける というのももったいないことです。
願わくば、使いどころを見極め適切な設定を行って、上手に利用していきましょう!
設計書へ記述するのも忘れずに!
コメント