Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AWS PrivateLink × SCIM で実現する セキュアで運⽤負荷の低い Datab...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

AWS PrivateLink × SCIM で実現する セキュアで運⽤負荷の低い Databricks 基盤の構築

CA DATA NIGHT#10 〜データ基盤の「正解」は、Databricksにあります〜
https://cyberagent.connpass.com/event/393631/

上記イベントで発表した資料です。

Avatar for tsudash0

tsudash0

June 26, 2026

More Decks by tsudash0

Other Decks in Technology

Transcript

  1. 自己紹介 @tsudash0 所属: サイバーエージェント > メディア統括本部 > Data Science Center

    (DSC ) 役割: データエンジニア, インフラエンジニア 経歴: 2012 年からデータ領域のソフトウェアエンジニアとして働き始める サイバーエージェント歴 2015 年〜2022 年 正社員(全社のデータ基盤運用、データマネジメント業務) 2025 年〜 業務委託(某プロジェクトのデータエンジニア) インフラも含めたデータ基盤の設計・構築・運用 AWS / Databricks / Snowflake / Google Cloud / Terraform どういう人か: データ基盤を長期的に機能させるための原理・設計・組織を考えるエンジニア by Claude データ基盤のシステムアーキテクチャ設計、データアーキテクチャ設計 DMBOK データマネジメントによる成熟度の評価から施策立案 2
  2. もくじ 1. プロジェクト全体像 2. 運用面での対策 1. メダリオンアーキテクチャで職責を分離 2. Databricks Asset

    Bundle によるジョブ管理 3. セキュア面での対策 1. Private Link の構成 2. SCIM による IdP 統合 4. 得られた学び 5. まとめ 3
  3. データ基盤への要件 データエンジニアの工数が少ないため、データサイエンティストやBI エンジニアでもデータ加工が必要: メダリオンアーキテクチャによる職責分離 Databricks のマネージドサービスを利用。Notebook ベースでのデータ加工を中心としたETL プロセスを導入 データは一部機密性のあるもの(PII 、PHI

    等)が含まれ、セキュリティの優先度が高い SCIM による権限の一元管理 PrivateLink 利用によるネットワークセキュリティの確保 Databricks を選んだ理由 2025 年内に Snowflake, Databricks 双方で PoC を行いました。CA グループではどちらも利用実績がありますが、今回 のプロジェクトでは Databricks を採用しました。 理由としては: データエンジニアのリソースが少なく、データサイエンティストやBI エンジニアだけでもデータ管理できるプラット フォームがよかった Databricks の Notebook を中心としたデータ加工方法がデータサイエンティストと相性がよかった メダリオンアーキテクチャーを導入しやすく、エンジニア・アナリストでの職責分離がしやすかった 6
  4. 対策1: メダリオンアーキテクチャで職責を分離 データ基盤のシステムアーキテクチャーにはさまざまな選択肢がありますが、このプロジェクトでは Databricks のマネ ージドサービスを中心に据えたシンプルな構成にしています。 特にデータ加工においてデファクトスタンダードである dbt も採用を見送りしています: 連携データソースが多く、データエンジニアの稼働時間がほとんどがデータ抽出に取られてしまう

    プロジェクト内のアナリストで dbt 運用経験があるメンバーがいない (私も Databricks に向けた dbt の最適なオプションなど把握していなかった) リアルタイム集計の需要が一部あり、dbt だけでは対応できないケースが見えていた これらの理由から、以下のように職責を分離。アナリストが自走できるような環境としました: データエンジニア:データソースからデータを集め、差分連携や重複排除などの処理までを行う アナリスト:準備されたデータを、ダッシュボード用に結合・加工する ※アナリスト側でもDatabricks を利用した様々な最適化をしてデータ加工していますが、今回は割愛 10
  5. 職責分離の全体像 ポイント: Silver 層を2 つに分離 レイヤー 担当 役割 Silver (

    データソース) データエンジニア 重複排除・型変換などデータ品質担保 Silver ( ドメイン) DS / BI エンジニア ビジネスロジックに基づく自由な加工 → 境界が明確になり、お互いの作業が干渉しない 11
  6. 対策2: Databricks Asset Bundle (DAB) によるジョブ管理 Databricks Asset Bundle (DAB)

    は、Databricks のジョブ、パイプライン、ノートブックなどのリソースを YAML ベー スで宣言的に管理し、デプロイを自動化するための公式ツールです(公式ドキュメント) IaC (Infrastructure as Code ): ジョブ定義を Git で管理可能 環境分離: targets で dev / prod などを切り替え CI/CD 対応: CLI でデプロイを自動化(対応予定) 変数サポート: 環境ごとにパラメータを差し替え 12
  7. DAB 導入の目的 このプロジェクトでは、データエンジニアが担当する領域と、一部のデータサイエンティストの作業領域で DAB を導入 しています。 課題 DAB による解決 ジョブ定義が

    UI に散らばり、差分管理が困難 YAML で Git 管理、PR レビュー可能 dev/prod で設定を手動で変更 targets で環境を宣言、切り替えコマンド1 つ デプロイ手順が属人化 databricks bundle deploy で誰でも同じ結果 ジョブ変更の履歴が追えない Git のコミット履歴で追跡可能 本プロジェクトでの活用 Ingestion ジョブ: 各種データソースのデータ取り込みを DAB で管理 スケジュール実行: cron で定期実行を定義 GitHub Actions 連携: PR マージ時に本番へ自動デプロイ( 対応中) 13
  8. 管理しているバンドル構成 databricks-asset-bundle/ ├── bundles/ │ ├── ingestion-datasource1/ # データソース1 の

    S3 -> Bronze -> Silver までの加工処理を定義 │ ├── ingestion-datasource2/ # データソース2 の S3 -> Bronze -> Silver までの加工処理を定義 │ │ └── src/ # ノートブックや Python スクリプト │ │ ├── databricks.yml # バンドル定義 │ │ ├── resources/ # ジョブ定義 │ └── ingestion-master/ # マスターデータの Delta Live Table 定義 └── README.md 14
  9. サンプル: databricks.yml (バンドル定義) バンドル全体の メタデータと共通設定を定義するファイルです: bundle: name: myproject-ingestion variables: env:

    default: dev catalog: default: myproject include: - resources/*.yml targets: dev: mode: development default: true prod: mode: production variables: env: prod catalog: myproject permissions: - group_name: myproject-databricks-admin level: CAN_MANAGE 15
  10. サンプル: ジョブ定義(resources/*.yml ) 各 Databricks リソース(Jobs, Pipelines 等)を定義するファイルです: resources: jobs:

    ingestion_datasource1_activities: name: "[${bundle.target}] Ingestion Datasource1" description: "Load Datasource1 data from S3 (hourly)" schedule: quartz_cron_expression: "0 35 * * * ?" timezone_id: Asia/Tokyo tags: domain: ingestion source: datasource1 layer: bronze tasks: - task_key: load_datasource1_activities notebook_task: notebook_path: ../src/load_datasource1_activities.ipynb base_parameters: env: ${var.env} catalog: ${var.catalog} - task_key: transform_silver_activities depends_on: - task_key: load_datasource1_activities notebook_task: notebook_path: ../src/transform_silver_activities.ipynb 16
  11. DAB コマンド一覧 # バンドルの検証(YAML 構文チェック) databricks bundle validate # dev

    環境へデプロイ databricks bundle deploy -t dev # prod 環境へデプロイ databricks bundle deploy -t prod # ジョブを即時実行 databricks bundle run -t dev ingestion_datasource1_activities # デプロイ状態の確認 databricks bundle summary -t prod # リソースの削除(クリーンアップ) databricks bundle destroy -t dev 17
  12. なぜ PrivateLink が必要か Databricks on AWS は、Compute Plane (データ処理を行うクラスター)が Control

    Plane (UI やAPI )と通信する 際、デフォルトではパブリックネットワークを経由します。セキュリティ要件の高い環境では、この通信をプライベー トネットワーク内に閉じ込める必要があります。 Private Link 構成 19
  13. PrivateLink の種類と採用方針 Databricks では 3 種類の PrivateLink が提供されています(公式ドキュメントより) : 種類

    保護する通信 本環境 インバウンド(フロントエンド) ユーザー → Workspace UI/API 対応検討中 アウトバウンド(サーバーレス) サーバーレスコンピュート → 顧客リソース(S3 等) (Databricks 側で対応※) クラシック(バックエンド) クラシックコンピュート → Control Plane 対応済 ※ サーバーレスは、Databricks 側の環境に S3 Gateway Endpoint が置かれており、同一リージョンであれば閉域網で 通信される 本環境の方針: クラシック(バックエンド) を優先的に実装 構成手順: PrivateLink 構成手順(公式) Terraform サンプル: GitHub 今後の対応予定: インバウンド(フロントエンド): SSO + MFA で保護中だが、より厳格なセキュリティ要件対応時に検討 20
  14. VPC エンドポイント構成(クラシック向け) クラシック PrivateLink 用に、3 種類の VPC エンドポイントを構成しています: エンドポイント 種別

    目的 Backend REST Interface Workspace UI & REST API Backend Relay Interface Secure Cluster Connectivity S3 Gateway プライベート S3 アクセス(クラシック Cluster 用) ネットワーク構成 VPC を以下のサブネットに分割し、PrivateLink 専用のサブネットを設けています: サブネット CIDR 用途 Private Subnet 10.10.1.0/24, 10.10.2.0/24 Databricks コンピュート PrivateLink Subnet 10.10.3.0/24, 10.10.4.0/24 VPC エンドポイント配置 Public Subnet 10.10.101.0/24, 10.10.102.0/24 NAT Gateway 21
  15. 通信経路のセキュリティ 経路 保護方式 説明 クラシック Cluster → Control Plane PrivateLink

    REST API / SCC 通信は VPC 内で完結 クラシック Cluster → S3 Gateway Endpoint AWS バックボーン経由、NAT 不要 サーバーレス→Unity Catalog (Databricks 管理 S3) Databricks 内部 Silver/Gold 層は安全 サーバーレス→顧客管理 S3 (Bronze 層) Databricks で対応済 同一リージョンならS3 へのアクセスは安 全 ユーザー → Workspace パブリック SSO + MFA で保護 ストレージ構成: Bronze 層: 顧客管理 S3 → サーバーレスからのアクセスは今後対応 Silver / Gold 層: Databricks 管理 S3 ( Unity Catalog ) → サーバーレスでも安全 Terraform による IaC 管理 これらの設定はすべて Terraform で管理しており、以下の資料を参考に実装: 構成手順: PrivateLink 構成手順(公式) Terraform サンプル: GitHub 22
  16. なぜ SCIM 連携が必要か CA グループでは PERMAN という認証認可基盤を独自で構築・運用しています。Databricks や QuickSight へのユーザ

    ー連携を PERMAN 経由にすることで以下の利点が得られます: ユーザー管理の一元化: 入退社やロール変更を PERMAN 側で行えば、各サービスに自動反映 アクセス権限の可視化: 誰がどのデータ・ダッシュボードにアクセスできるか PERMAN で確認可能 監査対応: PERMAN の履歴で権限変更を追跡できる 24
  17. Databricks との統合 現時点では Databricks はユーザーが直接使っていませんが、Genie などのインタラクティブにデータ活用できる仕組み にも興味をもっており、中長期的には Databricks を直接利用する可能性があります。 そのため、PERMAN

    を用いてユーザー管理を一元化したいのですが、PERMAN は Databricks との SCIM 連携に対応し ていませんでした。 しかし Databricks API を利用した実装は難しくありませんでした。どのように実装したのかを簡単にご紹介します。 使用技術 カテゴリ 技術 用途 言語 Go 社内の類似 Lambda を流用(Python でも可) Databricks API SCIM 2.0 REST API ユーザー・グループ同期 HTTP クライアント net/http (Go 標準) SDK 不要、自前実装 PERMAN API GraphQL ロール・ユーザー取得 シークレット管理 AWS Secrets Manager トークン保管 25
  18. SCIM 関連の Databricks API はシンプル メソッド エンドポイント 用途 GET /scim/v2/Users

    ユーザー一覧取得 POST /scim/v2/Users ユーザー作成 GET /scim/v2/Groups グループ一覧取得 POST /scim/v2/Groups グループ作成 PATCH /scim/v2/Groups/{id} グループ更新(メンバー追加・削除) 公式ドキュメント: https://docs.databricks.com/api/account/accountscim ポイント 公式 SDK 不要: SCIM は標準仕様なので net/http だけで実装可能 エンドポイントは5 つだけ: Users GET/POST, Groups GET/POST/PATCH 実装期間: 約1 週間(テスト含む) 26
  19. 27

  20. 実装例 // Databricks クライアント(SDK不要、標準HTTPで十分) type DatabricksClient struct { httpClient *http.Client

    token string accountURL string // https://accounts.cloud.databricks.com } // ユーザー作成(POST /scim/v2/Users) func (c *DatabricksClient) CreateUser(user *DatabricksUser) error { body, _ := json.Marshal(user) req, _ := http.NewRequest("POST", c.accountURL+"/scim/v2/Users", bytes.NewReader(body)) req.Header.Set("Authorization", "Bearer "+c.token) req.Header.Set("Content-Type", "application/scim+json") return c.httpClient.Do(req) } // グループへメンバー追加(PATCH /scim/v2/Groups/{id}) func (c *DatabricksClient) AddMemberToGroup(groupID, userID string) error { patch := map[string]interface{}{ "schemas": []string{"urn:ietf:params:scim:api:messages:2.0:PatchOp"}, "Operations": []map[string]interface{}{{ "op": "add", "path": "members", "value": []map[string]string{{"value": userID}}, }}, } body, _ := json.Marshal(patch) req, _ := http.NewRequest("PATCH", c.accountURL+"/scim/v2/Groups/"+groupID, bytes.NewReader(body)) // ... } 28
  21. QuickSight 権限の特殊な挙動 AWS Console へのログインイベントは、東京リージョン(ap-northeast-1 )ではなく us-east-1 の CloudTrail に

    のみ記録されます。Lambda は ap-northeast-1 で動かしたいため、クロスリージョンのイベント転送が必要でし た。 初回連携時: IAM Policy の quicksight:CreateReader 等を参照して QuickSight 権限が決まる 連携後: IAM Policy と QuickSight 権限は 連動しない IAM Policy を変更してもユーザーの QuickSight 権限は変わらない QuickSight 側で権限を昇格することは可能(ただし降格は不可) このため、運用としては: デフォルト: 全員「Reader 」で作成 必要に応じて: 管理画面から手動で「Author 」へ昇格 30
  22. 最後に感想として、得られた学びを共有いたします。 プロジェクトやチーム体制によって適切なツールは異なる 今回のプロジェクトでは Databricks のマネージドな機能を利用し、技術スタックを積まない方向性にしています。 例えばデータ加工処理に dbt を採用せず、Notebook や Python

    スクリプトによるデータ抽出・変換を行なっています。 ブロンズ・シルバー層まではデータエンジニアがプログラムとデータの品質を保つ必要はありますが、Notebook 形式に よってゴールド層はデータサイエンティストやBI エンジニアがフットワーク軽くデータを構築できる体制にできまし た。 また、そのおかげで各担当者が自分の領域にオーナーシップをもてており、より良いデータ加工の方法はないか Databricks の機能を色々と試したりしています。例えば LakeFlow Spark 宣言型パイプライン (SDP) を使って、シルバー 層以降のデータ加工をストリーミング変換にする領域もあります。 このように Databricks のネイティブ機能を利用しやすい環境にすることで、Databricks の新機能も取り入れやすくな ります。 32
  23. Genie が優秀 散々語られていると思いますが、1 つ事例を紹介させてください。 今回 DAB を紹介しましたが、実は旧開発環境から本番環境にジョブを移植する必要があり、その際に DAB を導入しま した。

    DAB の実装は次の通りです: 開発環境に、DAB の github リポジトリを連携 Genie に DAB 化したいジョブを共有 Genie が対象ジョブの Notebook, ジョブ設定(YAML), DAB 用の設定ファイルを構築し、リポジトリに追加 本番環境へ bundle deploy 環境間のジョブ移設は手間なことが多いですが、Genie + DAB であっという間に作業が済んでしまい感動しました。 34