Lakebase plugin
Lakebase plugin
Databricks Lakebase オートスケーリング 向けの PostgreSQL 接続プールを提供し、OAuth トークンを自動でリフレッシュします。
主な機能:
- あらゆる PostgreSQL ライブラリや ORM で利用できる標準の
pg.Pool - OAuth トークンの自動リフレッシュ(トークン有効期間 1 時間、リフレッシュバッファ 2 分)
- API 呼び出しを最小限に抑えるトークンキャッシュ
- OpenTelemetry 計装を標準搭載(クエリ実行時間、プール接続数、トークンのリフレッシュ)
- クエリおよび接続イベント向けに AppKit ロガーを既定で構成
Lakebase を使い始める
Lakebase plugin を使い始めるには、Databricks CLI で AppKit と Lakebase plugin をインストール済みの Databricks app を新規作成するのが最も簡単です。
前提条件
npmが使える Node.js v22 以上の環境- Databricks CLI (v1.0.0 以上) :公式チュートリアルに従ってインストールと設定を行ってください。
- AppKit をインストール済みの新しい Databricks アプリ。詳細は新しい Databricks アプリのブートストラップを参照してください。
Steps
- まず、Get started ドキュメントに従って、新しい Lakebase Postgres オートスケーリング project を作成します。
- Lakebase plugin をプロジェクトに追加するには、
databricks apps initコマンドを実行し、対話形式で Lakebase plugin を選択します。CLI の案内に従って、Lakebase の project、branch、データベースを選択してください。- 確認を求められたら Yes を選択し、作成直後にアプリを Databricks Apps へ deploy します。
基本的な使い方
import { createApp, lakebase, server } from "@databricks/appkit";
await createApp({
plugins: [server(), lakebase()],
});プールへのアクセス
初期化後は、AppKit.lakebase オブジェクト経由で Lakebase にアクセスします。
const AppKit = await createApp({
plugins: [server(), lakebase()],
});
await AppKit.lakebase.query(`CREATE SCHEMA IF NOT EXISTS app`);
await AppKit.lakebase.query(`CREATE TABLE IF NOT EXISTS app.orders (
id SERIAL PRIMARY KEY,
user_id VARCHAR(255) NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
const result = await AppKit.lakebase.query(
"SELECT * FROM app.orders WHERE user_id = $1",
[userId],
);
// 生の pg.Pool(ORM や高度な用途向け)
const pool = AppKit.lakebase.pool;
// ORM にそのまま渡せる設定オブジェクト
const ormConfig = AppKit.lakebase.getOrmConfig(); // { host, port, database, ... }
const pgConfig = AppKit.lakebase.getPgConfig(); // pg.PoolConfig設定
環境変数
必須の環境変数は次のとおりです。
| 変数 | 説明 |
|---|---|
LAKEBASE_ENDPOINT | endpoint リソースのパス (例: projects/.../branches/.../endpoints/...) |
PGHOST | Lakebase のホスト (本番環境では postgres Databricks Apps リソースが自動的に注入します) |
PGDATABASE | データベース名 (本番環境では postgres Databricks Apps リソースが自動的に注入します) |
PGSSLMODE | TLS モード。require を指定します (本番環境では postgres Databricks Apps リソースが自動的に注入します) |
postgres データベースリソースを構成した状態で Databricks Apps にデプロイすると、PGHOST、PGDATABASE、PGSSLMODE、PGUSER、PGPORT、PGAPPNAME はプラットフォームが自動的に注入します。明示的に設定する必要があるのは LAKEBASE_ENDPOINT のみです。
env:
- name: LAKEBASE_ENDPOINT
valueFrom: postgresローカル開発では、.env ファイルは databricks apps init によって、お使いの Lakebase project に対応した正しい値で自動生成されます。
設定の完全なリファレンス (SSL、プールサイズ、タイムアウト、ロギング、ORM の例) については、@databricks/lakebase README を参照してください。
プール設定
デフォルト値を上書きするには、pool オブジェクトを渡します。
await createApp({
plugins: [
lakebase({
pool: {
max: 10, // プールの最大接続数(デフォルト: 10)
connectionTimeoutMillis: 5000, // 接続タイムアウト(ミリ秒、デフォルト: 10000)
idleTimeoutMillis: 30000, // アイドル接続のタイムアウト(ミリ秒、デフォルト: 30000)
},
}),
],
});On-Behalf-Of (OBO) — ユーザーごとの接続
アプリで行レベルセキュリティ (RLS) やユーザー単位のデータ分離が必要な場合は、asUser(req) を使用して、ユーザーごとの Lakebase 接続プールでクエリを実行します。各ユーザーのプールはそのユーザーの Databricks ID で認証されるため、PostgreSQL の current_user には実際のユーザーが反映されます。
前提条件
Databricks App で
postgresスコープを指定して ユーザー認可を有効化 します。設定手順は User authorization を参照してください。databricks.ymlでは次のように記述します:resources: apps: app: user_api_scopes: - postgresdatabricks apps initと Lakebase plugin でスキャフォールディングしたアプリには、この設定が自動的に含まれます。アプリのユーザーごとに Lakebase 上の Postgres ロール が必要です。Databricks CLI で作成します:
databricks postgres create-role "projects/{project_id}/branches/{branch_id}" \ --json '{"spec": {"identity_type": "USER", "postgres_role": "user@example.com"}}'Lakebase UI の Branch Overview → Add role からロールを作成することもできます。
note OBO ユーザーに
databricks_superuserを付与しないでください。スーパーユーザーは RLS を回避してしまいます。代わりに fine-grained grants を使用してください。
使い方
設定は不要です。asUser(req) を呼び出すだけです。
const AppKit = await createApp({
plugins: [server(), lakebase()],
});
// サービスプリンシパルによるクエリ(デフォルト — テーブル所有者として RLS をバイパス)
const all = await AppKit.lakebase.query("SELECT * FROM app.orders");
// ユーザースコープのクエリ(ユーザーごとのプール、RLS が適用される)
app.get("/api/my-orders", async (req, res) => {
const result = await AppKit.lakebase
.asUser(req)
.query("SELECT * FROM app.orders ORDER BY created_at DESC");
res.json(result.rows);
});asUser(req) を呼び出すと、次の処理が行われます。
x-forwarded-access-tokenおよびx-forwarded-emailヘッダー (Databricks Apps が自動的に設定) から、ユーザーのトークンと ID が抽出されます。- ユーザーの OAuth 資格情報を使って、ユーザーごとの
pg.Poolが作成 (または再利用) されます。 query()とpoolはそのユーザーのプールを使用し、PostgreSQL のcurrent_userにはそのユーザーの ID が反映されます。
行レベルセキュリティ (RLS) の例
-- サービスプリンシパルとして実行(アプリのセットアップ時):
ALTER TABLE app.orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY user_orders ON app.orders
FOR ALL TO PUBLIC
USING (owner = current_user);
-- OBO ユーザーがクエリを実行できるようにアクセス権を付与
GRANT USAGE ON SCHEMA app TO PUBLIC;
GRANT SELECT, INSERT ON ALL TABLES IN SCHEMA app TO PUBLIC;仕組み
- サービスプリンシパルプール (
AppKit.lakebase.pool) は常に作成され、DDL 操作、シード処理、管理用クエリに使用されます。 - ユーザーごとのプールは最初の
asUser(req)呼び出し時に作成され、ユーザー ID ごとにキャッシュされます。各プールは独自の OAuth トークンのリフレッシュサイクルを持ちます。 - ユーザーごとのプール内のアイドル接続は自動的にクローズされます (アイドルタイムアウトは 30 秒) 。空になったプールオブジェクトは定期的にクリーンアップされます。
- シャットダウン時には、すべてのプール (SP + ユーザー) が正常にクローズされます。
- 開発モード (
NODE_ENV=development) では、ユーザートークンが利用できない場合、asUser(req)は警告を出力して SP プールにフォールバックします。
PostgreSQL のスーパーユーザーは行レベルセキュリティ (RLS) を完全にバイパスします。databricks_superuser ロールを持つユーザーは、RLS ポリシーに関係なくすべての行を参照できます。RLS を確実に適用するには、スーパーユーザーロールではなくfine-grained grantsを使用してください。
データベース権限
はじめにガイドに従って Lakebase リソースを持つアプリを作成すると、サービスプリンシパルに postgres リソースに対する CONNECT_AND_CREATE 権限が自動的に付与されます。これにより、サービスプリンシパルはデータベースに接続して新しいオブジェクトを作成できますが、既存のスキーマやテーブルにはアクセスできません。
ローカル開発
deploy済みの Lakebase データベースに対してローカルで開発する手順は次のとおりです。
まずアプリをdeployします。 初回deploy時に、サービスプリンシパルがデータベーススキーマとテーブルを作成します。
databricks apps initで生成したアプリはこの処理を自動で行います。起動時にテーブルの有無を確認し、すでに存在する場合は作成をスキップします。databricks_superuserを付与します (Lakebase project のオーナーであればスキップしてください。すでにフルアクセス権があります) :# databricks_superuser を持つ新しいロールを作成する databricks postgres create-role "projects/{project_id}/branches/{branch_id}" \ --json '{"spec": {"identity_type": "USER", "postgres_role": "user@example.com", "membership_roles": ["DATABRICKS_SUPERUSER"]}}'既存のロールに スーパーユーザー を付与するには、
update-roleを使用します:databricks postgres update-role \ "projects/{project_id}/branches/{branch_id}/roles/{role_id}" \ "spec.membership_roles" \ --json '{"spec": {"membership_roles": ["DATABRICKS_SUPERUSER"]}}'また、Lakebase オートスケーリング UI で project の Branch Overview ページ → Add role / Edit role からロールを管理することもできます。
ローカルで実行します。 OAuth 認証には Databricks のユーザー ID (メールアドレス) が使用されます。
databricks_superuserロールには完全な DML アクセス (データの読み書き) が与えられますが、DDL (スキーマやテーブルの作成) は含まれません。先にdeployすることが重要なのはこのためです (下記の注記を参照) 。
他のユーザーにも同様に、手順 2 を繰り返して各ユーザー用に databricks_superuser を持つ OAuth ロールを作成してください。
Postgres パスワード認証 は、OAuth ロールの権限まわりの複雑さを避けられる、よりシンプルな代替手段です。ただし、Lakebase オートスケーリング UI の Branch Overview ページでユーザーのパスワードを設定しておく必要があります。
アプリをdeployすると、サービスプリンシパルがスキーマとテーブルを作成し、そのオーナーになります。databricks_superuser には完全な DML アクセス (読み書き) が与えられますが DDL は含まれないため、ローカル開発が可能になるのはスキーマが作成された後です。
先に npm run dev を実行してしまうと、自分の資格情報がスキーマのオーナーとなり、deployしたアプリ側で permission denied が発生します。復旧するには、まずデータをエクスポートし (pg_dump または一時的なスキーマのコピー) 、スキーマを削除してから再deployしてください。再deploy後、サービスプリンシパルが起動時にスキーマを再作成します。 (PostgreSQL のスキーマ所有権は作成したロールに紐付いており、通常のユーザーが再割り当てすることはできません。)
きめ細かな権限
ほとんどのユースケースでは databricks_superuser で十分です。スキーマ単位の grants が必要な場合は、公式ドキュメントを参照してください。
fine-grained grants 用の SQL スクリプト
これらの grants を実行する前に、アプリを少なくとも一度は deploy して run し、サービスプリンシパルにデータベーススキーマを初期化させてください。
subject はユーザーのメールアドレスに、schema は使用するスキーマ名に置き換えてください。
CREATE EXTENSION IF NOT EXISTS databricks_auth;
DO $$
DECLARE
subject TEXT := 'your-subject'; -- name@databricks.com のようなユーザーのメールアドレス
schema TEXT := 'your_schema'; -- 'your_schema' をスキーマ名に置き換えてください
BEGIN
-- Databricks ID 用の OAuth ロールを作成
PERFORM databricks_create_role(subject, 'USER');
-- 接続とスキーマへのアクセス
EXECUTE format('GRANT CONNECT ON DATABASE "databricks_postgres" TO %I', subject);
EXECUTE format('GRANT ALL ON SCHEMA %s TO %I', schema, subject);
-- 既存オブジェクトに対する権限
EXECUTE format('GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA %s TO %I', schema, subject);
EXECUTE format('GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA %s TO %I', schema, subject);
EXECUTE format('GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA %s TO %I', schema, subject);
EXECUTE format('GRANT ALL PRIVILEGES ON ALL PROCEDURES IN SCHEMA %s TO %I', schema, subject);
-- 今後作成されるオブジェクトに対するデフォルト権限
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %s GRANT ALL ON TABLES TO %I', schema, subject);
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %s GRANT ALL ON SEQUENCES TO %I', schema, subject);
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %s GRANT ALL ON FUNCTIONS TO %I', schema, subject);
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %s GRANT ALL ON ROUTINES TO %I', schema, subject);
END $$;