DataZone本番3ヶ月|メタデータ管理の地獄をどう乗り越えたか
AWSのDataZoneを3ヶ月運用して気づいた現実。導入は簡単だけど、メタデータ管理の運用設計で失敗したこと、工夫した対策をそのまま書きました。
DataZone導入の背景——データ迷子と決別したい
先日、うちのチームでDataZoneを本番環境に投入してから3ヶ月が経った。正直、最初の1ヶ月は地獄だった。なぜなら、誰も「メタデータ管理」が何なのか、現場レベルで理解していなかったから。
うちのデータエンジニアチームは去年の夏くらいから、ある悩みに直面していた。S3に山積みされたデータセットが増えるたびに「あのデータって何?どこから来たの?」という質問が絶えない。ExcelやConfluenceにドキュメントを書いても、気づくと3世代前の情報になってる。データソースが10を超えたあたりから、もう管理しきれなくなってた。
「これはカタログツール導入が必須だな」って判断したのは去年の11月。選択肢はCollibra、Alation、Atlasと、あとはAWSネイティブなDataZone。CloudFormationでインフラ即座に作れるし、既存のGlueジョブやAthenaと連携できるDataZoneを選んだ。当時は「これなら数週間で導入できるだろう」なんて甘く見てた。
最初の試行錯誤——「メタデータを入れてください」の地獄
DataZoneの基本設定は実は簡単だ。AWSコンソールで数クリック、IAM設定を済ませたら動く。ただし、ここからが本番なんだ。
# DataZone最初の構成(シンプル過ぎた)
Project: Analytics
AssetTypes:
- S3
- Athena
Users: 5名
MetadataFields:
- name
- description
これだけじゃ何も始まらない。データセット1つを登録しようとしたら、「このデータの所有者は?更新頻度は?データ品質スコアは?」って項目がポップアップする。最初は「まあ、入力すればいいか」って感じで進めた。
そしたら3週目に、データエンジニアから悲鳴が上がった。「毎回これ入力するんですか?」と。実は、S3のメタデータ自動検出機能があっても、ビジネス層のメタデータ(「これ何に使うデータなの?」という文脈)は手動入力が必須なんだ。
うちの場合、Glueカタログと連携させようとしたら、スキーマはGlueから自動取得できるけど、そこからはお手上げ。「え、Glueのテーブル説明文をDataZoneに同期させることできるの?」って思ったけど、できない。手作業だ。
AWS構成図でDataZoneを見える化する
graph TB
subgraph VPC["VPC"]
AppLayer["Application Layer"]
DataZone["AWS DataZone"]
end
subgraph DataLake["Data Lake Architecture"]
S3Raw["S3 Raw Zone"]
S3Processed["S3 Processed Zone"]
GlueDB[("AWS Glue Catalog")]
end
subgraph Analytics["Analytics & Governance"]
Athena["Amazon Athena"]
DataZoneCatalog["DataZone Catalog"]
MetadataStore[("Metadata Store")]
end
subgraph Users["Users & Access"]
DataOwner["Data Owner"]
DataConsumer["Data Consumer"]
Analyst["Analyst"]
end
DataZone <-->|「メタデータ連携失敗」| GlueDB
GlueDB -->|テーブル定義| S3Raw
GlueDB -->|テーブル定義| S3Processed
S3Raw -->|ETL| S3Processed
S3Processed -->|Query| Athena
Athena <-->|メタデータ参照| DataZoneCatalog
DataZoneCatalog -->|同期| MetadataStore
MetadataStore -->|情報提供| Users
DataOwner -->|メタデータ管理| DataZoneCatalog
DataConsumer -->|検索・利用申請| DataZoneCatalog
Analyst -->|データ発見| DataZoneCatalog
style DataZone fill:#FF9900
style GlueDB fill:#FF9900
style DataZoneCatalog fill:#FF9900
style MetadataStore fill:#FF6666
この図を見てもらえば、DataZoneがGlueカタログの上に乗っかってる感じが伝わると思う。ただし「上に乗っかる」ってのは「統合される」じゃなく「並走する」の意味だ。互いに独立してるから、連携がスムーズじゃないんだよね。
メタデータ自動化への転換——LambdaとEventBridgeの組み合わせ
2ヶ月目に、自動化を本気で考えた。毎日新しいS3パスが追加されるたびに、誰かがDataZoneに手入力するなんて持たない。
実装したのがこれだ:
# Lambda関数:S3新規データセット発見時にDataZoneに自動登録
import boto3
import json
from datetime import datetime
datazone_client = boto3.client('datazone', region_name='ap-northeast-1')
s3_client = boto3.client('s3')
def lambda_handler(event, context):
"""
S3 PutObject → EventBridge → Lambda → DataZone Asset自動作成
"""
bucket = event['detail']['bucket']['name']
key = event['detail']['object']['key']
# S3メタデータから基本情報を取得
try:
obj = s3_client.head_object(Bucket=bucket, Key=key)
except Exception as e:
print(f"Error getting S3 object metadata: {e}")
return {"statusCode": 500, "body": str(e)}
# DataZoneアセット登録のペイロード
asset_payload = {
"domainIdentifier": "YOUR_DOMAIN_ID",
"name": key.split('/')[-1].replace('.parquet', '').replace('.csv', ''),
"typeIdentifier": "S3Location",
"owningProjectIdentifier": "YOUR_PROJECT_ID",
"description": f"Auto-discovered from s3://{bucket}/{key}",
"externalIdentifier": f"s3://{bucket}/{key}",
"metadata": {
"s3_bucket": bucket,
"s3_path": key,
"size_bytes": str(obj['ContentLength']),
"last_modified": obj['LastModified'].isoformat(),
"content_type": obj.get('ContentType', 'unknown')
}
}
try:
response = datazone_client.create_asset(
domainIdentifier=asset_payload['domainIdentifier'],
name=asset_payload['name'],
typeIdentifier=asset_payload['typeIdentifier'],
owningProjectIdentifier=asset_payload['owningProjectIdentifier'],
description=asset_payload['description'],
externalIdentifier=asset_payload['externalIdentifier'],
)
print(f"Successfully created asset: {response['id']}")
return {
"statusCode": 200,
"body": json.dumps({"assetId": response['id']})
}
except Exception as e:
print(f"Error creating DataZone asset: {e}")
return {"statusCode": 500, "body": str(e)}
このLambda、最初は自分で書いてテストしたんだけど、本番環境で走らせたら予想外の問題が出た。DataZoneのAPI呼び出しレート制限にすぐ引っかかるんだ。
1時間に100ファイル追加されるようなパイプラインだと、Lambda関数が100個同時起動して、DataZoneのAPI呼び出しが集中して、503エラーが返ってくる。これはEventBridgeでスロットリング設定を入れるしかない。
{
"Name": "DataZoneAutoDiscovery",
"EventBusName": "default",
"EventPattern": {
"source": ["aws.s3"],
"detail-type": ["Object Created"],
"detail": {
"bucket": {
"name": ["data-lake-bucket"]
},
"object": {
"key": [{
"prefix": "processed/"
}]
}
}
},
"State": "ENABLED",
"Targets": [
{
"Arn": "arn:aws:lambda:ap-northeast-1:ACCOUNT_ID:function:datazone-auto-register",
"RoleArn": "arn:aws:iam::ACCOUNT_ID:role/EventBridgeDataZoneRole",
"RetryPolicy": {
"MaximumEventAge": 3600,
"MaximumRetryAttempts": 2
},
"DeadLetterConfig": {
"Arn": "arn:aws:sqs:ap-northeast-1:ACCOUNT_ID:datazone-dlq"
}
}
]
}
重要なのはDeadLetterConfigだ。API呼び出しに失敗したイベントを死なせず、SQSキューに入れて、後から非同期で処理する。これでAPIレート制限の問題をうまく避けられた。地味だけど、本番環境では必須の設定だ。
メタデータの品質問題——「入ったら終わり」の罠
2ヶ月目から3ヶ月目にかけて気づいたのは、メタデータを登録することより、更新し続けることの方がずっと難しいってこと。
DataZoneに「データ品質スコア」みたいなフィールドを設定したんだけど、誰がそれを保守するのか。データエンジニアか?ビジネスオーナーか?ステークホルダーが増えると、その答えはもっと複雑になる。
うちの場合、Athenaでクエリを走らせたときのメタデータ(実行時間、データサイズ、クエリ複雑度)をDataZoneに自動同期させることにした。
# Athena実行完了後にDataZoneメタデータを更新する仕組み
import boto3
from datetime import datetime
athena_client = boto3.client('athena')
datazone_client = boto3.client('datazone')
def update_asset_metadata_from_athena(query_execution_id, asset_id):
"""
Athena実行結果からメタデータを抽出し、DataZoneのアセットを更新
"""
# Athena実行情報を取得
response = athena_client.get_query_execution(
QueryExecutionId=query_execution_id
)
stats = response['QueryExecution']['Statistics']
metadata_updates = {
"last_queried": datetime.now().isoformat(),
"execution_time_ms": stats['TotalExecutionTimeInMillis'],
"data_scanned_bytes": stats['DataScannedInBytes'],
"status": response['QueryExecution']['Status']['State']
}
# DataZone APIで動的にメタデータを更新
# ただし、DataZone APIにはメタデータ更新エンドポイントが限定的
# 公式ドキュメント:UpdateAsset APIは特定フィールドのみ対応
try:
datazone_client.update_asset(
domainIdentifier="YOUR_DOMAIN_ID",
identifier=asset_id,
description=f"Last queried: {metadata_updates['last_queried']} | "
f"Execution time: {metadata_updates['execution_time_ms']}ms | "
f"Data scanned: {metadata_updates['data_scanned_bytes']} bytes"
)
print(f"Updated asset {asset_id} with Athena metrics")
except Exception as e:
print(f"Failed to update metadata: {e}")
# 重要:失敗してもクエリ結果は保存しておく
# メタデータ更新失敗がデータ利用を妨げてはいけない
正直まだ検証中なんだけど、このやり方で**「メタデータが古い」という訴えは大幅に減った**。なぜなら、メタデータが常に「最後に使われたのはいつ」という情報を持つようになったから。これってビジネスユーザーにとって、スキーマ情報より大事な情報かもしれない。
DataZone vs 他のカタログツール——本音で比較
うちのチームは、DataZone導入前にCollibra と Alationのトライアルも触ってた。率直に言うと、こんな感じだ:
| 項目 | DataZone | Collibra | Alation |
|---|---|---|---|
| AWS統合 | ネイティブ | API連携 | API連携 |
| 学習コスト | 低い | 中程度 | 高い |
| カスタマイズ性 | 限定的 | 高い | 高い |
| 初期費用 | 数十万円 | 数百万円 | 数百万円 |
| メタデータ自動化 | 部分的 | 自動 | 自動 |
| 運用負荷 | 低い | 中程度 | 高い |
| ガバナンス機能 | 標準的 | 高度 | 高度 |
DataZoneを選んだ理由は、AWS環境ならサクッと動く、という「気軽さ」。ただし、本当にエンタープライズレベルのガバナンスが必要なら、Collibra や Alation の方が圧倒的に強い。機能としては向こうが数段上なんだよね。でも、コストと運用負荷を考えると、うちみたいな小〜中規模チームはDataZoneが無難かもしれない。
意外な落とし穴——ビジネスユーザーのメタデータ理解
3ヶ月目で気づいた一番大きな問題は、データオーナーとデータコンシューマーの「メタデータ」の定義がズレてたってこと。
エンジニアは「スキーマ、更新頻度、データ品質スコア」って考えるけど、マーケティング部門は「このデータで何ができるのか」を知りたい。営業は「信頼度は?」を気にする。ビジネスアナリストは「どの部門が持ってるデータなの?」を聞きたい。それぞれ違うメタデータを欲しがってるんだ。
これを解決するために、DataZoneの「カスタムメタデータフィールド」機能を使ってみた。各ユーザーグループに必要な情報を個別に設定できるようにしたんだ:
{
"CustomFields": [
{
"name": "business_use_case",
"type": "string",
"description": "このデータの主なビジネス用途",
"required": true,
"options": [
"顧客分析",
"売上予測",
"マーケティング自動化",
"リスク管理",
"その他"
]
},
{
"name": "data_quality_score",
"type": "numeric",
"description": "0-100スケールのデータ品質スコア",
"required": true,
"minValue": 0,
"maxValue": 100
},
{
"name": "refresh_lag_hours",
"type": "numeric",
"description": "ソースシステムからの更新遅延(時間単位)",
"required": false
},
{
"name": "pii_flag",
"type": "boolean",
"description": "個人識別情報を含むか",
"required": true
}
]
}
これを導入したら、ようやく「あ、このデータ信頼できるんだ」「このデータは顧客情報が入ってるから慎重に扱わないと」という判断がビジネスユーザー側でできるようになった。メタデータって、結局のところ「判断材料」なんだなって改めて感じたね。
3ヶ月運用して分かった実装のコツ
1. メタデータ入力は段階的に
最初から完璧なスキーマを作らない。まず「最小限」のメタデータ(名前、説明、所有者)を満たしたら、あとは使いながら追加していく。完璧さを求めると、チームのモチベーションが下がっちゃう。
2. 自動化は「失敗容認」で設計する
Lambdaが失敗してもメインのデータパイプラインが止まっちゃダメ。メタデータ更新はあくまで「補足情報」。DLQにためて、非同期で処理する。データの可用性を絶対に優先する。
3. ビジネス層とエンジニア層のメタデータを分ける
「テーブル定義」と「ビジネス文脈」は別物。前者はGlueから自動同期、後者は手動入力か、ビジネスユーザーが自分で入力する仕組みを作る。混ぜると誰のための情報かわからなくなる。
4. データカタログはGUIじゃなくAPIで検索
うちの場合、DataZoneのWebUIより、Pythonで検索クエリを書く方が圧倒的に速い。開発者はAPIの方が使いやすいんだ。
# DataZone検索API
import boto3
datazone_client = boto3.client('datazone')
# キーワードで資産を検索
response = datazone_client.search(
domainIdentifier='YOUR_DOMAIN_ID',
searchScope='ASSET',
searchText='customer', # 「customer」に関するアセット検索
filters=[
{
'name': 'typeName',
'values': ['S3Location'] # S3オブジェクトのみ
}
]
)
for result in response['results']:
print(f"Asset: {result['name']}, Owner: {result['owner']}")
まとめ
DataZoneは確かに便利なカタログツールなんだけど、「導入したら自動的にデータガバナンスが回る」わけじゃない。むしろ、メタデータをどう定義して、誰が保守するのか、という組織的な問題の方がずっと大きい。
3ヶ月運用してわかった重要なポイント:
- メタデータ自動化には上限がある — スキーマは自動取得できるが、ビジネス文脈は手動入力が必須
- API呼び出しレート制限は早めに対策する — EventBridgeのリトライとDLQ設定が大事
- カスタムメタデータフィールドでビジネスユーザーの要件を満たす — エンジニア視点だけじゃデータ探索は進まない
- 完璧さを目指さない — 「80%のメタデータで十分」くらいの気持ちで進めた方が、運用が続く
- ビジネス層のオーナーシップが必須 — データエンジニアだけで回そうとすると、確実に破綻する
うちはまだ5人のチームだからちょうどいいスケールだけど、これが50人、100人規模のデータ組織になったら、もっと高度なカタログツール(CollibラやAlation)の出番なんだろう。ただし、AWSだけで完結させたいなら、DataZoneは悪くない選択肢だ。正直、Alationの初期導入費用を聞いたときは目玉が飛び出たし。
まだ改善の余地があるし、メタデータの「信頼度」をどう担保するかはこれからのテーマだ。ただ、3ヶ月前の「データ迷子状態」に比べたら、格段に良くなったのは確か。最近では「あのデータ、DataZoneで見つけてくれ」って言う人も増えてきた。