次の監視標準になるか?Amazon Managed Service for Prometheus / Grafana
こんにちは、NRIデジタルの島です。
OSSの監視プロダクトとして有名な「Prometheus」、「Grafana」がAWSマネージドサービスとなり、パブリックプレビューとして公開されました。
・Prometheus
Amazon Managed Service for Prometheus(以下AMP)
What is Amazon Managed Service for Prometheus? – Amazon Managed Service for Prometheus
・Grafana
Amazon Managed Service for Grafana(以下AMG)
What is Amazon Managed Grafana? – Amazon Managed Grafana
AMP/AMGを利用することで、構築や運用管理コストがかなり軽減されると期待しておりますが、実際にどのようなメリットがあるのか、両サービスを触ってみたので内容を共有させていただこうと思います。
クラウド時代におけるシステムの監視
昨今のシステム構築は従来のオンプレミスから徐々にクラウド利用へシフトしてきており、システムのアジリティ向上の為、コンテナやサーバレス等のクラウドネイティブ技術の採用が進んできています。
モノリシックなシステムの場合、対象のサーバを集中的に監視していたと思いますが、クラウドネイティブ技術を利用したマイクロサービスアーキテクチャなど、分散化された環境においては監視の難易度はより高まります。
構成が分散・複雑化し、頻繁かつ動的に変化するシステム環境となる為、その環境下で「アプリケーションが正常に動作しているのか」、「問題がどこで起きているか」といったことについての可観測性(Observability)をいかに確保できるかが重要になってきます。
また、可観測性(Observability)は、サーバの状態を監視するのがメインである従来のモニタリングとは異なり、ビジネス/サービスのメトリクスまでをスコープとしていることが重要なポイントとなります。
Cloud Native Computing Foundation(以下CNCF)が提唱する「CloudNative TrailMap(クラウドネイティブ化を実現するためのステップ)」において、可観測性(Observability)は「Step4」に定義されています。
出典:GitHub – cncf/trailmap: 🗺TrailMap files from the cncf/landscape repo
(少々古いですが)CNCFにおけるRadarチームによる可観測性(Observability)の調査が下記にアップされておりますので、興味ある方は是非ご参照ください。
CNCF End User Technology Radar: Observability, September 2020 | Cloud Native Computing Foundation
可観測性(Observability)を実現する為のプロダクトは数多くあり、特徴もそれぞれ異なる為、プロジェクトにあったプロダクトを選択すべきかと思います。
この中でOSSとして利用実績も多いPrometheus/GrafanaがAWSのマネージメントサービス(AMP/AMG)としてパブリックプレビューとして利用可能になりました。
出典:CNCF Cloud Native Interactive Landscape 、下図は執筆時点のもの
AMP/AMG概要
Promethes、GrafanaはOSSとして提供されている為自由に改変、商用利用が可能です。
(ご参考)
サポートという観点で見ると、筆者の知る限りPrometheusは提供元による商用サポートサービスはありません。
Grafanaについては、「Grafana Labs」が商用サポート提供をしております。
Grafana: The open observability platform
なお、弊社親会社であるNRIには「OpenStandia」というOSSサポートサービスがあり、Prometheus、Grafana共に商用サポートも可能となっております。
OpenStandia
OSSサポート・保守サービス| OpenStandia™【NRI】
Prometheus、GrafanaをKubernetes環境(Amazon EKS(以下EKS))で構築した場合は、下記のような構成イメージになると思います。
Prometheus、GrafanaそれぞれPodでデプロイし、必要に応じて冗長化、外接(Grafanaコンソールアクセスやアラート通知等)、ストレージ等を自前で構築し、運用管理していく必要が出てきます。
筆者の経験においては、特に下記のような事項がボトルネックになるのでは?と考えています。
・Prometheus
- クエリの実行等のワークロードに応じたスケールが難しい
- メトリックデータの保存(永続化)について、ストレージ設計や構築、運用管理にコストがかかる
- 障害時の調査や復旧には相応のノウハウが必要
・Grafana
- コンソールへのアクセスについて、ネットワーク設計や構築(Ingress等)にコストがかかる
- データソース設定を一から実施する必要がある
- 作成したダッシュボードの保存(永続化)について、ストレージ設計や構築、運用管理にコストがかかる
一方、AMP/AMGを利用した場合は下記のような構成イメージとなります。
上記構成図の通り、自前で構築が必要なのはメトリックを収集しAMPへ送信する「Prometheus Server」やターゲットからメトリックを取得する「Exporter」のみで、環境構築は非常に容易です。
AMP/AMGを利用することで下記メリットが享受できます。
・AMP
- スケーラビリティとして「メトリクスデータの取り込み」、「ストレージへの保存」,「クエリの実行」のワークロードに応じてオートスケールが実施可能 ※1
- マルチAZ構成となっており、AMP のワークスペースに取り込まれたメトリクスデータは同一リージョン内の 3 つの AZ にレプリケートされ保存される為、データ消失のリスクがかなり少ない
- AMP自体はAWS管理の為、障害時の復旧はAWSの責務内で実施される
※1 AMPは水平スケーラビリティにCNCFプロジェクトの「Cortex」を使用しています。
Prometheusは冗長化やスケーリングをプロダクトとしてサポートしておらず、それらを実現するための標準的なアプローチであるCortexはアーキテクチャが複雑で自前で構築するのはかなり大変です。
GitHub – cortexproject/cortex: A horizontally scalable, highly available, multi-tenant, long term Prometheus.
・AMG
- NW環境を自前で構築することなく、SSOによるセキュアなアクセス環境が提供される
- 「Amazon CloudWatch(以下CloudWatch)」、「Amazon Elasticsearch Service」、「Amazon Timestream」、「AWS IoT SiteWise」、「AWS X-Ray(以下X-Ray)」、「AMP」などのAWSデータソースと統合されている為、導入時点で容易に連携可能 ※2
- 各種データはAMG内で保存(永続化)されている為、作成したダッシュボードや各種設定が消失に対する考慮は不要
※2 メトリック別に参照元がCloudWatch、Grafanaに泣き別れることは避けたいところです。
AMGを利用すると特別な設定不要で最初からこれらの統合が利用できる為、Grafanaで一元的に参照できるようになります。
また、両サービスともOSSコミュニティと積極的に連携することで、継続的に信頼性向上や機能拡張を行っているようです。
その為、バージョン更新やセキュリティパッチ適用など、自前で運用管理することなく実施可能となります。
また、当然ですがAWSのサポートが受けられることも大きなメリットとなります。
なお、執筆時点では両サービスともパブリックプレビューということもあり、利用可能なリージョンに制限がありますのでご注意ください。
利用可能なリージョン(執筆時点)
- 欧州(アイルランド)
- 欧州(フランクフルト)
- 米国東部(バージニア北部)
- 米国東部(オハイオ)
- 米国東部(オレゴン)
※検証時点では東京リージョンで利用できませんでしたが、執筆時点では利用可能なリージョンとして追加されています
また、機能面についても現時点で利用できないものがありますが、AMPについては以下をはじめ順次機能追加され利用可能になる見込みのようです。
- Prometheus アラートマネージャー
- Prometheus AlertingルールとRecordingルール
- メトリクスデータの保存期間設定
- CloudFormation のサポート
- ワークスペースのリソースのタグ付け etc…
※アラートマネージャーは2021年10月4日に機能公開されました
実機検証
では、実際にEKSにPrometheus Serverを構築し、AMP/AMGと連携する構成で動かしてみたいと思います。
・AMPの構築
Prometheus Serverの構築に先立ち、まずAMPを構築します。
基本的には下記Getting Startedの内容を実施することで構築可能です。
Getting Started
※東京リージョンがまだ利用不可ですので、米国東部(バージニア北部)で構築していきます
① AMPワークスペースの作成
AWSコンソールより、AMPのワークスペースを作成します。
下記の通り作成されます。
② IAMポリシー・ロールの作成とEKSサービスアカウントとの連携
EKS上にデプロイしたPrometheus Server(③で構築)からAMPワークスペースへメトリックを書き込みする為には下記設定が必要です。
- AMPワークスペースへリモート書き込み権限を持つIAMロールの作成
- OIDCプロバイダの作成と作成したIAMロールとの間の信頼関係の作成
- EKSのサービスアカウントの作成と作成したIAMロールとの紐づけ
Getting Startedのページに記載されているスクリプトを利用し、上記設定を一括で行います。
##!/bin/bash CLUSTER_NAME=coe-cluster1 AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) OIDC_PROVIDER=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///") PROM_SERVICE_ACCOUNT_NAMESPACE=prometheus GRAFANA_SERVICE_ACCOUNT_NAMESPACE=grafana SERVICE_ACCOUNT_NAME=iamproxy-service-account SERVICE_ACCOUNT_IAM_ROLE=EKS-AMP-ServiceAccount-Role SERVICE_ACCOUNT_IAM_ROLE_DESCRIPTION="IAM role to be used by a K8s service account with write access to AMP" SERVICE_ACCOUNT_IAM_POLICY=AWSManagedPrometheusWriteAccessPolicy SERVICE_ACCOUNT_IAM_POLICY_ARN=arn:aws:iam::$AWS_ACCOUNT_ID:policy/$SERVICE_ACCOUNT_IAM_POLICY # # Setup a trust policy designed for a specific combination of K8s service account and namespace to sign in from a Kubernetes cluster which hosts the OIDC Idp. # If the IAM role already exists, then add this new trust policy to the existing trust policy # echo "Creating a new trust policy" read -r -d '' NEW_TRUST_RELATIONSHIP <<EOF [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${OIDC_PROVIDER}:sub": "system:serviceaccount:${GRAFANA_SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}" } } }, { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${OIDC_PROVIDER}:sub": "system:serviceaccount:${PROM_SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}" } } } ] EOF # # Get the old trust policy, if one exists, and append it to the new trust policy # OLD_TRUST_RELATIONSHIP=$(aws iam get-role --role-name $SERVICE_ACCOUNT_IAM_ROLE --query 'Role.AssumeRolePolicyDocument.Statement[]' --output json) COMBINED_TRUST_RELATIONSHIP=$(echo $OLD_TRUST_RELATIONSHIP $NEW_TRUST_RELATIONSHIP | jq -s add) echo "Appending to the existing trust policy" read -r -d '' TRUST_POLICY <<EOF { "Version": "2012-10-17", "Statement": ${COMBINED_TRUST_RELATIONSHIP} } EOF echo "${TRUST_POLICY}" > TrustPolicy.json # # Setup the permission policy grants write permissions for all AWS StealFire workspaces # read -r -d '' PERMISSION_POLICY <<EOF { "Version":"2012-10-17", "Statement":[ { "Effect":"Allow", "Action":[ "aps:RemoteWrite", "aps:QueryMetrics", "aps:GetSeries", "aps:GetLabels", "aps:GetMetricMetadata" ], "Resource":"*" } ] } EOF echo "${PERMISSION_POLICY}" > PermissionPolicy.json # # Create an IAM permission policy to be associated with the role, if the policy does not already exist # SERVICE_ACCOUNT_IAM_POLICY_ID=$(aws iam get-policy --policy-arn $SERVICE_ACCOUNT_IAM_POLICY_ARN --query 'Policy.PolicyId' --output text) if [ "$SERVICE_ACCOUNT_IAM_POLICY_ID" = "" ]; then echo "Creating a new permission policy $SERVICE_ACCOUNT_IAM_POLICY" aws iam create-policy --policy-name $SERVICE_ACCOUNT_IAM_POLICY --policy-document file://PermissionPolicy.json else echo "Permission policy $SERVICE_ACCOUNT_IAM_POLICY already exists" fi # # If the IAM role already exists, then just update the trust policy. # Otherwise create one using the trust policy and permission policy # SERVICE_ACCOUNT_IAM_ROLE_ARN=$(aws iam get-role --role-name $SERVICE_ACCOUNT_IAM_ROLE --query 'Role.Arn' --output text) if [ "$SERVICE_ACCOUNT_IAM_ROLE_ARN" = "" ]; then echo "$SERVICE_ACCOUNT_IAM_ROLE role does not exist. Creating a new role with a trust and permission policy" # # Create an IAM role for Kubernetes service account # SERVICE_ACCOUNT_IAM_ROLE_ARN=$(aws iam create-role \ --role-name $SERVICE_ACCOUNT_IAM_ROLE \ --assume-role-policy-document file://TrustPolicy.json \ --description "$SERVICE_ACCOUNT_IAM_ROLE_DESCRIPTION" \ --query "Role.Arn" --output text) # # Attach the trust and permission policies to the role # aws iam attach-role-policy --role-name $SERVICE_ACCOUNT_IAM_ROLE --policy-arn $SERVICE_ACCOUNT_IAM_POLICY_ARN else echo "$SERVICE_ACCOUNT_IAM_ROLE_ARN role already exists. Updating the trust policy" # # Update the IAM role for Kubernetes service account with a with the new trust policy # aws iam update-assume-role-policy --role-name $SERVICE_ACCOUNT_IAM_ROLE --policy-document file://TrustPolicy.json fi echo $SERVICE_ACCOUNT_IAM_ROLE_ARN # EKS cluster hosts an OIDC provider with a public discovery endpoint. # Associate this Idp with AWS IAM so that the latter can validate and accept the OIDC tokens issued by Kubernetes to service accounts. # Doing this with eksctl is the easier and best approach. # eksctl utils associate-iam-oidc-provider --cluster $CLUSTER_NAME --region ap-northeast-1 --approve
③ Prometheus Serverのデプロイ
EKSクラスタへPrometheus Serverをデプロイします。
Getting Startedの手順の通りHelmを使用してデプロイします。
>IAM_PROXY_PROMETHEUS_ROLE_ARN=<ARN of the "EKS-AMP-ServiceAccount-Role" created in the previous step> >WORKSPACE_ID=<Workspace ID of the AMP workspace created earlier> >AWS_REGION=<AWS Region of the AMP workspace> >helm repo add prometheus-community https://prometheus-community.github.io/helm-charts >kubectl create ns prometheus >helm install prometheus-for-amp prometheus-community/prometheus -n prometheus -f ./amp_ingest_override_values.yaml \ --set serviceAccounts.server.annotations."eks\.amazonaws\.com/role-arn"="${IAM_PROXY_PROMETHEUS_ROLE_ARN}" \ --set server.remoteWrite[0].url="https://aps-workspaces.${AWS_REGION}.amazonaws.com/workspaces/${WORKSPACE_ID}/api/v1/remote_write" \ --set server.remoteWrite[0].sigv4.region=${AWS_REGION}
下記のようにエラーなく送信できているようであれば正常です。
>kubectl logs -f prometheus-for-amp-server-0 -n prometheus -c prometheus-server --- level=info ts=2021-06-17T01:00:07.285Z caller=db.go:1230 component=tsdb msg="Deleting obsolete block" block=01FFK8KQHXTYW943DWGBDD1Q8Q level=info ts=2021-06-17T01:00:07.310Z caller=head.go:880 component=tsdb msg="Head GC completed" duration=23.999924ms level=info ts=2021-06-17T03:00:01.066Z caller=compact.go:507 component=tsdb msg="write block" mint=1631664000020 maxt=1631671200000 ulid=01FFKPB61YGHYJ6C50J7DJE7DC duration=875.899683ms level=info ts=2021-06-17T03:00:01.070Z caller=db.go:1230 component=tsdb msg="Deleting obsolete block" block=01FFKFFN1QVZN9M86JA0BBZK70 level=info ts=2021-06-17T03:00:01.095Z caller=head.go:880 component=tsdb msg="Head GC completed" duration=24.227743ms level=info ts=2021-06-17T03:00:01.109Z caller=checkpoint.go:95 component=tsdb msg="Creating checkpoint" from_segment=650 to_segment=651 mint=1631671200000 level=info ts=2021-06-17T03:00:01.679Z caller=head.go:977 component=tsdb msg="WAL checkpoint complete" first=650 last=651 duration=569.344545ms level=info ts=2021-06-17T05:00:00.877Z caller=compact.go:507 component=tsdb msg="write block" mint=1631671200050 maxt=1631678400000 ulid=01FFKX6X9Y04KR6B7ARFKCACK6 duration=687.33268ms level=info ts=2021-06-17T05:00:00.882Z caller=db.go:1230 component=tsdb msg="Deleting obsolete block" block=01FFKPB61YGHYJ6C50J7DJE7DC level=info ts=2021-06-17T05:00:00.916Z caller=head.go:880 component=tsdb msg="Head GC completed" duration=34.279685ms ---
・AMGの構築
次にAMGの構築を行います。
① SSOの有効化とSSOユーザの作成
AMGは「AWS Single Sign-ON(以下SSO)」と統合されている為、前提としてSSOユーザの作成が必要です。
SSOを有効化し、SSOユーザを作成します。
② AMGワークスペースの作成
AWSコンソールより、AMGのワークスペースを作成します。
ワークスペース名の設定
認証アクセス、アクセス許可タイプの設定
AWSデータソース、通知チャネルの設定
ワークスペース作成後、①で作成したSSOユーザを紐づけます。
以上で、設定は完了です。
メトリック確認
実際にAMGへログインして、EKSクラスタのメトリックが参照できるか確認します。
作成したワークスペースの「GrafanaワークスペースURL」にアクセスし、作成したSSOユーザでログインします。
左メニューの「+」→「Import」から「Kubernetes cluster monitoring(via Prometheus)」ダッシュボード(3119)をインポートします。
データソースにはAMPを指定します。
正常にEKSクラスタの情報を可視化することが出来ました。
AWSデータソース
前述した通り、AMG導入すると既に下記データソースが利用可能です。
例えば、可観測性(Observability)を実現するうえで重要になるトレーシングについては、「AWS X-Ray(以下X-Ray)」を利用できます。
X-Rayデータソースを設定すると下記の通りトレーシング情報が取得できるようになります。
また、トレーシングという観点で言うと、CNCFにて最近IncubatingProjectとなった「OpenTelemetry」の仕様をサポートするディストリビューションとして「AWS Distro for OpenTelemetry(以下ADOT)」がパブリックプレビューとなりました。
パブリックプレビュー – AWS Distro for OpenTelemetry
ADOTもまたAMPとの統合をサポートしており、下記の通りOpenTelemetryのトレーシング情報をAMPへ取り込み、AMGで可視化することが可能です。
今回は検証していませんが、興味のある方は下記ドキュメントをご参照ください。
Getting Started with Prometheus Remote Write Exporter for AMP | AWS Open Distro for OpenTelemetry
※「Getting Started with Prometheus Remote Write Exporter for AMP」より引用
なお、執筆時点では下記の通りGAとなっております。
New for AWS Distro for OpenTelemetry – Tracing Support is Now Generally Available
権限制御
最後に、運用上必要になるAMGの権限関連を共有させていただきたいと思います。
AMGは運用性を考慮し、「Admin/Editor/Viewer」のロールにて権限制御が可能です。
詳細は下記ページをご参照ください。
User roles – Amazon Managed Grafana
実際に仕様通りロールごとに権限制御ができるか、確認してみました。
① SSO設定で下記グループとユーザを作成
まず、SSO設定でユーザとグループを作成します。
② AMGコンソールにてロール設定
AWSコンソールにてそれぞれのグループに対してロールを設定します。
※執筆時点では、Editorロールの設定が出来ませんでした
設定は以上です。
では、実際にログインしてみます。
・Adminロールのグループのユーザ
想定通りフルアクセス出来ました。
・Viewerロールのグループのユーザ
想定通り参照しか出来ないように制御されておりました。
・Editorロールのグループのユーザ
上記「②AMGコンソールにてロール設定」ではEditorのロール設定が出来ませんでしたが、Grafanaコンソールにてロール設定が出来ました。
設定後再ログインすると、想定通りダッシュボードの編集等の編集権限が付与されました。
(データソース設定等は不可)
さいごに
AMP/AMGを構築し、基本的な機能について触ってみました。
自前で構築・運用管理していた方々からすると、かなり魅力的なサービスではないでしょうか。
特にサーバ・ストレージ管理をAWSに寄せられることは大きなメリットだと思います。
執筆時点ではまだパブリックブレビューの為、SLAの定義もなく機能も絞られてますが、GA後は可観測性(Observability)を実現する為の候補として検討すべきサービスだと思います。
なお、先日「AzureAD」からAMGへ接続する方法のブログがMicrosoftから出ておりました。
チュートリアル: Azure Active Directory シングル サインオン (SSO) と Amazon Managed Grafana の統合
他クラウドベンダからの注目度も高いようです。
GAまでまだ先かもしれませんが、期待して待ちたいと思います。
以上