
こんにちは。
アプリケーションサービス本部 DevOps 担当の兼安です。
前回に続けてもう一つ Amazon Managed Grafana のことを述べます。
Amazon Managed Grafana で DynamoDB のデータを可視化する方法の一つを紹介します。
- はじめに
- 本記事のターゲット
- 本記事の検証環境
- 今回紹介する構成
- VPC+Lambda+DynamoDB+プライベートAPIのAWS CDKコード
- NetworkStack — VPC設計
- DynamoDbApiDatasourceStack — セキュリティグループ
- DynamoDbApiDatasourceStack — VPC Endpoint
- DynamoDbApiDatasourceStack — Lambda関数とIAMポリシー
- DynamoDbApiDatasourceStack — Private API Gateway
- Lambda関数の実装(Python)
- CDKデプロイ
- VPC の ID、サブネットの ID、API の VPC Endpoint の ID
- Managed GrafanaのワークスペースID
- プライベート API のエンドポイントURL
- Managed GrafanaをVPCに接続する
- Infinity Pluginのインストール
- ダッシュボードへの設定方法
- 最後に
- 参考リンク
はじめに
本記事では、各種サービスおよび言語を以下のように記述します。
- Amazon Managed Grafana:Managed Grafana
- AWS Lambda:Lambda
- Amazon DynamoDB:DynamoDB
- Amazon API Gateway:API Gateway
- AWS CDK:CDK
Managed Grafana は、Amazon Aurora や Amazon Timestream などの連携がしやすくなっています。
一方で、本記事執筆時点(2026年7月)、DynamoDB との連携は有料プラグインが必要な仕様になっています。
これに対して本記事では、Infinity Plugin + プライベート API 構成を用いることで、API 経由で DynamoDB のデータを可視化する方法を紹介します。
本記事のターゲット
本記事は Grafana と DynamoDB および AWS Lambda、Amazon API Gateway などの基礎知識がある方を想定しています。
ご了承ください。
本記事の検証環境
| ソフトウェア | バージョン |
|---|---|
| Amazon Managed Grafana | 10.4 |
| AWS CDK | 2.259.0 |
| Python(Lambda ランタイム) | 3.14 |
今回紹介する構成
本記事で紹介する構成の全体像は以下のとおりです。
この後で、かなり長く説明を書いていきますが、結論を言うと、下記構成で DynamoDB のデータを Managed Grafana で可視化できることを知ってもらえれば OK です。

Managed Grafana の Infinity Plugin が Private API Gateway のエンドポイントを呼び出し、Lambda が DynamoDB からデータを取得して JSON で返す、というシンプルなデータフローです。
構成のポイントは以下のとおりです。
- Managed Grafana ワークスペースは VPC に接続し、プライベートサブネット内に ENI を作ることができます。これにより、Managed Grafana から VPC 内のリソースにアクセスできるようにしています。
- API Gateway はプライベート API を作ることができます。これを用いて、VPC Endpoint 経由でのみアクセス可能な REST API を作ります。
- Lambda は API Gateway からのリクエストを受け取り、DynamoDB にクエリを実行して結果を JSON で返却するようにします。
- Managed Grafana から Private API Gateway へアクセスするために Interface VPC Endpoint を設けています。
- VPC 内に配置した Lambda から DynamoDB へアクセスするために Gateway VPC Endpoint を設けています。
DynamoDB のテーブル構造は以下のようにしています。
| 属性名 | 型 | キー | 説明 |
|---|---|---|---|
metric_name |
String | パーティションキー | メトリクス名(例: cpu_usage, memory_usage) |
timestamp |
String | ソートキー | ISO 8601 形式のタイムスタンプ(例: 2025-01-01T00:00:00Z) |
value |
Number | — | メトリクスの値 |
unit |
String | — | 単位(例: percent, count, milliseconds) |
API Gateway+Lambda によるプライベート API はこのテーブルを参照し、以下の書式の JSON を返します。
[ { "timestamp": "2025-01-01T00:00:00Z", "value": 45.2, "metric_name": "cpu_usage", "unit": "percent" }, { "timestamp": "2025-01-01T00:05:00Z", "value": 52.8, "metric_name": "cpu_usage", "unit": "percent" } ]
このプライベート API を Managed Grafana から呼び出して可視化します。
GrafanaのDynamoDBプラグインのメリットと制約
本題に入る前に、Grafana が公式に提供している DynamoDB プラグインについて触れておきます。
Grafana Labs は Amazon DynamoDB データソースプラグイン を提供しています。
このプラグインを使えば、DynamoDB テーブルに対して直接クエリを実行し、結果をダッシュボードに表示できます。
後述の Infinity Plugin + API Gateway のような中間レイヤーを構築する必要がなく、設定もシンプルです。
ただし、このプラグインは Grafana Enterprise ライセンスが必要です。
Amazon Managed Grafana は AWS のサービスですが、Grafana Enterprise ライセンスは Grafana Labs との契約になります。
したがって、AWS の利用料金とは別に Grafana Labs へのライセンス費用が発生します。
Enterprise ライセンスは DynamoDB プラグイン以外にも多くのエンタープライズ機能を含むため、それらの機能もあわせて活用するのであれば十分に検討の価値があります。
本記事で紹介する Infinity Plugin + Private API Gateway 構成は、Enterprise ライセンスなしで DynamoDB のデータを可視化できる代替手段です。
一方で、VPC Endpoint や Lambda など複数のリソースを構築・管理する必要があり、構成の複雑さは増すとともに、クエリによる柔軟性はないというデメリットがあります。
本記事では後者を選択していますが、どちらが適切かはプロジェクトの要件次第です。
Infinity PluginによるAPI連携
Infinity Plugin は、Grafana Labs がオープンソースで提供しているデータソースプラグインです。
JSON、CSV、XML、GraphQL など、さまざまな形式の REST API レスポンスを Grafana のダッシュボード上で可視化できます。
通常の Grafana データソースプラグイン(CloudWatch、Prometheus など)は特定のバックエンドサービスとの接続を前提としていますが、Infinity Plugin は JSON を返却する API 全般が対象となる汎用的なプラグインです。
本構成では、この特性を活用します。
Lambda が DynamoDB のデータを JSON 形式で返す API を用意し、Infinity Plugin がその API を呼び出してデータを取得します。
Infinity Plugin の利用にはライセンス契約は不要です。
Managed Grafana ではプラグイン管理画面からインストールできます。
参考:Infinity data source plugin for Grafana(公式ドキュメント)
API Gateway のプライベート REST API
API Gateway のプライベート REST API は、Amazon API Gateway のエンドポイントタイプの一つで、VPC 内からのみアクセス可能な API です。
API Gateway による通常の REST API はインターネットに公開されるため、認証・認可を検討する必要がありますが、プライベート REST API は VPC 内からの閉じた通信でのみアクセスできます。
本構成では、このプライベート REST API を使用します。
プライベート REST API の設定は以下のとおりです。
- API のエンドポイントタイプを
PRIVATEに設定する - VPC 内に Interface VPC Endpoint を作成する
- API のリソースポリシーで
aws:sourceVpce条件を指定し、許可する VPC Endpoint ID を限定する
この仕組みにより、Managed Grafana(VPC 接続経由)→ VPC Endpoint → Private API Gateway → Lambda → DynamoDB という経路が、すべて VPC 内で完結します。
参考:プライベート API の作成(AWS公式ドキュメント)
Managed GrafanaのVPC接続
Managed Grafana はマネージドサービスであり、通常はインターネット経由でデータソースにアクセスします。
しかし、VPC 内のプライベートリソース(Private API Gateway など)にアクセスするには、ワークスペースを VPC に接続する必要があります。
VPC 接続を設定すると、Managed Grafana は指定したサブネット内に ENI(Elastic Network Interface)を作成し、VPC 内のリソースと直接通信できるようになります。
これにより、インターネットを経由せずに Private API Gateway の VPC Endpoint へアクセスできます。
VPC 接続には以下が必要です。
- Managed Grafana 用のセキュリティグループ
- VPC 内のプライベートサブネット(2つ以上)
本構成では、CDK でインフラを構築した後に AWS CLI で VPC 接続を設定します。
CDK で完結することもできるとは思いますが、コードの複雑さが増すのと、記事として説明するのが難しくなるため、あえて CDK+AWS CLI の合わせ技構成としました。
参考:Amazon Managed Grafana の VPC 接続(AWS公式ドキュメント)
VPC+Lambda+DynamoDB+プライベートAPIのAWS CDKコード
今回の構成のうち VPC・Lambda・DynamoDB・Private API Gateway の部分を CDK で構築します。ポイントを抜粋して説明します。
スタック構成は以下のとおりです。
| スタック | 主なリソース |
|---|---|
| NetworkStack | VPC、パブリック/プライベートサブネット |
| DatabaseStack | DynamoDB テーブル |
| DynamoDbApiDatasourceStack | VPC Endpoint、Lambda、Private API Gateway |
NetworkStack — VPC設計
VPC は NAT Gateway なし、パブリックサブネットとプライベートサブネットの構成です。
プライベートサブネットは PRIVATE_ISOLATED を指定します。
PRIVATE_ISOLATED は、インターネットへのルートも NAT もないサブネットです。
this.vpc = new ec2.Vpc(this, 'Vpc', { vpcName: `${prefix}-vpc-main`, maxAzs: 2, natGateways: 0, subnetConfiguration: [ { cidrMask: 24, name: 'Public', subnetType: ec2.SubnetType.PUBLIC }, { cidrMask: 24, name: 'Private', subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, ], });
DynamoDbApiDatasourceStack — セキュリティグループ
Lambda 用と VPC Endpoint 用に 2 つのセキュリティグループを作成します。
Lambda は VPC 内に配置するためセキュリティグループが必要で、
execute-api VPC Endpoint にもアクセス制御用のセキュリティグループを設定します。
const lambdaSecurityGroup = new ec2.SecurityGroup(this, 'LambdaSecurityGroup', { vpc, securityGroupName: `${prefix}-sg-lambda-metrics-api`, allowAllOutbound: false, }); const vpceSecurityGroup = new ec2.SecurityGroup(this, 'VpceSecurityGroup', { vpc, securityGroupName: `${prefix}-sg-vpce-execute-api`, allowAllOutbound: false, }); // Lambda SG → VPCE SG へのインバウンド(HTTPS)を許可 vpceSecurityGroup.addIngressRule(lambdaSecurityGroup, ec2.Port.tcp(443)); // Lambda SG からのアウトバウンド(HTTPS)を許可(DynamoDB Gateway Endpoint 向け) lambdaSecurityGroup.addEgressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443));
ここで作成した grafana-db-conn-dev-sg-vpce-execute-api が後述の VPC 接続設定で参照するセキュリティグループです。
Managed Grafana 用のセキュリティグループは VPC 接続時に CLI で作成し、
そのタイミングでこの VPCE SG への受信ルールも追加します。
DynamoDbApiDatasourceStack — VPC Endpoint
VPC Endpoint を 2 種類作成します。
// Managed Grafanaがデータ取得用APIにアクセスするためのInterface VPC Endpoint const executeApiVpcEndpoint = new ec2.InterfaceVpcEndpoint(this, 'ExecuteApiVpcEndpoint', { vpc, service: ec2.InterfaceVpcEndpointAwsService.APIGATEWAY, subnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, securityGroups: [vpceSecurityGroup], privateDnsEnabled: true, }); // VPC内のLambdaがDynamoDBにアクセスするためのGateway VPC Endpoint new ec2.GatewayVpcEndpoint(this, 'DynamoDbVpcEndpoint', { vpc, service: ec2.GatewayVpcEndpointAwsService.DYNAMODB, subnets: [{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }], });
privateDnsEnabled: true を設定することで、データ取得用APIのURL(execute-api.{region}.amazonaws.com)の DNS 名が
VPC 内で VPC Endpoint の IP アドレスに解決されます。
これにより、Managed Grafana がプライベートな URL で API Gateway にアクセスできます。
DynamoDbApiDatasourceStack — Lambda関数とIAMポリシー
Lambda はプライベートサブネットに配置します。
IAM ポリシーは dynamodb:PartiQLSelect のみを付与し、必要最小限の権限に絞っています。
lambdaRole.addToPolicy(new iam.PolicyStatement({ actions: ['dynamodb:PartiQLSelect'], resources: [dynamoTableArn], })); const metricsApiFunction = new lambda.Function(this, 'MetricsApiFunction', { runtime: lambda.Runtime.PYTHON_3_14, handler: 'index.handler', code: lambda.Code.fromAsset(path.join(__dirname, '../../lambda/metrics-api')), vpc, vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, environment: { TABLE_NAME: dynamoTableName }, timeout: cdk.Duration.seconds(30), });
DynamoDbApiDatasourceStack — Private API Gateway
Private API Gateway は、特定の VPC Endpoint からのみ API を呼び出せるようにします。
EndpointType.PRIVATE を指定し、リソースポリシーで aws:sourceVpce 条件を設定します。
const api = new apigateway.RestApi(this, 'MetricsApi', { endpointConfiguration: { types: [apigateway.EndpointType.PRIVATE], vpcEndpoints: [executeApiVpcEndpoint], }, policy: new iam.PolicyDocument({ statements: [new iam.PolicyStatement({ principals: [new iam.AnyPrincipal()], actions: ['execute-api:Invoke'], resources: ['execute-api:/*'], conditions: { StringEquals: { 'aws:sourceVpce': executeApiVpcEndpoint.vpcEndpointId }, }, })], }), });
Lambda関数の実装(Python)
Lambda は Python 3.14 で実装しています。
実際に Managed Grafana で可視化する場合は、時間範囲を指定するのでこれを意識した GET パラメータを受け取れるようにします。
Infinity Plugin は URL Parameters に設定した値を GET クエリパラメータとして API に送信します。
Lambda はそれを event["queryStringParameters"] で受け取ります。
def handler(event, context): params = event.get("queryStringParameters") or {} metric_name = params.get("metric_name", "").strip() # Infinity の URL Parameters から届く start = params.get("start") # ${__from:date:iso} が ISO 8601 文字列に変換されて届く end = params.get("end") # ${__to:date:iso} が ISO 8601 文字列に変換されて届く result = query_dynamodb(metric_name, start, end) formatted = format_for_infinity(result) return response(200, formatted)
受け取った start/end を DynamoDB の PartiQL クエリの時間範囲フィルタに使います。
def build_partiql_query(metric_name, start=None, end=None): query = ( f'SELECT metric_name, "timestamp", "value", unit ' f'FROM "{TABLE_NAME}" ' f"WHERE metric_name = '{metric_name}'" ) if start and end: query += f" AND \"timestamp\" BETWEEN '{start}' AND '{end}'" return query
レスポンスは Infinity Plugin が扱いやすいフラットな JSON 配列で返します。
[ { "timestamp": "2025-01-01T00:00:00Z", "value": 45.2, "metric_name": "cpu_usage", "unit": "percent" }, { "timestamp": "2025-01-01T00:05:00Z", "value": 52.8, "metric_name": "cpu_usage", "unit": "percent" } ]
CDKデプロイ
cd cdk npm ci npx cdk deploy --all --require-approval never
デプロイ後、後続の手順で必要な設定値を AWS マネジメントコンソールで確認しておきます。
VPC の ID、サブネットの ID、API の VPC Endpoint の ID
いずれも VPC の画面で確認できます。
VPC の ID、サブネットの ID の確認方法はメジャーなので割愛します。
VPC Endpoint は、VPC の画面の左ナビゲーションペインから「エンドポイント」で確認できます。
今回の構成の場合、API 用に Interface VPC Endpointができているはずなので、その ID を控えます。

Managed GrafanaのワークスペースID
ワークスペース ID は Grafana のワークスペース画面の URL の末尾です。
https://<リージョン>.console.aws.amazon.com/grafana/home?region=<リージョン>#/workspaces/<ワークスペースID>
プライベート API のエンドポイントURL
API Gateway の画面で API > ステージから「URL を呼び出す」でエンドポイント URL が取得できます。

なお、プライベート API であるかどうかは、API の設定の「API エンドポイントタイプ」で確認できます。

ただし、この画面に表示される URL はそのままでは VPC Endpoint 経由でアクセスできません。
Managed Grafana から VPC Endpoint 経由で Private API Gateway を呼び出すには、前の手順で確認した VPC Endpoint ID を使って以下の形式に書き換える必要があります。
https://{APIのID}-{VPC Endpoint ID}.execute-api.{region}.amazonaws.com/{stage}/{resource}
たとえば、API Gateway の画面で表示される URL が以下だとします。
https://abc1234def.execute-api.ap-northeast-1.amazonaws.com/dev/
VPC Endpoint ID が vpce-0123456789abcdef0 であれば、実際に Infinity Plugin に設定する URL は以下のようになります。
https://abc1234def-vpce-0123456789abcdef0.execute-api.ap-northeast-1.amazonaws.com/dev/metrics
{APIのID} と {VPC Endpoint ID} をハイフンで結合する点に注意してください。
Managed GrafanaをVPCに接続する
上述の CDK デプロイ後、AWS CLI で Managed Grafana に VPC 接続を設定します。
VPC には Managed Grafana 用のセキュリティグループを作っておきます。
Managed Grafana 用のセキュリティグループに追加する設定は以下のとおりです。
| 方向 | プロトコル | ポート | 送信先/送信元 | 用途 |
|---|---|---|---|---|
| アウトバウンド | TCP | 443 | API 用の VPC Endpoint に付けるセキュリティグループ(grafana-db-conn-dev-sg-vpce-execute-api) |
Private API Gateway への HTTPS 通信 |
続けて、API 用の VPC Endpoint に付けるセキュリティグループ(grafana-db-conn-dev-sg-vpce-execute-api)に追加するルールは以下のとおりです。
| 方向 | プロトコル | ポート | 送信先/送信元 | 用途 |
|---|---|---|---|---|
| インバウンド | TCP | 443 | Managed Grafana 用のセキュリティグループ(grafana-db-conn-dev-sg-grafana-vpc) |
Managed Grafana からの HTTPS 受信 |
# マネジメントコンソールで確認した値を設定
WORKSPACE_ID="g-xxxxxxxxxx"
VPC_ID="vpc-xxxxxxxxxx"
SUBNET_ID_1="subnet-xxxxxxxxxx" # Private サブネット 1 の ID
SUBNET_ID_2="subnet-xxxxxxxxxx" # Private サブネット 2 の ID
# Grafana VPC 用セキュリティグループを作成
GRAFANA_SG_ID=$(aws ec2 create-security-group \
--group-name "grafana-db-conn-dev-sg-grafana-vpc" \
--description "Security group for Managed Grafana VPC ENI" \
--vpc-id "$VPC_ID" \
--query "GroupId" --output text)
# VPCE セキュリティグループ ID を取得
VPCE_SG_ID=$(aws ec2 describe-security-groups \
--filters "Name=group-name,Values=grafana-db-conn-dev-sg-vpce-execute-api" \
--query "SecurityGroups[0].GroupId" --output text)
# Grafana SG から VPCE SG へのアウトバウンド(HTTPS)を許可
aws ec2 authorize-security-group-egress \
--group-id "$GRAFANA_SG_ID" \
--protocol tcp --port 443 \
--source-group "$VPCE_SG_ID"
# VPCE SG に Grafana SG からのインバウンド(HTTPS)を許可
aws ec2 authorize-security-group-ingress \
--group-id "$VPCE_SG_ID" \
--protocol tcp --port 443 \
--source-group "$GRAFANA_SG_ID"
# Managed Grafana に VPC 接続を設定
aws grafana update-workspace \
--workspace-id "$WORKSPACE_ID" \
--vpc-configuration "{
\"securityGroupIds\": [\"$GRAFANA_SG_ID\"],
\"subnetIds\": [\"$SUBNET_ID_1\", \"$SUBNET_ID_2\"]
}"
VPC 接続の設定後、Managed Grafana のステータスが ACTIVE に戻るまで数分かかります。
Infinity Pluginのインストール
Managed Grafana のプラグイン管理画面から Infinity Plugin をインストールします。
- 左メニュー > 「Administration」 > 「Plugins and data」 > 「Plugins」
- 検索ボックスに
Infinityと入力(ヒットしない場合は、State を All にしてみてください) - 「Infinity」プラグインを選択してインストール


インストール後、データソースの設定画面に Infinity が表示されます。
ダッシュボードへの設定方法
データソースの追加
- 左メニュー > 「Connections」 > 「Data sources」 > 「Add data source」
- 検索ボックスに
Infinityと入力して選択 - 「Name」を入力して「Save & test」をクリック



クエリの設定
Explore 画面またはダッシュボードパネルの編集画面で以下を設定します。
| 項目 | 値 |
|---|---|
| Type | JSON |
| Source | URL |
| Method | GET |
| Parser | Backend |
| URL | 事前に控えておいた、プライベートAPIのエンドポイントURL |
今回のプライベート API は、GET パラメータを受け取るようにしているので、「URL Parameters」セクションで以下を追加します。
ここに設定したキーと値は、Infinity Plugin が GET クエリパラメータとして API に付与して送信します。
Lambda はこれを event["queryStringParameters"] で受け取り、DynamoDB の時間範囲フィルタに使用します。
| Key | Value | 説明 |
|---|---|---|
metric_name |
cpu_usage |
クエリ対象のメトリクス名 |
start |
${__from:date:iso} |
タイムピッカーの開始時刻(ISO 8601 形式で自動付与) |
end |
${__to:date:iso} |
タイムピッカーの終了時刻(ISO 8601 形式で自動付与) |
${__from:date:iso} と ${__to:date:iso} は Grafana の組み込み変数で、タイムピッカーで選択した時間範囲が
ISO 8601 形式(例: 2025-01-01T00:00:00Z)に変換され、GET パラメータとして Lambda に届きます。
これにより、ダッシュボードの時間範囲操作がそのまま DynamoDB のクエリ範囲に連動します。

カラムマッピングの設定
今回のプライベート API は、以下の書式の JSON を返します。
これをカラムマッピングで Grafana に合わせます。
[ { "timestamp": "2025-01-01T00:00:00Z", "value": 45.2, "metric_name": "cpu_usage", "unit": "percent" }, { "timestamp": "2025-01-01T00:05:00Z", "value": 52.8, "metric_name": "cpu_usage", "unit": "percent" } ]
「Columns」セクションで、API レスポンスのフィールドを Grafana のカラムにマッピングします。
| Selector | Type | As |
|---|---|---|
timestamp |
Timestamp |
Time |
value |
Number |
Value |
metric_name |
String |
Metric |
unit |
String |
Unit |

あとは「Save」「Apply」をクリックします。
「Time series」を選択すると、時系列グラフが表示されるはずです。
最後に
本記事では、Infinity Plugin と Private API Gateway を組み合わせることで、Amazon Managed Grafana から DynamoDB のデータを可視化する構成を紹介しました。
今回の構成と、DynamoDB プラグインを使う構成のどちらを選ぶかはコストと手間のバランスによりますが、本記事の内容が皆様の開発においてお役に立てば幸いです。
参考リンク
- Infinity data source plugin for Grafana | Grafana Plugins documentation
- API Gateway のプライベート REST API - Amazon API Gateway
- Amazon Managed Grafana から Amazon VPC のデータソースまたは通知チャネルに接続する - Amazon Managed Grafana
兼安 聡(執筆記事の一覧)
アプリケーションサービス本部 DS3課
2026 Japan AWS Ambassadors
2024-2026 Japan AWS Top Engineers
2024-2026 Japan AWS All Certifications Engineers
2025-2026 AWS Community Builders
Certified ScrumMaster
PMP
広島在住です。今日も明日も修行中です。
X(旧Twitter)