跳到主要内容

外部数据库

默认情况下,私有化部署控制面会包含一个 PostgreSQL 数据库。如果希望改用 DBA 团队管理的数据库,请禁用随包数据库实例,并配置控制面连接到你的数据库。

本指南介绍私有化控制面的 PostgreSQL 外部数据库路径。控制面连接角色不需要 PostgreSQL 超级用户权限。该部署路径暂不支持其它数据库引擎。

控制面后端服务会共享同一个数据库:

  • cp-api:控制面 API Server,启动时会执行 schema migration。
  • dp-manager:数据面管理器,连接同一个数据库,但不执行 migration。

PostgreSQL 要求

  • PostgreSQL 14 或更高版本。
  • 一个由控制面连接角色拥有的空数据库。
  • 一个带 CREATEROLEBYPASSRLS 权限、但不是 SUPERUSER 的登录角色。
  • 不需要 PostgreSQL 扩展。UUID 使用内置的 gen_random_uuid()

为什么控制面需要这些权限

首次启动时,cp-api 会准备数据库 schema,并创建一个内部低权限角色。连接角色需要足够权限来完成该引导过程,以及执行共享控制面操作。

每项权限都有明确用途:

  • 数据库所有权允许 cp-api 创建 publicauth schema、表、索引、函数和行级安全策略。在 PostgreSQL 默认权限下,数据库 owner 可以在 public 中创建对象,因此标准集群不需要额外 schema grant。
  • **CREATEROLE**允许 cp-api 创建和配置内部角色 cp_api_app。该角色用于带行级安全的租户范围查询。你不需要手动创建这个角色。
  • **BYPASSRLS**允许共享控制面操作在必要时跨组织读取数据,包括调用方 token 认证、计费 webhook、后台预算聚合器和 dp-manager 操作。

租户范围请求仍会切换到 cp_api_app,该角色既不是 SUPERUSER,也没有 BYPASSRLS。因此,控制面连接角色需要特定 PostgreSQL 能力,但不需要超级用户权限。

创建数据库和角色

以数据库管理员身份执行一次。请使用能够创建角色、创建数据库并授予 BYPASSRLS 的账号。控制面连接角色本身不需要是超级用户。

-- 1) 为控制面创建专用登录角色,不是超级用户。
CREATE ROLE aisix LOGIN PASSWORD 'change-me-to-a-strong-password'
NOSUPERUSER CREATEROLE BYPASSRLS;

-- 2) 创建由该角色拥有的专用数据库。
CREATE DATABASE aisix_cloud OWNER aisix;

你可以自行选择角色名、密码和数据库名。数据库所有权让 aisix 可以在首次启动时创建 public 对象并添加 auth schema。

请使用 URL 安全的密码,因为密码会嵌入 PostgreSQL 连接 URL 中。+/= 等字符如果没有百分号编码,可能破坏 DSN。建议使用 URL 安全值,例如 openssl rand -hex 24。参见私有化部署

如果 DBA 加固了 public schema,例如撤销了默认 CREATE 权限,请连接到新数据库后显式授予 schema 访问权限:

\c aisix_cloud
GRANT USAGE, CREATE ON SCHEMA public TO aisix;

不要预先创建 cp_api_app 角色。控制面会在 migration 期间创建并配置该角色,同时校验它的属性。提前创建该角色,尤其是属性不一致时,可能导致 migration 安全检查失败。

连接控制面到数据库

使用 Helm 时,请按照私有化部署配置中的说明设置 externalDatabase.* values,并设置 postgresql.builtin=false。Chart 会根据这些值为控制面服务构造连接 URL。

对于 Docker Compose 部署,服务会从环境变量读取标准 PostgreSQL 连接 URL。请让每个服务使用同一个角色和数据库:

AISIX_CLOUD_DATABASE_URL="postgres://aisix:<url-encoded-password>@db.internal.example.com:5432/aisix_cloud?sslmode=require"
AISIX_DPMGR_DATABASE_URL="postgres://aisix:<url-encoded-password>@db.internal.example.com:5432/aisix_cloud?sslmode=require"
  • AISIX_CLOUD_DATABASE_URL:由 cp-api 和 Dashboard 读取,其中 cp-api 会在启动时执行 migration。
  • AISIX_DPMGR_DATABASE_URL:由 dp-manager 读取。如果全新集群中 cp-api 仍在执行 migration,schema 尚未就绪,dp-manager 会重试最多约 2 分钟。

当数据库通过不完全受控的网络访问时,请设置 sslmode=require,或使用更严格的模式,例如 verify-full

控制面会创建什么

首次成功启动时,cp-api 会在你准备的数据库中构建完整 schema;之后每次启动都会以幂等方式重新执行相同步骤:

  • 用于控制面表的 public schema,例如 organizations、environments、models、caller API keys 和 budgets,由你的角色拥有;
  • 用于认证表的 auth schema,例如 users 和 sessions;
  • cp_api_app 角色,属性为 NOSUPERUSER NOBYPASSRLS NOINHERIT NOLOGIN,只被授予控制面表的 CRUD 权限,以及少数非敏感身份列的读写权限;
  • 将每个租户表限定到单个组织的行级安全策略。

连接角色会自动成为 cp_api_app 的成员,因此可以在每个请求中切换到该角色。你不需要手动授予该成员关系。

数据库权限检查清单

与 DBA 团队评审数据库角色时,可以使用以下清单:

要求作用
LOGIN允许控制面服务以该角色连接数据库。
数据库所有权允许 cp-api 创建和修改 schema、表、索引、函数和 RLS 策略。
CREATEROLE允许 cp-api 创建并管理内部 cp_api_app 角色。
BYPASSRLS允许跨组织控制面路径和 dp-manager 在共享连接上读取所需数据。
不是 SUPERUSER将角色权限控制在 PostgreSQL 超级用户以下。

验证数据库设置

控制面启动后,以管理员身份连接数据库并确认引导结果。

内部角色存在且权限正确受限:

SELECT rolname, rolsuper, rolbypassrls, rolcanlogin
FROM pg_roles WHERE rolname = 'cp_api_app';
-- 期望结果:cp_api_app | f | f | f

两个 schema 已创建:

SELECT nspname FROM pg_namespace WHERE nspname IN ('public', 'auth');
-- 期望结果:两行

排查启动错误

可以根据启动错误信息定位缺失的数据库能力。

cp-api database role must be SUPERUSER or have BYPASSRLS ...

连接角色缺少 BYPASSRLS。请以数据库管理员身份授予:

ALTER ROLE aisix BYPASSRLS;

permission denied for schema public

该角色无法在 public schema 中创建对象。请确认数据库所有权。如果 schema 被锁定,请显式授予 schema 访问权限:

\c aisix_cloud
GRANT USAGE, CREATE ON SCHEMA public TO aisix;

permission denied to create role

连接角色缺少 CREATEROLE。请以数据库管理员身份授予:

ALTER ROLE aisix CREATEROLE;

permission denied to set role "cp_api_app"

授予 cp_api_app 成员关系的 migration 可能没有完成。请检查 cp-api 启动日志中是否有更早的 migration 错误。

下一步

数据库和角色准备完成后,请返回私有化部署,配置控制面使用外部数据库。

完整的 Docker Compose 环境变量和 Helm values 请参见私有化部署配置