はじめに
初めまして!日鉄ソリューションズ株式会社(NSSOL) 流通・サービスソリューション事業本部 流通・サービスソリューション第三事業部 リテイルDXビジネスソリューション部 所属のharukaと申します。
私の所属する部では、業務を通じて蓄積した技術知見を社外へ発信を行う取り組みを始めました。今回その第一弾としてQiitaの記事を作成しました。
監視のお勉強として、サンプルアプリにAmazon Managed Service for Prometheus(以下AMP)、Grafanaを組み込んでみました。
※Prometheus→オープンソースのデータ収集ツール。サーバーのリソースの使用状況など、各種メトリクスを収集して監視ができます。
※Grafana→オープンソースのデータ可視化ツール。Prometheus等で収集したデータをわかりやすく可視化できます。
PrometheusはOSS版もありますが、今回はAWSサービスと組み合わせるためAWSマネージド版のAMPを使うことにしました。
Grafanaは今回OSS版をAmazon Elastic Container Service (以下ECS)コンテナにデプロイして使用することにしました。
(GrafanaにもAWSマネージドサービスがありますが、Amazon Organizationsの設定が必要であり、社内環境では利用が難しかったため断念しました。。。)
サンプルアプリについて
今回、サンプルアプリとしてamazon-ecs-java-microservices/3_ECS_Java_Spring_PetClinic_CICDを選びました。
単純なREST APIであり、機能ごとに5つのサービス(system,owner,pet,vet,visit)に分かれていて、リクエストのパスによってApplication Load Balancer (以下ALB)から各サービスへルーティングが行われる点が特徴です。
アプリケーションはECS上にデプロイするようになっています。
導入後のアーキテクチャイメージ
アプリケーションのメトリクスを収集するために、AWSがプレビューとして公開しているAWS Distro for OpenTelemetry Collector (以下ADOTCollector)をアプリケーションのサイドカーとしてデプロイします。
ADOTCollectorからAMPへメトリクスの送信を行い、その結果をECSクラスター上にデプロイしたGrafanaで確認しています。
今回、社内規定の関係でアプリケーションをAmazon Virtual Private Cloud (以下VPC)内のプライベートサブネットにデプロイしているので、各リソースからAMPへのアクセスの際にVPCエンドポイントを設置して、インターネットを介さない接続をしています。
導入手順
導入手順_AMP編
参考文献に従って、AMPをセットアップしていきます。
①Amazon managed Service for Prometheusワークスペースを作成する
②イメージを格納するためのAmazon Elastic Container Registry (以下ECR)リポジトリを作成する
-
ECRコンソール画面右上の「リポジトリを作成」をクリック
-
リポジトリ名に任意のリポジトリ名を入力
③adot-config.yamlファイルを修正する
- adot-config.yamlファイルのexporters.awsprometheusremotewrite.endpoint にPrometheusのリモート書き込みURLエンドポイントを記載する
adot-config.yaml
receivers:
awsecscontainermetrics:
collection_interval: 10s
processors:
filter:
metrics:
include:
match_type: strict
metric_names:
- ecs.task.memory.utilized
- ecs.task.memory.reserved
- ecs.task.cpu.utilized
- ecs.task.cpu.reserved
- ecs.task.network.rate.rx
- ecs.task.network.rate.tx
- ecs.task.storage.read_bytes
- ecs.task.storage.write_bytes
exporters:
awsprometheusremotewrite:
endpoint: # Prometheusのリモート書き込みURLエンドポイントを記載
aws_auth:
region: ap-northeast-1
service: aps
resource_to_telemetry_conversion:
enabled: true
logging:
loglevel: info
extensions:
health_check:
pprof:
endpoint: :1888
zpages:
endpoint: :55679
service:
extensions: [pprof, zpages, health_check]
pipelines:
metrics:
receivers: [prometheus]
exporters: [logging, awsprometheusremotewrite]
metrics/ecs:
receivers: [awsecscontainermetrics]
processors: [filter]
exporters: [logging, awsprometheusremotewrite]
④buildspec.ymlファイルを修正する
- buildspec.ymlファイルのCOLLECTOR_REPOSITORYに②で控えておいたECRリポジトリのURIを記載する
- AWSのドキュメントに従って、イメージのタグは「:ecs」としておきます。
buildspec.yml
- AWSのドキュメントに従って、イメージのタグは「:ecs」としておきます。
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- COLLECTOR_REPOSITORY= # ECRリポジトリのURIを記載
- aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin $COLLECTOR_REPOSITORY
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build . -t $COLLECTOR_REPOSITORY:ecs
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image...
- docker push $COLLECTOR_REPOSITORY:ecs
⑤Dockerfile, buildspec.yml, adot-config.yamlをAWS CodeCommitリポジトリに配置する
- AWS CodeCommitに新規リポジトリを作成し、Dockerfile, ③adot-config.yaml, ④buildspec.ymlファイルを配置する
Dockerfile
FROM public.ecr.aws/aws-observability/aws-otel-collector:latest
COPY adot-config.yaml /etc/ecs/otel-config.yaml
CMD ["--config=/etc/ecs/otel-config.yaml"]
⑥ADOTCollectorのコンテナイメージを作成しECRにプッシュする
- ⑤で作成したAWS CodeCommitリポジトリをソースとして、AWS CodeBuildにて新規ビルドプロジェクトを作成し、ECRにコンテナイメージをプッシュする
- (AWS CodeBuildの利用方法は各自調べてください。)
⑦アプリ側のECSタスク定義を修正する
- アプリ側の修正例として、参考までにpetclinicデモアプリのAWS CloudFormationテンプレートの一部を紹介する
- TaskDefinition.Properties.ContainerDefinitionsに、adot-collectorというコンテナを追加し、サイドカーとして定義する
- ImageにECRリポジトリのURI:ecs と記載する
- 修正が終わったら、改めてECSデプロイ作業を行うこと
petclinic-service.yaml
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub ${ECRRepository}
TaskRoleArn: !Ref TaskDefinitionServiceRole
ExecutionRoleArn: arn:aws:iam::265407044485:role/ecsTaskExecutionRole
ContainerDefinitions:
- Name: !Sub ${ECRRepository}
Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepository}:${ECRImageTag}
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-region: !Sub ${AWS::Region}
awslogs-group: !Ref ECSCluster
awslogs-stream-prefix: !Sub ${ECRImageTag}
Essential: true
Memory: !Ref ContainerMemorySize
PortMappings:
- ContainerPort: !Ref ContainerPort
Environment:
- Name: SPRING_PROFILES_ACTIVE
Value: mysql
- Name: SPRING_DATASOURCE_URL
Value: !Ref JDBCConnectionString
- Name: SPRING_DATASOURCE_USERNAME
Value: !Ref DBUsername
- Name: SPRING_DATASOURCE_PASSWORD
Value: cnabc2022
- Name: AWS_Region
Value: !Sub ${AWS::Region}
- Name: adot-collector
Image: # ECRリポジトリのURI:ecs と記載
Essential: true
Memory: 512
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-region: !Sub ${AWS::Region}
awslogs-group: !Ref ECSCluster
awslogs-stream-prefix: !Sub ${ECRImageTag}
Environment:
- Name: ECS_SERVICE_NAME
Value: !Sub ${ECRRepository}
⑧タスク実行ロールにAWS Identity and Access Management (以下IAM)ポリシーをアタッチする
⑨VPCエンドポイントを作成し、ECSクラスターのセキュリティグループを設定する
- VPC>仮想プライベートクラウド>エンドポイント>右上の「エンドポイントを作成」をクリック
- 名前タグに任意の名前を入力する
- サービスカテゴリは「AWSのサービス」とし、サービスにて「com.amazonaws.ap-northeast-1.aps-workspaces」を選択する
- 使用しているVPCとサブネットを選択する
- ECSクラスターのセキュリティグループを設定する
導入手順_Grafana編
Grafanaの方も参考文献が用意されています。ここではAWS Fargateを利用します。
①ECSにGrafanaコンテナを立てる
-
ECSにGrafanaコンテナを立てる
- ECSのタスク定義に、以下2つの環境変数を定義しておくこと
- AWS_SDK_LOAD_CONFIG=true
- GF_AUTH_SIGV4_AUTH_ENABLED=true
- ECSのタスク定義に、以下2つの環境変数を定義しておくこと
-
ブラウザで「http://(ALBのパス)/login」を打鍵するとGrafanaコンソール画面が表示される。
- ユーザ名/パスワード両方adminと入力しログイン
- ログイン後パスワードの変更を求められるため任意のパスワードを入力してsubmit
②VPCエンドポイントに、Grafanaのセキュリティグループを設定する
- GrafanaからAMPにデータを取得しに行くために、作成済のVPCエンドポイントにGrafanaコンテナのセキュリティグループを追加する
- 「セキュリティグループの管理」をクリック
- Grafanaコンテナのセキュリティグループを選択し、「セキュリティグループの変更」をクリック
③IAMユーザーを作成する
④PrometheusデータソースをGrafanaに追加する
-
Grafanaコンソール画面にて、サイドバーから設定(歯車マーク)を選択
-
HTTP URLの欄に、PrometheusのクエリURLエンドポイントから/api/v1/queryを抜いたものを入力する
- Authにて「SigV4 auth」を選択
- SigV4 Auth Detailsを以下のように入力
- Authentication Provider:Access & secret key
- Access Key ID:<③で作成したIAMユーザーのアクセスキー>
- Secret Access Key:<③で作成したIAMユーザーのシークレットアクセスキー>
- Default Region:ap-northeast-1
- 「Save & test」をクリックして、保存&接続テストを行う
- 接続テストに成功すると「Data source is working」と表示される
⑤ダッシュボードでメトリクスを確認する
- Grafanaダッシュボードが確認できる
- 各タスクのCPU使用量
- 各タスクのメモリ使用量
- 各タスクが受信したバイト数
- 各タスクが送信したバイト数
等
※今回はちょうどよいダッシュボードがなかったので、自作しました。
感想
Web上に文献が多くなく、公式ドキュメントを読み解きながら進める必要があり、トラブルシューティングが大変でしたが、いい経験になりました!
CloudWatchとAMP+Grafanaのグラフを見比べてみると、以下のようなメリットを感じました。
- より短い時間間隔でデータが取れる(CloudWatchではECSのメトリクスはデフォルトで1分間隔でしか取れないが、AMP+Grafanaはもっと細かく取れる。今回は10秒で取得)
- ダッシュボードのカスタマイズの自由度が高く、監視しやすい
機会があれば、AWSマネージド版のGrafanaを使った構成にもチャレンジしてみたいです。
登録商標
NS Solutions、NSSOL は、日鉄ソリューションズ株式会社の登録商標です。
Amazon Web Services, AWS, Amazon Managed Service for Prometheus, Amazon Organizations, Amazon Elastic Container Service, AWS Distro for OpenTelemetry Collector, Application Load Balancer, Amazon Virtual Private Cloud, Amazon Elastic Container Registry, AWS CodeCommit, AWS CodeBuild, AWS CloudFormation, AWS Fargate, AWS Identity and Access Managementは、Amazon.com, Inc. またはその関連会社の商標です。
本文中の会社名および商品名は、各社の商標または登録商標です。