0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWSとDatabricksでのデータ分析基盤を検討してみた

0
Last updated at Posted at 2025-09-30

生命保険業界で「データ移動なき」分析基盤を検討した話

生命保険業界のIT部門と関わっていると、データ活用の話で必ずぶつかる壁があります。
いわゆる「データのサイロ化」もありますが、それよりも厄介なのはセキュリティ要件と完全閉域網の制約です。

数千万人の契約者情報を預かっている以上、インターネットへの接続は原則禁止。にもかかわらず、ビジネスサイドからは「最新の生成AIを使いたい」「リアルタイムで契約状況を分析したい」とリクエストが飛んでくる。
セキュリティは死守しつつ、革新もしろと。

そんな状況で私たちが選んだのは、DatabricksとAmazon SageMakerを閉域網の中で組み合わせるという構成でした。
その構築で躓いたところや乗り越えたところを備忘録として残しておきます。

なぜハイブリッド構成を選んだのか

最初は迷いました。「Databricks一本で全部やればいい」という声もあれば、「AWSネイティブサービスだけで完結させよう」という意見もあったからです。
ただ、DatabricksのSparkエンジンによるデータ処理能力はやはり圧倒的で、データエンジニアにとっては最高の環境です。一方で、MLOpsやガバナンス、最終的なアプリケーションへの出口(推論APIなど)を考えると、AWSのエコシステム、特にSageMakerの堅牢さは捨てがたい。

そこで採用したのが、「ストレージはAWS(S3)に集約し、コンピュートは適材適所で使い分ける」 という構成です。

コンセプト自体はシンプルで、Databricksでデータを加工し、AWS Glue Catalogと同期をとる。そして実体データ(S3)をSageMakerから直接参照する。
ここで使うのが UniForm (Universal Format) です。Databricks独自のDelta形式ではなく、Iceberg形式のメタデータを自動生成させることで、SageMakerからも普通にデータを触れるようにします。

言葉にするとこれだけのことですが、金融グレードの閉域網で実現しようとすると色々と大変でした。

閉域網でのS3バケットポリシーとの格闘

最初の難関はネットワークです。AWS PrivateLink周りで結構ハマりました。
「S3にデータを置けば、同じアカウント内なんだから読めるでしょ?」というのはインターネットにつながっている環境の話で、閉域環境ではVPCエンドポイント(VPCE)を経由しないアクセスは一切通りません。

DatabricksのData Plane(EC2インスタンス群)とSageMaker Studio、この両方が同じS3バケットを見に行く必要があります。
セキュリティ審査を通すには「特定のVPCエンドポイント経由のアクセス以外はすべて拒否(Deny)」というガチガチのバケットポリシーを入れないといけないのですが、Databricksは独自のIAMロールで動くため、単にPrincipalを指定するだけでは弾かれてしまう。

何度も Access Denied を眺めて、たどり着いたのがこのCondition句でした。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAppAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::123456789012:role/service-role/AmazonSageMaker-ExecutionRole",
                    "arn:aws:iam::123456789012:role/databricks-access-role"
                ]
            },
            "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
            "Resource": ["arn:aws:s3:::enterprise-datalake-prod/*"],
            "Condition": {
                "StringEquals": {
                    "aws:SourceVpce": [
                        "vpce-0xxxxxxxxxxxxxx",  // Databricks Data Plane用
                        "vpce-0yyyyyyyyyyyyyy"   // SageMaker用
                    ]
                }
            }
        },
        {
            "Sid": "DenyNonVPC",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::enterprise-datalake-prod/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpce": [
                        "vpce-0xxxxxxxxxxxxxx",
                        "vpce-0yyyyyyyyyyyyyy"
                    ]
                },
                "Bool": {
                    "aws:ViaAWSService": "false" 
                }
            }
        }
    ]
}

このポリシーで一番ハマったのが aws:ViaAWSService の部分です。
構築当初はこの否定条件を入れていなかったのですが、ある日突然Amazon RDSからS3へのZero-ETL連携が完全に停止しました。
Zero-ETLのようなAWSマネージドサービス内部からのアクセスは、こちらが作ったVPCエンドポイントを経由しません。つまり DenyNonVPC ルールに引っかかってブロックされていたわけです。
「AWSサービス経由のアクセスは許可する」という一行を足すのに気づくまで丸一日溶かしました。。マニュアルの隅っこに書いてある仕様が現場では命取りになります。

UniFormの落とし穴

ネットワークの次はデータ形式の問題です。
Databricksで加工したデータを変換なしでSageMakerから学習データとして使える。UniForm機能は確かに便利でした。
実装自体はテーブル作成時にプロパティを足すだけです。

CREATE TABLE main.insurance.policy_risks (
  policy_id STRING,
  risk_score DOUBLE
)
TBLPROPERTIES (
  'delta.enableIcebergCompatV2' = 'true',
  'delta.universalFormat.enabledFormats' = 'iceberg'
);

ただ、UniFormはDelta Lakeへの書き込みが終わった後に「非同期」でIcebergのメタデータを生成します。この「非同期」が曲者でした。

Databricks側のETLジョブが終わった直後にSageMakerのパイプラインからデータを読みに行くと、「データが古い?」「更新されてない?」という事象が頻発したんです。
人間がコンソールで確認する分には数秒〜数十秒のラグなんて気になりませんが、システム間の連携では致命的なデータ不整合(Inconsistency)を生みます。

結局、AirflowのDAG(ワークフロー)を書き換えて、Databricksのジョブ完了後に OPTIMIZE table_name を実行するステップを追加し、強制的にメタデータをフラッシュさせる運用にしました。
スマートではないかもしれませんが、こういう泥臭いひと手間がシステムを安定させるんですよね。

IaCによるフィルタリング

基幹DB(Aurora)のデータを分析基盤に流す際も、ただ全量連携すればいいわけじゃありません。
生保には「絶対に分析担当者に見せてはいけないデータ」が存在します。センシティブな個人情報やクレジットカード情報などです。

Aurora Zero-ETL integrationは便利ですが、GUIでポチポチ設定して終わりにはしたくなかった。
そこでCloudFormationを使ってフィルタリング設定自体もコード化しました。

ZeroETLIntegration:
  Type: AWS::RDS::Integration
  Properties: 
    SourceArn: !Ref MyAuroraCluster
    TargetArn: !Ref DataLakeRedshiftOrIceberg
    # 2024年時点での機能拡張を想定したフィルタリング記述
    DataFilter: "include: *.policy_*, exclude: *.credit_card"

こうしておけば誰がいつどんなフィルタを設定したかGitに残るし、レビューもできる。
ガバナンスは口で言うよりコードで縛る方が確実です。

やってみてどうだったか

そんな苦労の末に本番稼働を迎えました。

これまで契約データの分析反映にはバッチ処理の関係で「T+1日」、つまり丸一日かかっていました。それがZero-ETLで平均15秒以内になりました。
アクチュアリーチームの担当者に「え、もう計算終わってるんですか?」と言われたときは、ああやって良かったなと。

4億レコードを超えるリスク計算処理もDatabricksのPhotonエンジンで60%ほど短縮。
なにより、SageMakerとDatabricksが同じS3(Iceberg)を見ているので「学習時と推論時でデータが違う」という不整合(Training-Serving Skew)が構造的に起きなくなりました。これが一番大きい。

まとめ

Databricks vs AWSという対立構造で語られることもありますが、現場の最適解はいつだって共存だと思います。
Databricksのデータ処理のパワーと、AWSの堅牢なガバナンス。この二つをIcebergという共通言語とIAMポリシーでつなぐ。
がんじがらめの制約の中で戦っているエンタープライズにとって、ひとつの参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?