見出し画像

AWSコンテナログ収集実装ハンズオン【ECS、Fargate】


こんにちは。SHIFTのITソリューション部の當眞です。
AWSを専門に主に上流(要件定義、基本設計)行程を担当しています。

インフラエンジニアはコンテナが必修科目になってくると考えていますので、コンテナ関連の記事をどんどん書いていこうと思っています。

はじめに


  • AWSエンジニアでコンテナ未経験なので、AWSコンテナの使用感を最速でつかみたい

  • AWSでのコンテナのログ収集のイメージを最小の労力で簡単に身につけたい

といった方向けにサンプルのCDKコードで簡単にコンテナのログ収集基盤を作る手順をまとめています。AWSでのコンテナの基礎・概要を理解したい方は以下の記事もおすすめです。

【AWSコンテナ入門】コンテナ初心者向けガイド

本記事ではAWSコンテナ設計・構築[本格]入門 の5-6章のハンズオンが最短でできる構成にしています。AWSコンテナ設計・構築[本格]入門 の5-6章の内容を読んだ方がより理解は深まると思うのですが、読む時間が無く、最短で構築してコンテナのログ収集体験をしたい方向けにまとめました。

※AWSコンテナ設計・構築[本格]入門は良書なのでおすすめです。時間があればぜひ読んでみてください。
AWSコンテナ設計・構築[本格]入門

ハンズオン内容


本記事の構成は以下の通りです。

CDK経験者であれば3時間程度で完了できるハンズオンです。

  • CDK基礎
    CDKを使ったことない方の場合はまずはCDKの理解をする時間が別途必要になります。
    最初に簡単にですがCDKについても触れます。

  • 構築:サンプルのCDKコードでコンテナの実行環境およびログ収集環境を作る手順(3時間)
    ネットワーク構築からコンテナの配置してサンプルアプリをブラウザ表示し、ログ収集結果を確認できるまでの 手順が3時間以内でできるようにまとめています。

CDKコードによって設定はほとんど自動で完了しますので、コンテナ初心者の方でも、つまずくことなく設定できると思います。
構築した設定内容をマネコンで確認することも良い勉強になるかと思います。

【消し忘れは要注意】
ログ関連のサービスは無料枠で利用が可能です。
しかし、前提のコンテナ構築に利用したサービスは有料になります。
一部時間課金のサービスを利用するため、無料ではない点に注意してください。
できれば一日でやり切れると良いと思います。3時間でやり切れれば1USD以下だと思います。

※ハンズオンはWindowsのPCで動作確認できています。
※CDKのバージョンは2.101.0で実施しましたが、CDKは後方互換ありのため、最新Verでも問題なく動作するものと思います。

本ハンズオンを中断する場合は以下の対応を実施すれば課金を最小限に抑えられます。

・ECS、ELB、Endpointについて、CDKのコード(ecs-stack.ts)からコメントアウトして削除

CDK基礎


CDKを触ったことが無い方はCDKを理解してから本ハンズオンを実施することをおすすめします。
以下のCDK初心者向けのハンズオンをやっておくと良いでしょう。
本ハンズオンではCDKのTypescriptを利用していますので、Typescriptワークショップを実施してください。

コンテナイメージを作りコンテナレジストリに保管する手順


ここでは以下のハンズオンを実施します。
CDKやエディタ(VSCodeがおすすめ)のインストールはできているものとします。
(各コマンドは注記無ければVSCodeのPowerShellで実行しています。)

  1. ネットワークなど構築(IAM Role、VPC、サブネット、IGW、ルートテーブル)

  2. コンテナレジストリ構築(ECR)

  3. コンテナイメージ作成(Cloud9★で実施)
    ★は課金対象です。(他は無料かほぼ無料 ※Cloud9は無料枠が使えれば無料)

※本コードによって作成されるAWS構成図はAWSコンテナ設計・構築[本格]入門 の4章、5-6章をご確認頂ければと思います。

順を追って手順を示します。

サンプルCDKコード取得

どのパスでも良いので最初に「container-demo」というディレクトリを作成します。作成したディレクトリに移動します。

以下のコマンドを実行します。

git clone https://github.com/toma1110/container-log.git
cd .\container-log\ 
npm install
cdk ls

以下の通り表示されたらコード実行準備が完了です。

VpcStack
IamStack
EcrStack
EcsStack
SecretsManagerMasterUserStack
RdsStack
SecretsManagerDBUserStack

ネットワークなど構築(IAM Role、VPC、サブネット、IGW、ルートテーブル)

以下の通り順次、CDKを実行します。

cdk deploy IamStack

cdk deploy VpcStack

両コマンドの正常終了を確認できたらIAMとVPCリソースの作成は完了です。

コンテナレジストリ構築(ECR)

cdk deploy EcrStack

ECRの作成はこれで完了です。

コンテナイメージ作成(Cloud9★で実施)

Cloud9上で実施します。まずはCloud9を構築します。
Cloud9は有料のため、ハンズオンが終わったら削除しましょう。
削除し忘れるとストレージ料金がかかります。EC2インスタンスはCloud9が自動停止してくれます。

※CDKコードでCloud9を作成するとエラーになり、エラー解消ができなかったため、この部分はCDKコード化ができませんでした。

Cloud9作成手順

AWSマネージメントコンソールにてCloud9サービスを開きます。

「環境を作成」をクリックします。
以下の通り設定します。記載のない項目はデフォルトで大丈夫です。

  • 名前 任意の名前

  • インスタンスタイプ t3.small

  • プラットフォーム AmazonLinux2(※)

  • ネットワーク設定

    • 接続 セキュアシェル (SSH)

    • VPC設定

      • VPC:sbcntr-stg-vpc

      • subnet:sbcntr-stg-subnet-mng-1a

※AmazonLinux2023を選択すると後のコマンドがエラーで進めなくなるため要注意

しばらく待ち(5分くらい)正常に作成されたら「Cloud9 IDE」列の「開く」をクリックします。
ブラウザ上でIDEが表示されます。コンテナイメージ作成はこのIDE上で実施していきます。

Backendコンテナイメージ作成

Cloud9のIDE上で以下のコマンドを実施します。

  • コンテナイメージのビルド

git clone https://github.com/uma-arai/sbcntr-backend.git
cd sbcntr-backend/
docker image build -t sbcntr-stg-backend:v1 .

→2~3分くらい待ちます

  • イメージのリポジトリ登録

AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
docker image tag sbcntr-stg-backend:v1 ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-backend:v1
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-backend:v1
docker image rm -f $(docker image ls -q)
docker image ls

→ローカルのDockerイメージがすべて削除されたことを確認します。

  • イメージのプルと動作確認

docker image pull ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-backend:v1
docker image ls

→リポジトリからプルしてきたDockerイメージのみが表示されます。

docker container run -d -p 8080:80 ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-backend:v1
docker container ls

→container idをメモします。

curl http://localhost:8080/v1/helloworld

→ここで「{"data":"Hello world"}」と表示されれば正しくコンテナの作成が完了できています。

  • 不要イメージ、ディレクトリの削除

docker container stop <ここに「docker container ls」で確認したコンテナIDを入力>
docker image rm -f $(docker image ls -q)
cd ../
rm -rf sbcntr-backend

Cloud9ストレージ増加

Cloud9によって作成されたEC2のストレージ容量を10GBから20GBに変更します。

  • 参考手順(詳細はこのブログ の「【手順2】コンソールからボリュームサイズを変更する」を参照)

ボリュームはまずmodifyingの状態になりますが、すぐにOptimizingの状態になります。
Optimizingの状態なればサイズの変更は完了していますので、
Cloud9上で以下のコマンドを実行し、パーティション拡張します。
(Optimizingの状態はしばらく続きます)

lsblk

→以下のように表示されます。「/」のパーティションは10GBです。

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:0 0 20G 0 disk
├─nvme0n1p1 259:1 0 10G 0 part /
└─nvme0n1p128 259:2 0 1M 0 part

sudo growpart /dev/xvda 1
sudo xfs_growfs /dev/xvda1
lsblk

→「/」のパーティションが20GBになっていたらストレージの変更は完了です。

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:0 0 20G 0 disk
├─nvme0n1p1 259:1 0 20G 0 part /
└─nvme0n1p128 259:2 0 1M 0 part

Frontendコンテナイメージ作成

  • コンテナイメージのビルド

git clone https://github.com/uma-arai/sbcntr-frontend.git
cd sbcntr-frontend/
git reset --hard 1c13f7b3363a0f30efef94e3dd3313e838bb9889
docker image build -t sbcntr-stg-frontend:v1 .

→5分〜10分くらい待ちます。warningは無視して大丈夫です。

・git resetが必要な理由
https://github.com/uma-arai/sbcntr-frontend/commits/main/
上記URLより、2024/6/4のCommitによりエラーが発生するようになったと思われます。
筆者の意図は分からないのですが、ひとつ前のコミットで処理を行うことで正常に作業ができるようになりました。

  • イメージのリポジトリ登録

AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
docker image tag sbcntr-stg-frontend:v1 ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-frontend:v1
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-frontend:v1
docker image rm -f $(docker image ls -q)
docker image ls

→Dockerイメージがすべて削除されたことを確認します。

  • イメージのプルと動作確認

docker image pull ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-frontend:v1
docker image ls

→リポジトリからプルしてきたDockerイメージのみが表示されます。

docker container run -d -p 8080:80 ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-stg-frontend:v1
docker container ls

→container idをメモします。

curl http://localhost:8080/ |grep アライとウマカツ

→ここでHTMLの一部が行表示されることを確認します。

  • 不要イメージ、ディレクトリの削除

docker container stop <ここに「docker container ls」で確認したコンテナIDを入力>
docker image rm -f $(docker image ls -q)
cd ../
rm -rf sbcntr-frontend

ログ収集基盤構築実装


ここからは本格的に課金対象のリソースを作っていきます。
時間に余裕がなければここで今日はここまでで作業終了としても良いです。
(cloud9は自動停止してくれます)

  • ECS構築に必要なリソース構築(SG、★ELB、★VPC Endpoint)

  • ログ格納用S3バケット構築

  • ログ収集用コンテナ(サイドカー)イメージ作成

  • ECS構築(★ECS)

  • 後片付け

順を追って手順を示します。

ECS構築に必要なリソース構築(SG、★ELB、★VPC Endpoint)

cdk deploy EcsStack

→SG、ELB、VPCエンドポイントが作成されます。

S3構築

cdk deploy LogStack

→ログ格納用のS3が作成されます。

ログ収集用コンテナ(サイドカー)イメージ作成

ベースイメージをECRへ格納

Cloud9で以下のコマンドを実行します。

  •  ベースイメージの取得

docker image pull golang:1.16.8-alpine3.13
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
  • 取得したイメージをECRへ格納

AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
aws ecr --region ap-northeast-1 get-login-password | docker login --username AWS --password-stdin https://${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-base
docker image tag golang:1.16.8-alpine3.13 ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-base:golang1.16.8-alpne3.13
docker image push ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-base:golang1.16.8-alpne3.13

FireLens用コンテナのベースイメージ作成

空ファイルを作成します。(fluent-bit-custom.conf myparsers.conf stream_processor.conf Dockerfile)

mkdir base-logrouter && cd $_
touch fluent-bit-custom.conf myparsers.conf stream_processor.conf Dockerfile

以下ファイルの内容を各ファイルにペーストします。 https://github.com/uma-arai/sbcntr-resources/tree/main/firelens

cd /home/ec2-user/environment/base-logrouter
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
docker image build -t sbcntr-log-router .
aws ecr --region ap-northeast-1 get-login-password | docker login --username AWS --password-stdin https://${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-base
docker image tag sbcntr-log-router:latest ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-base:log-router
docker image push ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sbcntr-base:log-router

オーケストレータ構築(★ECS)

  • コード修正
    lib\stack\ecs_stack.tsの
    「targetGroupが無いとエラーになる。」
    と記載の個所をコメントインする

cdk deploy EcsStack

→ECS(クラスター、サービス、タスク定義)が作成されます。

動作確認

各種ログが正しく出力されているかを確認します。

アクセスログ出力

作成されたELBのsbcntr-stg-alb-frontendの方のDNS名をコピーします。(以下のようなURLです)
http://sbcntr-stg-alb-frontend-XXXXXXXXXX.ap-northeast-1.elb.amazonaws.com/

ブラウザで「Hello world」という画面を表示させ、アクセスログを出力させます。

アクセスログ確認(S3)

S3を開きsbcntr-[アカウントID]のバケットを選択します。

アクセスログが出力されていることを確認します。(拡張子がありませんが、テキストエディタで開くとログが確認できます。)

コンテナ起動ログ確認(CloudWatchLogs)

CloudWatchを開き、ロググループを選択します。

「/aws/ecs/sbcntr-firelens-container」のロググループに「stream processor started」と出力されていることを確認します。

アクセスログ確認(CloudWatchLogs)

「/ecs/sbcntr-stg-backend」のロググループの 「from-fluentbit/access-log」のログストリームを確認します。

まとめ


これでログ収集基盤構築ハンズオンは完了です!

作成したコンテナを実行し、S3とCloudWatchLogsにログを出しわけることができることの確認を行いました。

もし別環境でECSのコンテナが起動しない時、うまくログ出力されないときに、ここまで実施したハンズオンの設定と見比べることで、誤りに気付くことができるかもしれません。

後片付け


  • Cloud9の削除

  • 「sbcntr-~」と先頭につくバケットを空にして削除

  • ECRに格納されたイメージの削除(ECRにイメージが残っているとCDKのリソース削除に失敗するため)

  • cdk destroy --all の実行

これで後片付け完了です。お疲れさまでした。


執筆者プロフィール:當眞 尚平
AWSエンジニアです。インフラ案件上流(要件定義)から下流(運用)までこなします。
・得意分野:IaC(Terraform、CDK)
・AWS認定:SAP、SAA、DVA、SOA、DOP、MLS、DAS、SCS、ANS
・直近の目標:DevOpsエンジニアになる
・SHIFTでやっていること:IaC、CI/CD、AWSセキュリティ実装

✅SHIFTへのお問合せはお気軽に

SHIFTについて(コーポレートサイト)

SHIFTのサービスについて(サービスサイト)

SHIFTの導入事例

お役立ち資料はこちら

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/

PHOTO:Unsplashbharath kumar