Amazon Web Services ブログ

Amazon CloudWatch Logs Insights を用いたAmazon ECSライフサイクルイベントの効果的な分析

この記事は Effective use: Amazon ECS lifecycle events with Amazon CloudWatch logs insights (記事公開日: 2023 年 12 月 22 日) を翻訳したものです。

導入

スタートアップ企業から大手企業まで、コンテナサービスの採用が増加傾向にあることが観察されています。この傾向は、アプリケーションのデプロイが容易になったことや、オンプレミス環境からクラウドへの移行がしやすくなったことが要因となっています。多くのお客様が選択するプラットフォームの一つが、Amazon Elastic Container Service(Amazon ECS)です。Amazon ECS の強力でシンプルな特性により、お客様は単一のタスク管理から、企業全体のアプリケーションポートフォリオの監視、さらには数千のタスクの管理にまでスケールアップすることができます。Amazon ECS を利用することで、自社でコンテナオーケストレーションサービスを運用する際に伴う管理の負担が解消されます。

お客様と仕事をしていると、Amazon ECS イベントの活用をさらに高める価値ある機会があることに気づきました。ライフサイクルイベントは、サービスイベントをメトリクスやログと関連付けることで、トラブルシューティングに役立つ洞察を提供します。Amazon ECS は最新の100件のイベントのみを表示するため、過去のイベントを遡って確認することが難しい場合があります。Amazon CloudWatch Container Insights を使用することで、この問題が解決されます。Container Insights は Amazon ECS のライフサイクルイベントを Amazon CloudWatch Log Group に保存するからです。この連携により、イベントを遡って分析することが可能となり、運用効率が向上します。

Amazon EventBridge は、アプリケーションをシームレスに接続するサーバーレスのイベントバスです。Container Insights と併せて、Amazon ECS はイベントソースとして機能し、Amazon CloudWatch Logs は Amazon EventBridge のターゲットとして動作します。これにより、Amazon CloudWatch Logs Insights を使用したインシデント後の分析が可能になります。

本記事では、Container Insights や Amazon EventBridge 、あるいはその両方を使用して、Amazon CloudWatch Logs Insights のクエリを通じて Amazon ECS のサービスイベントを効果的に分析する方法を説明します。これらのクエリは、開発および運用のワークフローを大幅に改善します。

前提条件

このテクニカルガイドで紹介する手法を実践するためには、お客様のアカウントで以下の機能が有効になっている必要があります。

  1. アクティブなワークロードがある Amazon ECS クラスター
  2. Amazon EventBridge は、イベントを Amazon CloudWatch ログに直接ストリーミングするか、Amazon ECS CloudWatch Container Insights を有効にするように設定されている

ここでは、Amazon CloudWatch Logs または Container Insights にイベントをストリーミングするように Amazon EventBridge をセットアップするための詳細なガイドを紹介します。

Walkthrough

有用なライフサイクルイベントパターン

Elastic Container Service(Amazon ECS)が発行するイベントは、以下の4つのグループに分類できます:

  1. コンテナインスタンス状態変更イベント – これらのイベントは、Amazon ECS コンテナインスタンスの状態に変更があった場合にトリガーされます。これは、タスクの開始や停止、Amazon ECS エージェントのアップグレード、その他のシナリオなど、様々な理由で発生する可能性があります。
  2. タスク状態変更イベント – これらのイベントは、タスクの状態に変更があるたびに発行されます。例えば、タスクが「PENDING(保留中)」から「RUNNING(実行中)」に移行する場合や、「RUNNING(実行中)」から「STOPPED(停止)」に移行する場合などです。また、タスク内のコンテナが停止した場合や、AWS Fargate Spot キャパシティーの終了通知を受け取った場合にもイベントがトリガーされます。
  3. サービスアクションイベント – これらのイベントは、サービスの状態に関する情報を提供し、INFO、WARN、ERROR に分類されます。サービスが安定状態に達した場合、サービスが継続的にタスクを配置できない場合、Amazon ECS API がスロットリングされた場合、またはタスクを配置するためのリソースが不足している場合に生成されます。
  4. サービスデプロイメント状態変更イベント – これらのイベントは、デプロイメントが進行中、完了、または失敗した場合に発行されます。通常、サーキットブレーカーロジックとロールバック設定によってトリガーされます。

これらのイベントの詳細な説明と例、および考えられるユースケースについては、Amazon ECS イベントのドキュメントを参照してください。

それでは、運用サポートにイベントを活用する実際の例をいくつか見ていきましょう。これらの例を、イベントパターンに基づいて4つのカテゴリに分類しました:タスクパターン、サービスアクションパターン、サービスデプロイメントパターン、ECS コンテナインスタンスパターンです。各カテゴリには一般的な使用例が含まれており、具体的なクエリとその結果を示しています。

Amazon CloudWatch Logs Insights クエリの実行方法

この記事の後半で紹介する Amazon CloudWatch Logs Insights クエリを実行するには、以下の手順に従ってください。

  1. Amazon CloudWatch コンソールを開き、「Logs(ログ)」を選択し、次に「Logs Insights(ログのインサイト)」を選択します。
  2. クエリを実行する Amazon ECS イベントとパフォーマンスログを含むロググループ「/aws/events/ecs/containerinsights/(クラスター名)/performance」を選択します。
  3. 目的のクエリを入力し、「Run(クエリの実行)」を選択して結果を表示します。

タスクイベントパターン

シナリオ 1:

このシナリオでは、運用チームが環境内で観察された HTTP ステータス 5XX (サーバーサイドの問題)エラーの原因を調査する必要がある状況に遭遇しています。そのために、彼らは Amazon ECS タスクが意図したタスクライフサイクルを正しく踏んでいるかどうかを確認しようとしています。チームは、タスクのライフサイクルイベントが 5XX エラーの原因となっている可能性を疑っており、効果的なトラブルシューティングと解決を行うために、これらの問題の正確な原因を絞り込む必要があります。

必要なクエリ

クエリー入力:
detail.containers.0.taskArn: 対象タスク ARN

fields time as Timestamp, `detail-type` as Type, detail.lastStatus as `Last Status`, detail.desiredStatus as `Desired Status`, detail.stopCode as StopCode, detail.stoppedReason as Reason  
| filter detail.containers.0.taskArn = "arn:aws:ecs:us-east-1:111122223333:task/CB-Demo/6e81bd7083ad4d559f8b0b147f14753f"
| sort @timestamp desc
| limit 10
Apache Configuration

結果:

サービスイベントがタスクライフサイクルの確認にどのように役立つかを見てみましょう。結果から、タスクの最終ステータスが以下のように進行したことがわかります:

PROVISIONING > PENDING > ACTIVATING > RUNNING > DEACTIVATING > STOPPING > DEPROVISIONING > STOPPED

これはタスクライフサイクルの流れを確認するものであり、タスクは最初に「DEACTIVATED(非アクティブ化)」され、その後「STOPPED(停止)」されたことがわかります。このタスクの停止は、「Task failed container health checks(タスクがコンテナのヘルスチェックに失敗した)」という理由で、スケジューラ(ServiceSchedulerInitiated)によって開始されたことが確認できます。

同様に、クエリを使用して、ロードバランサーのヘルスチェックに失敗したタスクのライフサイクルの詳細を取得することもできます。結果は以下のようになります:

以下のクエリで、detail.containers.0.taskArn を目的のタスクARNに置き換えてください:

fields time as Timestamp, `detail-type` as Type, detail.lastStatus as `Last Status`, detail.desiredStatus as `Desired Status`, detail.stopCode as StopCode, detail.stoppedReason as Reason  
| filter detail.containers.0.taskArn = "arn:aws:ecs:us-east-1:111122223333:task/CB-Demo/649e1d63f0db482bafa0087f6a3aa5ed"
| sort @timestamp desc
| limit 10
Apache Configuration

StopTask を呼び出して手動で停止されたタスクの別の例を見てみましょう。この場合、アクションは UserInitiated (ユーザーによって開始された)で、理由は Task stopped by user (ユーザーによってタスクが停止された)となっています:

さらに、両方のケースにおいて、Desired State (必要なステータス)が(誰がタスクの停止を開始したかに関係なく)タスクの Last Status (前回のステータス)をどのように導いているかを確認することができます。

参考:タスクライフサイクル

シナリオ 2:

サービス内でタスクの失敗が頻繁に発生し、これらの問題の根本原因を診断する手段が必要となるシナリオを考えてみましょう。タスクは、リソースの制限やアプリケーションのエラーなど、さまざまな理由で終了する可能性があります。この問題に対処するために、サービス内のすべてのタスクの停止理由をクエリして、根底にある問題を明らかにすることができます。

必要なクエリ

クエリー入力:

detail.group: 対象のサービス名

filter `detail-type` = "ECS Task State Change" and detail.desiredStatus = "STOPPED" and detail.group = "service:circuit-breaker-demo"
|fields  detail.stoppingAt as stoppingAt, detail.stoppedReason as stoppedReason,detail.taskArn as Task
| sort @timestamp desc
| limit 200
Apache Configuration

ヒント:
サービスの自動スケーリングが有効になっていて、サービスに頻繁なスケーリングイベントがある場合は、上記のクエリにさらにフィルターを追加して、スケーリングに関連するイベントを除外し、他の停止理由に焦点を絞ることができます。

filter `detail-type` = "ECS Task State Change" and detail.desiredStatus = "STOPPED" and detail.stoppedReason not like "Scaling activity initiated by" and detail.group = "service:circuit-breaker-demo"
|fields  detail.stoppingAt as stoppingAt, detail.stoppedReason as stoppedReason,detail.taskArn as Task
| sort @timestamp desc
| limit 200
Apache Configuration

結果:

結果では、サービス内のタスクの停止理由と、それぞれのタスクIDを確認することができます。これらの停止理由を分析することで、タスクの終了につながる具体的な問題を特定できます。停止理由に応じて、考えられる解決策には、アプリケーションの調整、リソース割り当ての調整、タスク定義の最適化、またはスケーリング戦略の微調整などが含まれる可能性があります。

シナリオ 3:

セキュリティチームが特定のネットワークインターフェース、MAC アドレス、またはアタッチメント ID の使用に関する重要な情報を必要とするシナリオを考えてみましょう。Amazon ECS がタスクの開始と停止時に自動的に Elastic Network Interface(ENI)をプロビジョニングおよびデプロビジョニングすることは重要なポイントです。しかし、タスクが停止されると、Elastic Network Interface(ENI)や ENI に割り当てられた Media Access Control(MAC)情報を使用して、あるタスク ID を特定するための記録や関連性がすぐに利用できなくなります。Amazon ECS が自動的に ENI を管理する特性上、これらの識別子の履歴を追跡する能力が制限される可能性があるため、このようなデータを求めるセキュリティチームの要求に応えることが課題となります。

必要なクエリ

クエリー入力:

detail.attachments.0.details.1.value : 対象となる ENI ID

追加:タスク ARN とクラスター ARN の詳細の置換

fields @timestamp, `detail.attachments.0.details.1.value` as ENIId,`detail.attachments.0.status` as ENIStatus, `detail.lastStatus` as TaskStatus
| filter `detail.attachments.0.details.1.value` = "eni-0e2b348058ae3d639" 
| parse @message "arn:aws:ecs:us-east-1:111122223333:task/CB-Demo/*\"" as TaskId
| parse @message "arn:aws:ecs:us-east-1:111122223333:cluster/*\"," as Cluster
| parse @message "service:*\"," as Service
| display @timestamp, ENIId, ENIStatus, TaskId, Service, Cluster, TaskStatus
Apache Configuration

ENI ID で検索するには、detail.attachments.0.details.2.valueの値を MAC アドレスに置き換えてください。

fields @timestamp, `detail.attachments.0.details.1.value` as ENIId, `detail.attachments.0.details.2.value` as MAC ,`detail.attachments.0.status` as ENIStatus, `detail.lastStatus` as TaskStatus
| filter `detail.attachments.0.details.2.value` = '12:eb:5f:5a:83:93'
| parse @message "arn:aws:ecs:us-east-1:111122223333:task/CB-Demo/*\"" as TaskId
| parse @message "arn:aws:ecs:us-east-1:111122223333:cluster/*\"," as Cluster
| parse @message "service:*\"," as Service
| display @timestamp, ENIId, MAC, ENIStatus, TaskId, Service, Cluster, TaskStatus
Apache Configuration

結果:

ENI ID により、ENI がプロビジョニングされたタスク/サービス/クラスターの詳細と、関連付いたタスクの状態が結果に表示されます。

ENI と同様に、 MAC アドレスでクエリを実行しても ENI の時と同じ詳細内容を確認できます。

サービスアクションイベントパターン

シナリオ 4:

最も多くの障害が発生しているサービスを特定し、その解決を優先する必要がある状況に遭遇するかもしれません。これを達成するために、問題が発生している上位 N 個のサービスをクエリして特定したいと考えています。

必要なクエリ:

filter `detail-type` = "ECS Service Action" and @message like /(?i)(WARN)/
| stats count(detail.eventName) as countOfWarnEvents by resources.0 as serviceArn, detail.eventName as eventFault
| sort countOfWarnEvents desc
| limit 20
Apache Configuration

結果:

WARN イベントをフィルタリングし、サービス固有の発生を集計することで、即座に対応が必要なサービスを特定できます。たとえば、このケースでは ecsdemo-auth-no-sd というサービスが SERVICE_TASK_START_IMPAIRED エラーに直面しています。これにより、最も影響の大きい問題の緩和と、マイクロサービスエコシステム全体の信頼性向上にリソースを集中させることができます:

サービス展開イベントパターン

シナリオ 5:

Amazon ECS のすべてのサービスには、INFO、WARN、ERROR のいずれかのイベントタイプがあることがわかっているので、これを検索パターンとして使用して、問題のあるサービスについてワークロードを分析することができます。

必要なクエリ:

fields @timestamp as Time, `resources.0` as Service, 
`detail-type` as `lifecycleEvent`, `detail.reason` as `failureReason`, @message
| filter `detail.eventType` = "ERROR"
| sort @timestamp desc
| display Time, Service, lifecycleEvent, failureReason
| limit 100
Apache Configuration

結果:

以下の結果では、ecsdemo-backend サービスがタスクの正常なデプロイに失敗しており、これによって Amazon ECS のサーキットブレーカーメカニズムが作動し、サービスのデプロイメントが停止されています。テーブルの左側にある展開矢印を使用すると、イベントに関するより詳細な情報を得ることができます:

サービス展開イベントパターン

シナリオ 6:

このシナリオでは、あなたは運用チームから通知を受け取りました。最近の Amazon ECS サービスへのデプロイメント後も、アプリケーションの以前のバージョンがまだ表示されているとのことです。新しいデプロイメントが予想通りに古いものを置き換えなかったという状況に直面しており、混乱や潜在的な問題を引き起こしています。運用チームは、デプロイメントプロセス中に発生したイベントの一連の流れを理解し、何が問題だったのか原因を特定し、デプロイメントを確実に成功するために必要な是正措置を実施したいと考えています。

必要なクエリ

クエリー入力:

resources.0: 対象サービス ARN

fields time as Timestamp, detail.deploymentId as DeploymentId , detail.eventType as Severity, detail.eventName as Name, detail.reason as Detail, `detail-type` as EventType
| filter `resources.0` ="arn:aws:ecs:us-east-1:12345678910:service/CB-Demo/circuit-breaker-demo"
| sort @timestamp desc
| limit 10
Apache Configuration

結果:

デプロイメント中に何が問題だったのかを理解するため、サービスイベントを分析してみましょう。イベントの順序を調べることで、明確なタイムラインが浮かび上がります:

  1. サービスが最初は安定状態にあり(7行目)、デプロイメントは適切であった(6行目の ecs-svc/6629184995452776901)ことがわかります。
  2. 新しいデプロイメント(ecs-svc/4503003343648563919)が発生し、おそらくコードのバグがあったと思われます(5行目)。
  3. このデプロイメントのタスクが起動に失敗しています(3行目)。
  4. この問題のあるデプロイメントがサーキットブレーカーロジックをトリガーし、以前の正常なデプロイメント(4行目の ecs-svc/6629184995452776901)へのロールバックを開始しています。
  5. 最終的にサービスは安定状態に戻ります(1行目と2行目)。

このイベントの流れは、何が起こったかの時系列的な視点を提供するだけでなく、関連するデプロイメントと問題の潜在的な理由についての具体的な洞察も提供しています。これらのサービスイベントを分析することで、運用チームは問題のあるデプロイメント(つまり、ecs-svc/4503003343648563919)を特定し、さらに調査して根本的なコードの問題を特定し対処することができ、将来のデプロイプロセスの信頼性が高まります。

ECS コンテナインスタンスのイベントパターン:

シナリオ 7:

クラスター内のコンテナインスタンスに対する Amazon ECS エージェントの更新履歴を追跡したいと考えています。追跡可能な履歴があれば、エージェントに必要なパッチと更新がインストールされていることを確認できるため、セキュリティ基準への準拠が保証されます。また、問題のある更新があった場合にロールバックの検証も可能になります。この情報は、運用効率とサービスの信頼性に役立ちます。

必要なクエリ:

fields @timestamp, detail.agentUpdateStatus as agentUpdateStatus, detail.containerInstanceArn as containerInstanceArn,detail.versionInfo.agentVersion as agentVersion
| filter `detail-type` = "ECS Container Instance State Change"
| sort @timestamp desc
| limit 200
Apache Configuration

結果:

結果からわかるように、コンテナインスタンスのエージェントは v 1.75.0 でした。 エージェントの更新がトリガーされると、エージェントを更新するプロセスはシーケンス9で開始され、最終的にシーケンス1で完了しました。

当初、コンテナインスタンスは ECS Agent バージョン 1.75.0 で動作していました。 その後、シーケンス 9 で更新操作が開始され、新しい Amazon ECS エージェントバージョンが存在することが示されました。 一連のアップデートアクションの後、エージェントアップデートはシーケンス1で正常に終了しました。 この情報は、バージョン移行と更新手順の明確なスナップショットを提供し、ECS クラスターのセキュリティ、信頼性、および機能性を確保するために Amazon ECS エージェントの更新を追跡することの重要性を強調しています。

クリーンアップ

サンプルクエリの探索が完了したら、追加のコストが発生しないように、Amazon EventBridge ルールと Amazon ECS CloudWatch コンテナインサイトを必ず無効にしてください。

結論

この記事では、トラブルシューティングに貴重なリソースである Amazon ECS イベントの可能性を最大限に活用する方法を探ってきました。Amazon ECS は、タスク、サービス、デプロイメント、およびコンテナインスタンスに関する有用な情報を提供します。Amazon CloudWatch Logs で ECS イベントを分析することで、時間の経過に伴うパターンの特定、他のログとのイベントの相関関係の把握、繰り返し発生する問題の発見、そして様々な形式の分析を行うことができます。

我々は、Amazon ECS イベントを検索し活用するための簡単でありながら強力な方法を概説しました。これには、予期せぬ停止を素早く診断するためのタスクのライフサイクルの追跡、セキュリティを強化するための特定のネットワーク詳細を持つタスクの特定、問題のあるサービスの特定、デプロイメントの問題の理解、そして信頼性のための Amazon ECS エージェントの最新状態の確認が含まれます。システムの運用に関するこの幅広い視点により、問題に積極的に対処し、コンテナのパフォーマンスに関する洞察を得て、スムーズなデプロイを促進し、システムのセキュリティを強化することができます。

その他の参考資料

ライフサイクルイベントの基本について説明したので、次はトラブルシューティングの目的で Amazon CloudWatch Log Insights コンソールでこれらのライフサイクルイベントをクエリするベストプラクティスを見てみましょう。 Amazon CloudWatch クエリのドメイン固有言語 (DSL) の詳細については、ドキュメント (CloudWatch ログインサイトのクエリ構文) を参照してください。

Amazon ECS イベントの EventBridge をさらに処理することで、異常検出をさらにセットアップすることができます。これについては、「Amazon EventBridge を利用した Amazon Elastic Container Service Anomaly Detector」で詳しく説明されています。

翻訳はクラウドサポートエンジニアの桐生が担当しました。原文はこちらです。