😎

Firelens を使用してECS (Fargate) 上にデプロイしたプロジェクトのログを S3 に収集する方法

2023/09/22に公開

はじめに

この記事は、すでにECS (Fargate) 上にプロジェクトのデプロイが完了したことを前提にしており、ECS (Fargate) 上に Nginx + PHP + Laravel の環境をデプロイした内容に焦点を当てています。

また、ECSのタスク定義とサービスの作成についてはコンソールではなく、AWS CLIを使用しています。

必要なポリシーについて

ロールにはAmazonECSTaskExecutionRolePolicyAmazonS3FullAccessAmazonSSMReadOnlyAccessの3つのポリシーをアタッチしてください。

既にプロジェクトのデプロイが完了しているので、S3にアクセスするためにAmazonS3FullAccessのポリシーを追加でロールにアタッチするだけで済むと思います。

S3の作成

ログを収集するためのS3を作成してください。

特に複雑な設定などは必要ないので、リージョンだけ注意して作成すれば良いかと思います。

タスク定義

タスク定義を作成するためのファイルを以下のように作成します。

今回はS3にnginxとlaravelのコンテナのログを収集したいのでタスク定義のファイルでは同じような内容になっています。

ecs-task-definition.json
{
  "family": "Firelens-logs", // お好きなタスク名
  "taskRoleArn": "arn:aws:iam::<アカウントID>:role/<タスク内のコンテナが他のAWSサービスにアクセスするためのIAMロール>", 
  "executionRoleArn": "arn:aws:iam::<アカウントID>:role/<タスク自体の実行と管理に必要なIAMロール>",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "nginx",
      "image": "<ECRでホストされているコンテナイメージのURI>",
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 80,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      "logConfiguration": {
        "logDriver": "awsfirelens", // ログデータを送信するために使用されるログドライバの種類を指定
        "options": {
          "Name": "s3",
          "bucket": "ecs-logs-firelens", // 作成したバケット名
          "region": "ap-northeast-1",
          "total_file_size": "1M",
          "upload_timeout": "1m",
          "use_put_object": "On"
        }
      }
    },
    {
      "name": "laravel",
      "image": "<ECRでホストされているコンテナイメージのURI>",
      "essential": false,
      "environment": [
        {
          "name": "APP_ENV",
          "value": "production"
        },
        {
          "name": "APP_DEBUG",
          "value": "true"
        },
        {
          "name": "LOG_CHANNEL",
          "value": "stderr"
        }
      ],
      "secrets": [
        {
          "name": "APP_KEY",
          "valueFrom": "arn:aws:ssm:ap-northeast-1:<アカウントID>:parameter/APP_KEY"
        },
        {
          "name": "APP_WORD",
          "valueFrom": "arn:aws:ssm:ap-northeast-1:<アカウントID>:parameter/APP_WORD"
        }
      ],
      "privileged": false,
      "readonlyRootFilesystem": false,
      "logConfiguration": {
        // 変更 ここから
        "logDriver": "awsfirelens", // ログデータを送信するために使用されるログドライバの種類を指定
        "options": {
          "Name": "s3",
          "bucket": "ecs-logs-firelens", // 作成したバケット名
          "region": "ap-northeast-1",
          "total_file_size": "1M",
          "upload_timeout": "1m",
          "use_put_object": "On"
        }
      }
    },
    // ここではFluent Bitのコンテナを作成しています
    {
      "name": "log-router", // お好きなコンテナ名
      "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable", // AWSの公開コンテナレジストリから提供されているイメージ
      "essential": true,
      "firelensConfiguration": {
        "type": "fluentbit", // FireLensがFluent Bitを使用することを指定
        "options": {} // 今回は独自の設定ファイルを指定しないので空
      },
      "logConfiguration": {
        "logDriver": "awslogs", // ログデータを送信するために使用されるログドライバの種類を指定
        "options": {
          "awslogs-create-group": "true", // ロググループが存在しない場合に、自動的にロググループを作成するかどうかを指定
          "awslogs-group": "ecs-logs-firelens", // ロググループの名前を指定
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "FargateService" // ログストリーム名を指定
        }
      }
    }
  ],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512"
}

タスクの作成

以下のコマンドで新しいタスクを作成することができます。
aws ecs register-task-definition --cli-input-json file://<タスク定義のファイル名>

以下のようになります。

aws ecs register-task-definition --cli-input-json file://ecs-task-definition.json

ECSのコンソールからタスクが作成されたか確認してください。

タスク名は、下記で指定したタスク名になっているはずです。

ecs-task-definition.json
"family": "Firelens-logs", // お好きなタスク名

サービスの作成

以下のコマンドで新しいサービスの作成することができます。

aws ecs create-service \
--cluster ecs-hands-on \ # サービスを作成するクラスターの名前を指定
--service-name ecs-logs \ # お好きなサービス名を指定
--task-definition <タスク名> \
--launch-type FARGATE \ # サービスのタスクをどのように実行するかを指定
--desired-count 1 \ # サービスで実行するタスクの数を指定
--network-configuration "awsvpcConfiguration={subnets=[<作成済みのサブネットID>],securityGroups=[<作成済みのセキュリティグループID>],assignPublicIp=ENABLED}"

--network-configurationの設定は、ECS サービスがどのVPC内のサブネットで実行され、どのセキュリティグループとパブリック IP アドレスの設定を使用するかを指定しています。

ECSのコンソールからサービスが作成されたか確認してください。

その後、S3にログが収集されていること、CloudWatchの指定したロググループにFluent Bitのコンテナのログが収集されているか確認してください。

ログを取得するには

S3のコンソールからログの詳細を見ていくと右上にダウンロードという項目があるので選択すると確認できます。

終わりに

何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉

Discussion