CloudQuery 6.50 配置参数详解
CloudQuery 6.50 spec 文件全字段实测解析:source/destination/transformer 三种 kind、registry 三种取值的鉴权差异、PostgreSQL destination 与 test source 的插件参数、backend_options 增量状态语法、transformer 脱敏/加列与迁移冲突、write_mode 四种语义、日志与 validate-config 预检
CloudQuery 6.50 配置参数详解
一、概述
CloudQuery 的一切行为由 spec 文件(YAML)驱动。6.50 的 spec 支持三种顶层 kind(实测 CLI 源码 cli/internal/specs/v0/kind.go):
| kind | 作用 | 数量约定 |
|---|---|---|
source | 定义一个数据源插件及其取数范围 | 一个文件可多个 |
destination | 定义一个目标端插件及其写入策略 | 一个文件可多个 |
transformer | 定义一个转换插件(源→目标管道中间件) | 按需 |
多个文档用 --- 分隔写在同一个文件里(如 connection.yml),cloudquery sync 会按 destinations/transformers 的引用关系组装管道。spec 的 JSON Schema 内置于 CLI(也可从 Hub API 取插件级 schema),因此 cloudquery validate-config 无需登录即可校验官方插件配置(实测,见第11节)。
安装与首次跑通见 《CloudQuery 6.50 安装部署指南》;背景与选型见 《CloudQuery 6.50 介绍与选型指南》。
二、Source 块顶层字段
实测 schema(cli/internal/specs/v0/schema.json 的 Source 定义):
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
name | string | 必填 | 管道内引用名(destination 的 destinations 数组按它匹配) |
path | string | 必填 | 插件路径:Hub 为 cloudquery/test;local 为二进制绝对路径 |
registry | enum | cloudquery | cloudquery/github/local(实测三值,见第4节) |
version | string | 必填 | 插件 semver,如 v4.0.0 |
tables | []string | — | 同步表清单,支持 * 通配(如 ec2_*) |
skip_tables | []string | — | 排除清单(实测 tables: ["*"] + skip_tables: ["test_paid_table"] 后资源数从 13 降为 12) |
skip_dependent_tables | bool | false | 跳过依赖表(父表被排除时子表一并跳过) |
destinations | []string | — | 指向 destination 的 name,一对多扇出 |
backend_options | object | — | 增量状态存储(见第6节) |
deterministic_cq_id | bool | false | _cq_id 是否按内容确定性生成(实测置 false) |
otel_endpoint | string | — | OpenTelemetry 上报端点 |
spec | object | 必填 | 插件自身配置,schema 由各插件定义(见第5节/第7节) |
三、Destination 块顶层字段
实测 schema 的 Destination 定义:
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
name / path / registry / version / spec | 同 Source | — | — |
write_mode | enum | overwrite | overwrite / append / overwrite-delete-stale / upsert(实测四种,见第9节) |
migrate_mode | enum | try-safe | try-safe / try-forced / forced-safe / forced:schema 迁移的激进程度(实测冲突案例见 §8.3) |
pk_mode | enum | — | 主键策略(append 模式实测提示移除 _cq_id PK 约束) |
sync_group_id | string | — | 多 destination 分组同步标识 |
send_sync_summary | bool | true | 是否把同步汇总写入目标库 cloudquery_sync_summaries(实测生效) |
transformers | []string | — | 引用 transformer 的 name,数据逐条流经 |
四、registry 三种取值(实测差异)
| registry | path 形态 | 鉴权 | 插件来源 | 实测 |
|---|---|---|---|---|
cloudquery | cloudquery/postgresql | 必须登录(cloudquery login 或 CLOUDQUERY_API_KEY) | Hub 分发 | 匿名调用报 Error: unauthorized. Try logging in via cloudquery login |
github | 社区插件仓库 owner/repo | 免鉴权 | 该仓库 GitHub Releases 资产 | 社区插件(如 cq-source-chess-com)release 页带二进制资产 |
local | 本地二进制绝对路径 | 免鉴权 | 自行编译/拷贝 | 本文全部实测链路 |
注意:官方插件的 monorepo release 不含二进制资产(实测 releases/expanded_assets/plugins-destination-duckdb-v6.4.2 仅有源码 zip/tar.gz),所以官方插件想免登录只能走 local 自编译(流程见 B1 篇第7节)。
五、PostgreSQL destination 的 spec 字段
实测源码(plugins/destination/postgresql/client/spec/spec.go,v8.19.0):
| 字段 | 默认 | 说明 |
|---|---|---|
connection_string | 必填 | postgresql://user:pass@host:5432/db?sslmode=disable DSN |
batch_size | 10000 | 单事务批量行数 |
batch_size_bytes | 100000000 | 单事务批量字节数(约 100MB),先到者生效 |
batch_timeout | 0 | 批量攒数据的超时(毫秒),0 为不等待 |
use_copy_from | true | 用 COPY 协议批量写入(大表性能关键项) |
pgx_log_level | 2 | 底层 pgx 驱动日志级别(0-5) |
create_performance_indexes | false | 自动为 JSON 列建性能索引 |
retry_on_deadlock | 1 | 死锁重试次数(实测设为 3) |
pgvector_config | — | 向量列配置(对接 pgvector 扩展) |
aws_iam_auth | — | AWS IAM 临时凭证连接 RDS |
lakebase | — | Databricks Lakebase 模式开关 |
DSN 里的 sslmode 生产环境建议 require;跨主机明文传输用 sslmode=disable 只限内网实验(本文即内网实测口径)。
六、backend_options:增量状态存进目标库
Source 块可加 backend_options,把增量同步的游标/水位持久化:
backend_options:
table_name: cloudquery_state
connection: "@@plugins.postgresql.connection"
语法要点(实测):connection 必须写成 @@plugins.<destination的name>.connection,末段固定是 .connection,它引用目标端 spec 里的连接串。写成字段名原文会直接报错(实测负例):
Error: failed to replace variables in spec: backend connection variable plugins.postgresql.connection_string not found. Hint: backend connection must reference a destination plugin connection string, e.g. "@@plugins.aws_account.connection"
增量机制的运行时证据(实测 cloudquery.log):
State checkpoints are off, so the source saves its state itself (e.g. client-side)
且日志明确给出原因链:管道挂了 transformer 时 CLI 关闭「checkpoint 式状态」,改由 source 自行经 backend 存储。纯 overwrite-delete-stale 全量场景可以不配 backend_options。
七、插件 spec 举例:test source
官方测试源 cloudquery/test 的 spec 字段(实测源码 plugins/source/test/client/spec.go):
| 字段 | 默认 | 说明 |
|---|---|---|
num_clients | 1 | 生成的「客户」数(决定资源量) |
num_rows | — | 主表行数 |
num_sub_rows | — | 子表行数 |
num_sub_cols | — | 子表列数 |
required_env | — | 校验环境变量存在(模拟需要凭证的源) |
fail_immediately | false | 测试用:立即失败 |
exit_immediately | false | 测试用:立即退出 |
delete_records | false | 测试用:删除记录验证 stale 清理 |
实测一次带全要素的同步配置(source+transformer+destination 三文档,cloudquery sync 成功,Resources: 8):
kind: source
spec:
name: test
path: /opt/cloudquery-demo/plugins/cloudquery-source-test
registry: local
version: "v4.0.0"
tables: ["test_some_table", "test_testdata_table"]
skip_tables: []
destinations: ["postgresql"]
deterministic_cq_id: false
spec:
num_clients: 2
num_rows: 3
num_sub_rows: 5
backend_options:
table_name: cloudquery_state
connection: "@@plugins.postgresql.connection"
---
kind: transformer
spec:
name: jsonflattener
path: /opt/cloudquery-demo/plugins/cloudquery-transformer-jsonflattener
registry: local
version: "v2.1.22"
spec:
tables: ["test_testdata_table"]
---
kind: destination
spec:
name: postgresql
path: /opt/cloudquery-demo/plugins/cloudquery-destination-postgresql
registry: local
version: "v8.19.0"
write_mode: "overwrite-delete-stale"
send_sync_summary: true
transformers: ["jsonflattener"]
spec:
connection_string: "postgresql://postgres:q1w2e3r4@10.89.62.2:5432/cqdemo?sslmode=disable"
batch_size: 5000
batch_size_bytes: 50000000
use_copy_from: true
retry_on_deadlock: 3
八、Transformer 配置详解(basic 实测)
官方 transformer 共 3 个(实测 Hub 目录 API):basic(free)、jsonflattener(free)、awsrelations(paid)。
8.1 basic 的 transformations
basic 的 spec 是「规则列表」结构(实测源码 plugins/transformer/basic/client/spec/spec.go):每条规则含 kind、tables(glob)、columns、name/value 等。支持的 kind 实测清单:remove_columns / add_column / obfuscate_columns / obfuscate_json_paths / change_table_names / add_current_timestamp_column / rename_column / add_primary_keys / uppercase / lowercase / drop_rows 等。
实测配置(加一列常量 + 混淆一列):
kind: transformer
spec:
name: basic
path: /opt/cloudquery-demo/plugins/cloudquery-transformer-basic
registry: local
version: "v2.7.1"
spec:
transformations:
- kind: add_column
name: sync_env
value: demo
tables: ["test_some_table"]
- kind: obfuscate_columns
columns: ["column2"]
tables: ["test_some_table"]
destination 端 transformers: ["basic"] 挂上后同步,目标表实测数据(SELECT resource_id, column2, sync_env FROM test_some_table;):
resource_id | column2 | sync_env
--------------------------+--------------------------------------------------+----------
87364024-1888-0818-... | Redacted by CloudQuery | 023743ae9599972b... | demo
脱敏列变成 Redacted by CloudQuery | <sha>,新增列直接落库——transformer 是逐条记录级转换,发生在写入之前。
8.2 jsonflattener
spec 只有一个字段 tables: []string(指定哪些表做 JSON 展平)。行为(实测源码):仅展平 JSON 列里的对象键为独立列;数组值不展平。官方 test 源的 json 列值是 {"test": ["a","b",93274]},实测同步后未产生新列——不是配置错误,而是数据里没有可展平的对象键。真实场景(如 CloudWatch metrics 的 JSON 维度)才有展平收益。
8.3 transformer 加 NOT NULL 列的迁移冲突(实录)
对已存在的表首次应用 add_column 时,sync 直接失败(实测):
Error: failed to sync v3 destination postgresql: Can't migrate tables automatically. Please migrate manually or consider using "migrate_mode: forced".
Changes for tables that can't be migrated automatically:
test_some_table:
- Column "sync_env" added with type "utf8" and not null constraint
原因:给存量表加非空列不是「安全变更」,try-safe 默认拒绝。处置二选一:
migrate_mode: "forced" # 让 CLI 强制执行 DDL(实测有效,sync 成功)
或先手工 ALTER TABLE ... ADD COLUMN ... DEFAULT ...。validate-config 会提前给出同样的变更预告(实测输出见第11节),建议改 transformer 配置后先跑一次校验。
连带实录:迁移冲突会以误导性的 EOF 出现。 带着 transformer 新增的 sync_env 列改用不含 transformer 的旧配置再同步,stdout 只报:
Error: failed to sync v3 source test: EOF
看着像 source 插件崩溃,实际 cloudquery.log 里 destination 的真实报错是:
plugin returned error: Can't migrate tables automatically, migrate manually or consider using 'migrate_mode: forced'. Non auto migratable tables changes: test_some_table ...
教训:遇到 EOF/连接中断类错误先翻 cloudquery.log 找 destination 侧的原始错误,stdout 的 gRPC 转译会丢失根因。
九、write_mode 四种语义(实测)
| 模式 | 语义 | 实测行为 |
|---|---|---|
overwrite | 整表清空重写 | 常规全量 |
overwrite-delete-stale | 按主键 upsert + 删除源端已消失的行 | 本文主链路,重复同步行数不变 |
append | 只追加,不更新不删除 | 同一配置连跑两次,test_some_table 从 1 行变 2 行(实测) |
upsert | 按主键更新,不删 stale | 适合日志型源 |
切换模式的坑(实录):从 overwrite-delete-stale 改 append 后再同步,migrate 想移除 _cq_id 主键约束(append 不要求主键),触发「不能自动迁移」报错;清空表重跑或 migrate_mode: forced 解决。
十、日志体系
全局 flags(实测 --help):
| Flag | 默认 | 说明 |
|---|---|---|
--log-level | info | trace/debug/info/warn/error |
--log-format | json | json/text |
--log-file | cloudquery.log | 默认落在执行目录;--no-log-file 关闭 |
--log-console | false | 同时打到 stdout |
--telemetry-level | enabled | 匿名遥测开关 |
--cq-dir | ~/.cloudquery | 凭证/缓存目录 |
实测 JSON 日志样本(cloudquery sync ... --log-format json --log-console):
{"level":"info","invocation_id":"51687452","plugin_name":"cloudquery/test","plugin_version":"v4.0.0","caller":"logging/logger.go:121","msg":"Initializing","plugin":"source","timestamp":"2026-11-03T06:03:12Z"}
{"level":"warn","invocation_id":"51687452","plugin_name":"cloudquery/test","plugin_version":"v4.0.0","caller":"specvars/variables.go:45","msg":"State checkpoints are off, so the source saves its state itself (e.g. client-side)","timestamp":"2026-11-03T06:03:12Z","reason":"destinations use transformers"}
排障口径:stdout 只给结论行(Sync completed ...),过程细节全在 cloudquery.log;invocation_id 可把一次同步的所有日志行串起来。
十一、validate-config:免鉴权预检(实测)
cloudquery validate-config 从 Hub API 拉插件 spec 的 JSON Schema 做校验,不需要下载插件、不需要登录(实测对 registry: cloudquery 的 spec 直接通过)。
正例:
root@cq-server:/opt/cloudquery-demo# cloudquery validate-config connection.yml
(无输出,退出码 0)
负例(把并发数写成负数):
root@cq-server:/opt/cloudquery-demo# cloudquery validate-config bad.yml
Error: spec must be valid against schema: /
- must be >= 0
对 transformer 引发的 schema 变更,validate-config 还会输出迁移预告(实测):
test_some_table:
- Column "sync_env" added with type "utf8" and not null constraint
生产建议:CI 里 validate-config → migrate(预演 DDL)→ sync 三步分开跑。
十二、环境变量与敏感信息
- spec 任意字符串支持
${ENV_VAR}插值(init 模板默认${POSTGRESQL_CONNECTION_STRING}),口令不落盘; CLOUDQUERY_API_KEY:Hub 鉴权 token(替代cloudquery login,实测自第6节报错提示);- 插件进程的环境继承 CLI 环境(
required_env类字段即校验这些变量)。
十三、FAQ
Q1:tables 支持什么通配语法?怎么排除表?
["*"] 全量、["ec2_*"] 前缀通配。排除用独立的 skip_tables 字段(实测生效)。注意:tables 里写 ! 前缀不是排除语法——实测 tables: ["*", "!test_testdata_table"] 会把 !test_testdata_table 当字面 glob 匹配,报 tables include a pattern !test_testdata_table with no matches(SDK glob 实现无取反逻辑,实测源码 plugin-sdk/v4/glob/glob.go)。
Q2:一个 source 能同时写两个 destination 吗?
能。destinations: ["pg", "s3"] 扇出,各 destination 独立 write_mode(本文实测为单 source→单 destination→单 transformer 链路)。注意扇出时增量状态按 destination 维度分别管理。
Q3:overwrite-delete-stale 和 upsert 怎么选?
源端会物理删除记录、且需要目标端跟着删 → overwrite-delete-stale;只增改不删(审计/日志流)→ append 或 upsert。误配 append 到全量源会行数翻倍(实测第9节)。
Q4:为什么我的 backend_options 没建 cloudquery_state 表?
两种常见原因(实测):管道含 transformer 时 CLI 关闭 checkpoint 模式(日志 State checkpoints are off);source 本身无增量键(如 test 源 IncrementalKey=false)。确认源插件支持增量再看状态表。
Q5:spec 文件里 version 写 v8.19.0 还是 8.19.0?
两种都能解析,官方模板统一带 v 前缀(init 生成即如此)。local registry 的 version 仅作元数据展示(实测填 v4.0.0 正常同步)。
十四、参考链接
- 实测环境:CloudQuery 6.50.0 + PostgreSQL 16(B1 篇同链路)
- spec 结构:cloudquery/cloudquery 仓库
cli/internal/specs/v0/(kind.go/schema.json/variables.go,tag plugins-destination-postgresql-v8.19.0,查询日期 2026-11-03) - 插件字段:
plugins/destination/postgresql/client/spec/spec.go、plugins/source/test/client/spec.go、plugins/transformer/basic/client/spec/spec.go(同上 tag) - 插件目录与 tier:https://api.cloudquery.io/plugins (查询日期 2026-11-03)
- 子命令用法详见 《CloudQuery 6.50 常用 CLI 命令详解》