
https://github.com/yuukanehiro/ECS-Laravel-CloudWatchLogs-Handson.git
もくじ
ゴール

Nginxのアクセスログから、実行速度の遅いURL(API)を抽出してパフォーマンス解析できるようにする。
構成

srcはLaravelプロジェクトです。
docker-compose.yaml
$ git clone https://github.com/yuukanehiro/ECS-Laravel-CloudWatchLogs-Handson.git $ cd ECS-Laravel-CloudWatchLogs-Handson $ ECS-Laravel-CloudWatchLogs-Handson % docker-compose up -d
http://localhost
でLaravelの画面が表示されたら成功です。
ポイントピックアップ
docker/php/nginx.conf
user www-data;
worker_processes auto;
error_log   /dev/stderr;
pid /var/run/nginx.pid;
events {
  worker_connections  1024;
}
http {
  # ALB Timeout対策
  fastcgi_connect_timeout 120;
  fastcgi_read_timeout    120;
  fastcgi_send_timeout    120;
  keepalive_timeout       120;
  keepalive_requests      100;
  client_header_timeout   60s;
  client_body_timeout     60s;
  include /etc/nginx/mime.types;
  default_type  application/octet-stream;
  log_format ltsv 'time:$time_iso8601\t'
    'remote_addr:$remote_addr\t'
    'request_method:$request_method\t'
    'request_length:$request_length\t'
    'request_uri:$request_uri\t'
    'https:$https\t'
    'uri:$uri\t'
    'query_string:$query_string\t'
    'status:$status\t'
    'bytes_sent:$bytes_sent\t'
    'body_bytes_sent:$body_bytes_sent\t'
    'referer:$http_referer\t'
    'useragent:$http_user_agent\t'
    'forwarded_for:$http_x_forwarded_for\t'
    'forwarded_proto:$http_x_forwarded_proto\t'
    'forwarded_port:$http_x_forwarded_port\t'
    'request_time:$request_time\t'
    'upstream_response_time:$upstream_response_time';
  log_format json escape=json '{'
    '"time": "$time_local",'
    '"host": "$host",'
    '"remote_user": "$remote_user",'
    '"status": "$status",'
    '"server_protocol": "$server_protocol",'
    '"request_method": "$request_method",'
    '"request_uri": "$request_uri",'
    '"query_string": "$query_string",'
    '"request": "$request",'
    '"body_bytes_sent": "$body_bytes_sent",'
    '"request_time": "$request_time",'
    '"upstream_response_time": "$upstream_response_time",'
    '"http_referer": "$http_referer", '
    '"http_user_agent": "$http_user_agent",'
    '"http_x_forwarded_for": "$http_x_forwarded_for",'
    '"http_x_forwarded_proto": "$http_x_forwarded_proto"'
  '}';
  include /etc/nginx/conf.d/*.conf;
}
CloudWatch Logs Insightで扱いやすいようにjson型のログフォーマットを用意しています。
バーチャルホストファイルには
server {
    listen 80;
    root /work/public;
    index index.php;
    charset utf-8;
    access_log /dev/stdout json;
    location / {
        root /work/public;
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
access_log /dev/stdout json;で標準出力に出力するようにして, フォーマットはJSON型を指定しています。
ECR作成からDockerイメージのpushまで
- AWS Cliは設定済みとする
ECRログイン
$ $(aws ecr get-login --no-include-email --region ap-northeast-1)
appのECRリポジトリ作成
$ aws ecr create-repository --repository-name app --region ap-northeast-1
{
    "repository": {
        "repositoryUri": "12312399.dkr.ecr.ap-northeast-1.amazonaws.com/app", 
        "registryId": "12312399", 
        "imageTagMutability": "MUTABLE", 
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:12312399:repository/app", 
        "repositoryName": "app", 
        "createdAt": 1621343423.0
    }
}
webのECRリポジトリ作成
$ aws ecr create-repository --repository-name web --region ap-northeast-1
{
    "repository": {
        "repositoryUri": "12312399.dkr.ecr.ap-northeast-1.amazonaws.com/web", 
        "registryId": "12312399", 
        "imageTagMutability": "MUTABLE", 
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:12312399:repository/web", 
        "repositoryName": "web", 
        "createdAt": 1621343424.0
    }
}
イメージのビルド $ docker build -t app -f docker/php/Dockerfile . $ docker build -t web -f docker/nginx/Dockerfile . appをECRリポジトリにpush $ docker tag app:latest 123123999.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest $ docker push 123123999.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest webをECRリポジトリにpush $ docker tag web:latest 123123999.dkr.ecr.ap-northeast-1.amazonaws.com/web:latest $ docker push 123123999.dkr.ecr.ap-northeast-1.amazonaws.com/web:latest
タスク定義
AWSのサービス検索欄で「ECS」と入力し、左のメニューバーの「タスク定義」をクリック

1.「新しいタスク定義の作成」をクリック

2.「EC2」を選択

3. 「タスク定義名」を適当に入力
4. ネットワークモードは「default」

タスク実行ロールを設定します。

5. 少し下に行き「コンテナの定義」で「コンテナの追加」をクリック
以下の表を参考にコンテナを作成してください。
appコンテナ
- コンテナ名 app
- イメージ イメージURL(ECR→app→イメージURLをコピーしてここに貼り付け)
- メモリ制限 ハード制限(300)
- 作業ディレクトリ /work
- DNS サーバー 8.8.8.8
- ログ設定 Auto-configure CloudWatch Logsにチェック
webコンテナ
- コンテナ名 web
- イメージ イメージURL(ECR→web→イメージURLをコピーしてここに貼り付け)
- ポートマッピング ホストポート→0,コンテナポート→80,プロトコル→tcp
- メモリ制限 ハード制限(300)
- 作業ディレクトリ /work
- リンク app
- DNS サーバー 8.8.8.8
- ログ設定 Auto-configure CloudWatch Logsにチェック
コンテナ追加を終えたら「作成」をクリック
クラスターの作成
次に左のメニュー欄から「クラスター」選択。
1.「クラスターの作成」をクリック
2.「EC2 Linux + ネットワーキング」を選択
3.「クラスター名」を入力
4.「インスタンスの設定」は以下のように設定
| プロビジョニングモデル | オンデマンドインスタンス | 
| EC2インスタンスタイプ | t2.small | 
| インスタンス数 | 1 | 
| キーペア | 先ほど作成したキーペアを選択 | 
「作成」をクリックしてください。
無事にクラスターが作成されたら成功です。
ALBの作成
ALBの作成を行います。
- 「ApplicationLoadBalancer(HTTP,HTTPS)」を選択
- 適当に名前を入力
- アベイラビリティーゾーンにECSの「VPC ID」と同じものを選択
- 次の手順を2回押し「3. セキュリティグループの設定」画面へ
- 新しいセキュリティグループを作成する(名前は適当に)
- 「ルーティングの設定」で名前だけ適当に入力し次の画面へ
- 「ターゲットの登録」で下のインスタンスからページ①のインスタンスを選択し「登録済みに追加」クリックし次の画面へ
- 「作成」をクリック
無事作成されれば成功です。
ECS側のセキュリティグループ設定

ALBのセキュリティグループからアクセスをすべて受け入れるようにインバウンドのルールに設定を追加してください。
タスクの実行
左のメニューの「クラスター」画面に行き、先ほど作ったクラスターの画面に行ってください。
そこから「タスク」→「タスクの実行」をクリック
| タスクの実行 | |
|---|---|
| 起動タイプ | EC2 | 
| タスク定義 | 先ほど作成したタスクを選択 | 
| タスクの数 | 1 | 
「タスクの実行」をクリック
「ステータス」が「RUNNING」になれば成功です!
ここが「STOPPED」になる場合は、おそらくタスク定義の設定ミスかDocker自体に問題があります。
サービスの作成

そのまますすめて、クラスターとALBを紐付けてください。

ALBのDNS名にアクセスしてLaravelの画面が見えたら成功です。
CloudWatch Logs Insightで解析しよう
CloudWatchサービスに移動して「インサイト」を選択します。
「ロググループを選択」でECSのタスク名を選択します。

クエリを入力して実行してください。
fields @timestamp, request_time, @message | sort request_time desc | limit 20
このクエリは実行速度の遅いリクエストを遅い順から抽出したものになります。
他には公式のドキュメントをご覧くださいませ


