CloudQuery 6.50 安装部署指南

CloudQuery CLI 6.50.0 在 Ubuntu 22.04 上的完整部署实测:二进制安装、cloudquery init、Hub 登录墙应对、源码构建 postgres destination 与 test source 插件、首次同步与数据验证、cron/systemd 调度与四条排障实录

CloudQueryCloudQueryELT安装部署PostgreSQL2026/11/03

CloudQuery 6.50 安装部署指南

一、概述

本文在两台服务器上完成 CloudQuery CLI 6.50.0 的安装与首次端到端同步:CloudQuery 服务器(Ubuntu 22.04,IP 10.89.62.3)负责运行 CLI 与插件,数据库服务器(PostgreSQL 16,IP 10.89.62.2,端口 5432)作为同步目标端。示例账号 root/admin,数据库连接口令 q1w2e3r4。

同步链路选用免费无凭证的官方测试源插件 cloudquery/test(生成模拟数据,不依赖任何云账号)写入 PostgreSQL destination。文中所有命令与输出均为实测回显。

关于版本与选型背景见 《CloudQuery 6.50 介绍与选型指南》;配置字段逐项解释见 《CloudQuery 6.50 配置参数详解》;子命令逐个拆解见 《CloudQuery 6.50 常用 CLI 命令详解》。

二、前置条件

项目要求实测值
操作系统Linux x86_64(glibc)Ubuntu 22.04
内存≥ 1 GB(单管道同步)8 GB
磁盘≥ 2 GB(CLI + 插件二进制 + 缓存)50 GB
网络可访问 github.com(下载二进制/插件)直连部分超时,见第9节
数据库服务器PostgreSQL ≥ 14(官方建议),需可远程连接PostgreSQL 16.13

数据库服务器侧的准备(安装、listen_addresses、pg_hba 放行 10.89.62.3)与 CloudQuery 无关,PostgreSQL 本身的部署可参考站内 《Ubuntu 22.04 安装 PostgreSQL 18 指南》。

三、第一步:下载并安装 CLI 二进制

CloudQuery 官方发布形态是单个压缩包(GitHub Releases,tag cli-v6.50.0)。在 CloudQuery 服务器上:

mkdir -p /opt/cloudquery-demo && cd /opt/cloudquery-demo
curl -sLO https://github.com/cloudquery/cloudquery/releases/download/cli-v6.50.0/cloudquery_linux_amd64.zip
curl -sLO https://github.com/cloudquery/cloudquery/releases/download/cli-v6.50.0/checksums.txt

核对大小与校验和(实测):

root@cq-server:/opt/cloudquery-demo# ls -la cloudquery_linux_amd64.zip
-rw-r--r-- 1 root root 13104580 Nov  3 05:41 cloudquery_linux_amd64.zip
root@cq-server:/opt/cloudquery-demo# sha256sum -c <(grep cloudquery_linux_amd64.zip checksums.txt)
cloudquery_linux_amd64.zip: OK

解压并安装到系统路径(实测):

root@cq-server:/opt/cloudquery-demo# unzip -o cloudquery_linux_amd64.zip
Archive:  cloudquery_linux_amd64.zip
  inflating: CHANGELOG.md
  inflating: cloudquery
root@cq-server:/opt/cloudquery-demo# install -m 0755 cloudquery /usr/local/bin/cloudquery
root@cq-server:/opt/cloudquery-demo# cloudquery --version
cloudquery version 6.50.0

压缩包内除二进制外自带 CHANGELOG.md,建议保留在项目目录里,升级前先看版本断代(6.50.0 就明确要求 source 插件必须是 protocol v3+)。

备注:若服务器直连 GitHub 超时,可临时挂代理下载(curl -x http://<proxy>:<port> -LO ...),本次实测 CLI 二进制下载直连可用,无需代理。

四、第二步:准备数据库服务器

在数据库服务器(10.89.62.2)上建同步目标库:

psql -U postgres -c "CREATE DATABASE cqdemo;"

从 CloudQuery 服务器验证连通性(实测):

root@cq-server:/opt/cloudquery-demo# PGPASSWORD=q1w2e3r4 psql -h 10.89.62.2 -U postgres -c "SELECT version();"
                                 version
---------------------------------------------------------------------------
 PostgreSQL 16.13 (Debian 16.13-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.3.0-1) 14.3.0, 64-bit
(1 row)

五、第三步:cloudquery init 生成项目配置

cloudquery init 从 Hub 插件目录(https://api.cloudquery.io/plugins)拉取模板生成 spec 文件。注意 `--source/--destination 参数必须用目录里的插件短名,写错会报 not found(实测负例):

root@cq-server:/opt/cloudquery-demo# cloudquery init --source files --destination postgres --spec-path connection.yml --disable-ai
Fetching plugins...
Error: source plugin "cloudquery/files" not found, destination plugin "cloudquery/postgres" not found. Run cloudquery init without --source and --destination flags to use interactive mode

PostgreSQL destination 的目录名是 postgresql;文件源叫 file,测试源叫 test。用正确名称实测成功:

root@cq-server:/opt/cloudquery-demo# cloudquery init --source file --destination postgresql --spec-path connection.yml --disable-ai
Spec file created successfully at connection.yml

Next steps:
  1. Edit connection.yml and configure the source and destination plugins
  2. Run cloudquery sync connection.yml to sync data
  3. See https://docs.cloudquery.io for more information

生成的 connection.yml 由两个 YAML 文档组成(kind: source + kind: destination),DSN 用环境变量占位:

kind: destination
spec:
  name: "postgresql"
  path: "cloudquery/postgresql"
  registry: "cloudquery"
  version: "v8.19.0"
  write_mode: "overwrite-delete-stale"
  spec:
    connection_string: "${POSTGRESQL_CONNECTION_STRING}"

把 DSN 改为实际值(本例直接写死,生产建议用环境变量):

root@cq-server:/opt/cloudquery-demo# grep -nE "files_dir|connection_string" connection.yml
11:  files_dir: "/opt/cloudquery-demo/data"
21:    connection_string: "postgresql://postgres:q1w2e3r4@10.89.62.2:5432/cqdemo?sslmode=disable"

六、第四步:test-connection 撞上 Hub 登录墙

先用 init 生成的官方 spec 测连接(实测):

root@cq-server:/opt/cloudquery-demo# cloudquery test-connection connection.yml
Error: unauthorized. Try logging in via `cloudquery login`

这是 2026 年 CloudQuery 商业化的关键行为:registry: cloudquery 下载官方插件需要 CloudQuery 账号(免费档也要登录,cloudquery login 走浏览器设备码流程;CI/无头环境可设 CLOUDQUERY_API_KEY 环境变量替代)。cloudquery login --help 原文:"This is required to download plugins from CloudQuery Hub. Local plugins and different registries don't need login."

两条可行路线:

  • 路线 A(有账号):cloudquery login 或 export CLOUDQUERY_API_KEY=<token> 后,connection.yml 原样可用,直接跳到第8节;
  • 路线 B(无账号,本文主线):改用 registry: local,插件二进制自行编译,全程离线可用,见第7节。

七、第五步(路线 B):从源码构建插件

7.1 安装 Go 工具链

官方插件源码在 cloudquery/cloudquery monorepo(tag plugins-destination-postgresql-v8.19.0),go.mod 要求 go 1.27.3。国内服务器直连 go.dev 不通(实测 curl https://go.dev/dl/ → 000),改走国内镜像:

curl -sL -o /tmp/go.tgz https://golang.google.cn/dl/go1.27.3.linux-amd64.tar.gz
tar -C /usr/local -xzf /tmp/go.tgz
/usr/local/go/bin/go version

实测输出:

go version go1.27.3 linux/amd64

7.2 稀疏检出源码

monorepo 体积大,用 blobless + cone sparse-checkout 只取需要的插件目录。直连 GitHub 时 git 报 HTTP2 错误(见第9节排障),加 HTTP/1.1 + 代理 后成功:

cd /opt/build
git -c http.version=HTTP/1.1 -c http.proxy=http://192.168.1.72:7897 \
  clone --filter=blob:none --depth 1 \
  --branch plugins-destination-postgresql-v8.19.0 --no-checkout \
  https://github.com/cloudquery/cloudquery.git cq-src
cd cq-src
git sparse-checkout init --cone
git sparse-checkout set plugins/destination/postgresql plugins/source/test
git checkout

实测检出体积:

root@cq-server:/opt/build/cq-src# du -sh .
126M    .

7.3 关闭用量上报(离线自托管补丁)

直接构建的官方插件在 sync 时会向 CloudQuery 平台上报用量并强校验账号(实测报错见第9节-2)。SDK 提供了公开开关:插件入口 main.go 中在 serve.Plugin(...) 前调用 SetSkipUsageClient(true)。对两个插件分别打补丁:

# destination:在 serve.Plugin(p) 调用前插入一行
sed -i "s|if err := serve.Plugin(p,|p.SetSkipUsageClient(true)\n\tif err := serve.Plugin(p,|" \
  plugins/destination/postgresql/main.go

test source 的 main.go 同理,把 p := serve.Plugin(plugin.Plugin()) 拆成先取对象再调 SetSkipUsageClient(true)。

说明:用量上报是官方免费额度(1M 行)的计数机制。跳过上报仅适用于自编译插件的学习/内网测试场景;生产环境请注册免费账号走官方分发,接受额度与合规约束。

7.4 构建

Go 模块代理同样降级到国内源(实测 proxy.golang.org 直连 000):

export PATH=/usr/local/go/bin:$PATH GOPROXY=https://goproxy.cn,direct GOFLAGS=-mod=mod
cd plugins/source/test && go build -o /opt/cloudquery-demo/plugins/cloudquery-source-test .
cd ../../plugins/destination/postgresql && go build -o /opt/cloudquery-demo/plugins/cloudquery-destination-postgresql .

实测产物:

root@cq-server:/opt/cloudquery-demo# ls -la plugins/
total 114260
-rwxr-xr-x 1 root root 63680525 Nov  3 06:00 cloudquery-destination-postgresql
-rwxr-xr-x 1 root root 52968731 Nov  3 05:59 cloudquery-source-test

八、第六步:local registry spec 与首次同步

写 local_sync.yml(source/destination 两个文档,registry: local 指向自编译二进制):

kind: source
spec:
  name: test
  path: /opt/cloudquery-demo/plugins/cloudquery-source-test
  registry: local
  version: "v4.0.0"
  tables: ["*"]
  destinations: ["postgresql"]
  spec:
    client_id: demo-client
---
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
  spec:
    connection_string: "postgresql://postgres:q1w2e3r4@10.89.62.2:5432/cqdemo?sslmode=disable"

依次执行 test-connection → migrate → sync(实测输出逐行照抄):

root@cq-server:/opt/cloudquery-demo# cloudquery test-connection local_sync.yml
connection succeeded for destination plugin postgresql
connection succeeded for source plugin test

root@cq-server:/opt/cloudquery-demo# cloudquery migrate local_sync.yml
All plugins initialized successfully
Migration planned for destination "postgresql"
Migration completed successfully

root@cq-server:/opt/cloudquery-demo# cloudquery sync local_sync.yml
All plugins initialized successfully
Migration planned for destination "postgresql"
Migration completed successfully
Sync completed successfully. Resources: 13, Errors: 0, Warnings: 0, Time: 1s

sync 默认自动先 migrate;--no-migrate 可关闭(见 D1 篇)。

九、第七步:数据验证

在数据库服务器上检查(实测):

postgres@db-server:~# psql -U postgres -d cqdemo -c "\dt"
                     List of relations
 Schema |           Name            | Type  |  Owner
--------+---------------------------+-------+----------
 public | cloudquery_sync_summaries | table  | postgres
 public | test_paid_table           | table  | postgres
 public | test_some_table           | table  | postgres
 public | test_sub_table            | table  | postgres
 public | test_testdata_table       | table  | postgres

postgres@db-server:~# psql -U postgres -d cqdemo -c "SELECT resource_id, column2, client_id, _cq_source_name FROM test_some_table;"
      resource_id       |   column2    | client_id  |    _cq_source_name
------------------------+--------------+------------+-----------------------
 63874524-1888-0818-... | 1023743ae... | client-... | cloudquery/test

postgres@db-server:~# psql -U postgres -d cqdemo -c "SELECT cli_version, source_name, destination_name, resources, source_errors, destination_errors, sync_duration_ms FROM cloudquery_sync_summaries ORDER BY _cq_sync_time DESC LIMIT 1;"
 cli_version | source_name | destination_name | resources | source_errors | destination_errors | sync_duration_ms
-------------+-------------+------------------+-----------+---------------+--------------------+------------------
 6.50.0      | test        | postgresql       | 13        | 0             | 0                  | 1015

destination 自动创建了 cloudquery_sync_summaries 审计表,每次同步写一行汇总——这是排查「同步到底跑了什么」的第一现场。

十、生产化要点

  1. 专用目录与账号:建议 /opt/cloudquery/{specs,plugins,state} 三目录分离,运行账号非 root;插件二进制固定版本存放,升级走灰度。

  2. DSN 用环境变量:spec 支持 ${VAR} 插值(init 模板即如此),避免口令进 Git。

  3. 定时调度:CloudQuery 无内置调度器,标准做法是 cron 或 systemd timer。cron 模板(每日 02:00 全量覆盖同步):

    0 2 * * * cquser cd /opt/cloudquery/specs && /usr/local/bin/cloudquery sync local_sync.yml --summary-location /opt/cloudquery/state/summary-$(date +\%F).jsonl >> /opt/cloudquery/state/cron.log 2>&1
    

    systemd timer 模板:

    # /etc/systemd/system/cloudquery-sync.service
    [Service]
    Type=oneshot
    User=cquser
    WorkingDirectory=/opt/cloudquery/specs
    ExecStart=/usr/local/bin/cloudquery sync local_sync.yml --summary-location /opt/cloudquery/state/summary.jsonl
    # /etc/systemd/system/cloudquery-sync.timer
    [Timer]
    OnCalendar=*-*-* 02:00:00
    Persistent=true
    
  4. 日志:CLI 默认在项目目录写 cloudquery.log(JSON 格式逐行),全局 flags 可调 --log-level/--log-format/--log-file/--log-console,详见 C1 篇 §日志。

  5. 增量同步:test 源无增量键;真实 source(如 postgresql/cloudwatch 类)配 backend_options 把状态存进目标库,语法与实测见 C1 篇。

十一、排障实录

实录 1:git 直连 GitHub 报 HTTP2 framing 错误。 现象:git clone ... https://github.com/cloudquery/cloudquery.git → fatal: unable to access ... The requested URL returned error: 421/Invalid HTTP2 stream 1(直连时 curl 正常、git 失败)。处置:-c http.version=HTTP/1.1 仍超时,最终 -c http.proxy=<内网代理> 成功。教训:容器/服务器上 curl 与 git 的网络栈行为不同,代理要单独给 git 配。

实录 2:sync 报 failed to initialize usage client: not authenticated。 现象:自编译官方 destination 首次 sync 失败,提示 "You may need to run cloudquery login or set CLOUDQUERY_API_KEY"。定位:plugin-sdk v4.20.0 起 source/destination 初始化用量客户端时强校验 token(SDK CHANGELOG 实测:"Fail early on usage client init if token is not set (#1401)")。处置:有账号→登录;无账号→按 §7.3 用 SDK 公开 API SetSkipUsageClient(true) 重编译。

实录 3:init 报 source plugin not found。 现象与处置见第5节:--source/--destination 必须用 Hub 目录短名(file/test/postgresql),不是仓库名(source_files/destination-postgres 都会 not found)。目录可在 https://api.cloudquery.io/plugins 直接查(免鉴权)。

实录 4:GitHub 直连超时。 本环境 api.github.com 与 releases 大文件下载直连不稳定,A1 篇版本核实即改走代理(查询日期 2026-11-03)。下载链降级顺序:官方直连 → 国内镜像(golang.google.cn、goproxy.cn)→ 代理。

十二、FAQ

Q1:必须注册 CloudQuery 账号吗? 用官方 Hub 插件(registry: cloudquery)必须登录(实测 unauthorized);用 registry: github 社区插件或 registry: local 自编译插件不需要。Free 账号 $0 含 1M 行额度,生产建议注册。

Q2:destination 一定要 PostgreSQL 吗? 官方 destination 共 14 种(postgresql/s3/duckdb/clickhouse/mysql/sqlite/file 等,实测目录 API)。本文选 PG 是因为其 schema 自动迁移最成熟、且自带 cloudquery_sync_summaries 审计表。

Q3:为什么 migrate 单独跑?sync 里不是已经做了? sync 默认隐含 migrate。单独 cloudquery migrate 的价值在于:变更表结构前先在目标库上「预演」DDL,配合 migrate_mode(try-safe/forced-safe/forced)与 --dry-run 控制风险,见 C1 篇。

Q4:自编译插件和官方分发功能上有差别吗? 同一 tag 源码编译,功能一致;差别仅在于官方分发带用量上报/许可校验(第11节-2),且官方渠道随 Hub 持续更新。自编译需自己跟踪版本升级(cloudquery upgrade check 可辅助,见 D1 篇)。

Q5:同步失败了一半怎么排查? 先看 stdout 的 Sync completed with errors. Resources: N, Errors: M 行,再查 cloudquery.log(JSON 逐行,含插件报错),最后 SQL 查 cloudquery_sync_summaries 的 source_errors/destination_errors 计数。三处口径互补。

十三、参考链接

CloudQuery 6.50 安装部署指南 - Quzuo