ingestr 完整教學

跨資料庫零程式碼資料搬遷 CLI 工具

§1 專案概述與定位

1.1 是什麼

ingestr 是由 Bruin Data 開發的開源命令列工具,用一條指令就能將資料從任意來源複製到任意目的地。以 Go 語言實作,底層採用 Apache Arrow 作為記憶體內中間格式,實現高效能的跨系統資料搬遷。

1.2 解決什麼問題

傳統資料搬遷面臨三大痛點:

  1. ETL 開發成本高:每個來源/目的地組合都需要獨立開發 connector
  2. 維護負擔重:API 變更、schema 演進、認證方式更新都需要人工介入
  3. 學習曲線陡:不同工具有不同的設定檔格式與部署方式

ingestr 的解法是「單一 CLI、統一 URI 格式」:使用者只需提供來源與目的地的 connection URI,就能完成資料搬遷。

1.3 關鍵數據

指標
GitHub Stars3,699
支援來源數113 個模組
支援目的地數27 個模組
主要語言Go (5.9 MB)
最新版本v1.0.21 (2026-06-06)
授權FSL-1.1-ALv2

1.4 適用對象

  • 資料工程師:快速建立 ad-hoc 資料搬遷管線
  • 後端工程師:跨環境資料同步(dev → staging → prod)
  • 資料分析師:將 SaaS 資料拉到本地 DuckDB 分析
  • DevOps:CI/CD 中的資料初始化與回填

§2 技術架構與核心設計

2.1 整體架構

ingestr 採用 pipeline 模式,核心流程為:

1Source → RecordBatch (Arrow) → Buffer → Strategy → Destination
  • Source:實作 source.Source 介面,負責連線、列舉表格、讀取資料
  • RecordBatch:使用 Apache Arrow 的 columnar 格式作為中間表示
  • Bufferdatabuffer 套件負責批次管理,支援記憶體與檔案兩種模式
  • Strategy:決定寫入策略(append / merge / delete+insert)
  • Destination:實作 destination.Destination 介面,負責 schema 建立與資料寫入

2.2 關鍵技術元件

元件路徑職責
Pipeline 核心pkg/pipeline/串接 Source → Destination 的完整流程
Source 介面pkg/source/source.go定義來源的統一 API
Destination 介面pkg/destination/destination.go定義目的地的統一 API
Strategy 引擎pkg/strategy/實作 append / merge / delete+insert
Schema Evolutionpkg/schemaevolution/來源/目的地 schema 差異處理
Schema Inferencepkg/schemainfer/無 schema 來源的自動推斷
Data Bufferpkg/databuffer/批次暫存(記憶體或檔案)
Arrow 轉換pkg/arrowconv/型別轉換與 Arrow 互操作
Naming 策略pkg/naming/表格/欄位命名轉換(如 snake_case)
Progress 追蹤pkg/progress/即時進度顯示
HTTP 工具pkg/http/共用 HTTP client 設定(TLS、重試等)
Web UIpkg/webui/內建 web 介面(server 模式)

2.3 Registry 模式

ingestr 使用自動化 registry 模式管理 113 個來源與 27 個目的地:

1cmd/genregistry/  → 自動產生 import 註冊碼
2pkg/source/*/register.go  → 每個來源的自我註冊
3pkg/destination/*/register.go  → 每個目的地的自我註冊

執行 go run ./cmd/genregistry 會掃描所有 register.go,產生統一的 import 檔案,避免手動維護巨型 import 清單。


§3 系統架構圖


graph TB
    subgraph CLI["CLI Layer (cmd/)"]
        ROOT[root.go
Cobra CLI 入口] INGEST[ingest.go
ingest 子命令] SERVER[server.go
server 子命令] TELEM[telemetry.go
匿名使用追蹤] end subgraph PIPELINE["Pipeline Core (pkg/pipeline/)"] PIPE[Pipeline
主引擎] BUF[DataBuffer
批次暫存] PROG[Progress
進度追蹤] end subgraph STRATEGY["Strategy Layer (pkg/strategy/)"] APPEND[Append
全量附加] MERGE[Merge
增量合併] DELINS[Delete+Insert
刪除後插入] end subgraph SOURCE["Source Layer (pkg/source/)"] SRC_DB["資料庫來源 (25+)
Postgres / MySQL / BigQuery
Snowflake / ClickHouse ..."] SRC_SAAS["SaaS 來源 (70+)
Shopify / Stripe / HubSpot
Salesforce / Slack ..."] SRC_FILE["檔案來源 (7+)
CSV / JSON / Parquet
Avro / HTTP / Blob"] end subgraph DEST["Destination Layer (pkg/destination/)"] DST_DB["資料庫目的地 (20+)
Postgres / BigQuery / Snowflake
ClickHouse / DuckDB ..."] DST_FILE["檔案目的地 (4)
CSV / JSONL / Parquet
Blob Storage"] end subgraph SCHEMA["Schema Layer"] EVOLVE[SchemaEvolution
schema 差異處理] INFER[SchemaInfer
自動推斷] ARROW[ArrowConv
型別轉換] end ROOT --> INGEST ROOT --> SERVER INGEST --> PIPE PIPE --> BUF PIPE --> PROG PIPE --> STRATEGY APPEND --> DEST MERGE --> DEST DELINS --> DEST SOURCE --> PIPE PIPE --> SCHEMA EVOLVE --> DEST style CLI fill:#E3F2FD,stroke:#1565C0 style PIPELINE fill:#FFF3E0,stroke:#E65100 style STRATEGY fill:#E8F5E9,stroke:#2E7D32 style SOURCE fill:#F3E5F5,stroke:#6A1B9A style DEST fill:#FCE4EC,stroke:#B71C1C style SCHEMA fill:#FFFDE7,stroke:#F57F17

sequenceDiagram
    participant User as 使用者
    participant CLI as CLI (cmd/)
    participant Pipe as Pipeline
    participant Src as Source
    participant Buf as DataBuffer
    participant Strat as Strategy
    participant Dst as Destination

    User->>CLI: ingestr ingest --source-uri ... --dest-uri ...
    CLI->>Pipe: New(config)
    Pipe->>Src: Connect(ctx, sourceURI)
    Src-->>Pipe: connected

    Pipe->>Src: ListTables(ctx)
    Src-->>Pipe: []TableInfo

    Pipe->>Dst: Connect(ctx, destURI)
    Dst-->>Pipe: connected

    Pipe->>Src: Read(ctx, readOpts)
    loop 每個 RecordBatch
        Src-->>Buf: Arrow RecordBatch
        Buf->>Strat: flush(batch)
        Strat->>Dst: Write(batch)
        Dst-->>Strat: ok
    end

    Pipe-->>CLI: done
    CLI-->>User: 完成 ✓ (rows, duration)


§4 快速上手

4.1 安裝

 1# 方法 1:官方安裝腳本(推薦)
 2curl -LsSf https://getbruin.com/install/ingestr | sh
 3
 4# 方法 2:pip 安裝(Python wrapper)
 5pip install ingestr
 6
 7# 方法 3:Docker
 8docker run --rm ghcr.io/bruin-data/ingestr:latest ingest --help
 9
10# 驗證安裝
11ingestr --version

4.2 第一次資料搬遷:Postgres → DuckDB

1# 從 Postgres 複製一張表到本地 DuckDB
2ingestr ingest \
3    --source-uri 'postgresql://user:pass@localhost:5432/mydb' \
4    --source-table 'public.orders' \
5    --dest-uri 'duckdb:///local.duckdb' \
6    --dest-table 'raw.orders'

4.3 增量載入(Incremental)

1# 使用 merge 策略,以 id 為主鍵,updated_at 為增量鍵
2ingestr ingest \
3    --source-uri 'postgresql://user:pass@localhost:5432/mydb' \
4    --source-table 'public.orders' \
5    --dest-uri 'bigquery://my-project?credentials_path=./sa.json' \
6    --dest-table 'warehouse.orders' \
7    --incremental-strategy merge \
8    --incremental-key updated_at \
9    --merge-key id

4.4 從 SaaS API 抓資料

 1# Shopify → BigQuery
 2ingestr ingest \
 3    --source-uri 'shopify://?api_key=YOUR_KEY&store_name=mystore' \
 4    --source-table 'orders' \
 5    --dest-uri 'bigquery://project?credentials_path=./sa.json' \
 6    --dest-table 'shopify.orders'
 7
 8# Stripe → DuckDB
 9ingestr ingest \
10    --source-uri 'stripe://?api_key=sk_live_xxx' \
11    --source-table 'charges' \
12    --dest-uri 'duckdb:///analytics.duckdb' \
13    --dest-table 'stripe.charges'

4.5 檔案匯入

 1# CSV → Postgres
 2ingestr ingest \
 3    --source-uri 'csv://.' \
 4    --source-table 'data.csv' \
 5    --dest-uri 'postgresql://user:pass@localhost:5432/mydb' \
 6    --dest-table 'public.imported_data'
 7
 8# Parquet → BigQuery
 9ingestr ingest \
10    --source-uri 'parquet://.' \
11    --source-table 'output.parquet' \
12    --dest-uri 'bigquery://project?credentials_path=./sa.json' \
13    --dest-table 'raw.parquet_data'

§5 進階功能

5.1 增量載入策略

策略說明適用場景
append直接附加,不檢查重複Log 類資料、事件串流
merge以主鍵更新或插入維度表、主資料
delete+insert先刪除符合條件的資料再插入需要精確覆蓋的場景

5.2 Schema Evolution

ingestr 自動處理來源/目的地的 schema 差異:

  • 新增欄位:自動在目的地新增
  • 型別衝突:可設定 discard_row(跳過)或 discard_value(設 null)
  • 欄位遮罩--column-mask 可隱藏敏感欄位(如密碼)

5.3 Column Masking(欄位遮罩)

1# 遮罩 email 和 phone 欄位
2ingestr ingest \
3    --source-uri 'postgresql://...' \
4    --source-table 'public.users' \
5    --dest-uri 'duckdb:///dev.duckdb' \
6    --dest-table 'dev.users' \
7    --column-mask 'email,phone'

5.4 Server 模式

ingestr 支援 HTTP server 模式,提供 Web UI 與 API:

1ingestr server --port 8080

5.5 CDC 多表同步(PostgreSQL)

1# PostgreSQL CDC:監聽 WAL 變更,同步多表到 BigQuery
2ingestr ingest \
3    --source-uri 'postgres_cdc://user:pass@localhost:5432/mydb?slot=ingestr_slot' \
4    --dest-uri 'bigquery://project?credentials_path=./sa.json' \
5    --dest-table 'cdc.*'

5.6 環境變數支援

所有 CLI 參數都可透過環境變數設定:

環境變數對應參數
SOURCE_URI / INGESTR_SOURCE_URI--source-uri
DESTINATION_URI / INGESTR_DESTINATION_URI--dest-uri
SOURCE_TABLE / INGESTR_SOURCE_TABLE--source-table
DESTINATION_TABLE / INGESTR_DESTINATION_TABLE--dest-table
INCREMENTAL_KEY / INGESTR_INCREMENTAL_KEY--incremental-key
INGESTR_DISABLE_TELEMETRY停用匿名使用追蹤

§6 資安檢測報告

6.1 掃描結果總覽

類別狀態說明
硬編碼密鑰🟢 安全未發現硬編碼的密碼、API key 或 token
.env 檔案🟢 安全未包含 .env 檔案
憑證檔案🟢 安全未包含 .pem / .key / credentials 檔案
Gitleaks 設定🟢 良好已配置 .gitleaksignore,已知誤報已排除
SQL 注入風險🟡 注意20 處使用 fmt.Sprintf 組裝 SQL 查詢
TLS 驗證跳過🟡 注意10 處 InsecureSkipVerify,均為使用者可設定選項
危險檔案操作🟢 安全10 處 os.Remove/WriteFile,均為暫存檔清理或憑證保存(0o600 權限)
外部指令執行🟢 安全未發現 exec.Command 呼叫
unsafe 指標🟢 安全未使用 unsafe.Pointer
CGO🟢 安全未使用 CGO
Telemetry🟡 注意內建匿名使用追蹤,可透過 INGESTR_DISABLE_TELEMETRY=true 關閉
Dockerfile🟢 良好多階段構建、非 root 使用者、最小化 runtime image
供應鏈🟡 注意go.mod 含 292 行相依,需留意供應鏈風險

6.2 SQL 注入風險詳細分析

ingestr 在 20 個來源模組中使用 fmt.Sprintf 組裝 SELECT 查詢:

1// 典型模式(以 postgres 為例)
2query := fmt.Sprintf("SELECT %s FROM %s", strings.Join(colNames, ", "), quoteTableName(table))

風險評估:🟡 低風險

  • 表名與欄位名來自系統目錄(metadata query),非使用者直接輸入
  • 多數模組有 quoteTableName() / quoteColumn() 函式做 escaping
  • 但仍有部分模組(如 adbc、databricks)未做完整 quoting

6.3 TLS 跳過驗證分析

10 處 InsecureSkipVerify = true 分佈於:

  • pkg/http/options.go — 通用 HTTP client 選項
  • pkg/source/influxdb/ — InfluxDB 連線
  • pkg/source/elasticsearch/ — Elasticsearch 連線
  • pkg/source/clickhouse/ — ClickHouse 連線
  • pkg/source/hana/ — SAP HANA 連線
  • pkg/destination/trino/ — Trino 目的地

風險評估:🟡 中低風險

  • 全部都是使用者透過 URI 參數主動啟用的選項
  • 程式碼中有 //nolint:gosec 註解標示為已知風險
  • 預設行為是啟用 TLS 驗證

6.4 總體評級

 1┌─────────────────────────────────────────┐
 2│  ingestr 資安評級:🟢 良好              │
 3│                                         │
 4│  整體風險:低                           │
 5│  可安全使用:是                         │
 6│  建議措施:                             │
 7│  1. 部署時設定 INGESTR_DISABLE_TELEMETRY│
 8│  2. 生產環境不使用 InsecureSkipVerify   │
 9│  3. 定期更新至最新版本                  │
10└─────────────────────────────────────────┘

§7 開發環境建置

7.1 前置需求

工具版本用途
Go1.25+編譯主程式
Git最新版本控制
Make任意建置自動化
gofumpt最新程式碼格式化
golangci-lintv2+靜態分析

7.2 建置步驟

 1# 1. Clone
 2git clone https://github.com/bruin-data/ingestr.git
 3cd ingestr
 4
 5# 2. 安裝開發工具
 6make setup
 7
 8# 3. 安裝相依
 9make deps
10
11# 4. 產生 registry imports
12make generate
13
14# 5. 建置
15make build
16
17# 6. 執行測試
18make test
19
20# 7. 格式化與 lint
21make format
22make lint

7.3 開發工作流

1# 新增來源:在 pkg/source/<name>/ 下建立檔案
2# 必須包含:
3# - register.go  → 自我註冊
4# - <name>.go    → 實作 source.Source 介面
5# 然後執行:
6make generate  # 更新 registry
7make build     # 重新編譯
8make test      # 執行測試

§8 部署模式

8.1 本地 CLI

最簡單的使用方式,適合 ad-hoc 操作:

1ingestr ingest --source-uri ... --dest-uri ...

8.2 Docker

1docker run --rm \
2    -e SOURCE_URI='postgresql://...' \
3    -e DESTINATION_URI='bigquery://...' \
4    -e SOURCE_TABLE='public.orders' \
5    -e DESTINATION_TABLE='raw.orders' \
6    ghcr.io/bruin-data/ingestr:latest ingest

8.3 CI/CD 整合

GitHub Actions 範例:

 1name: Daily Data Sync
 2on:
 3  schedule:
 4    - cron: '0 6 * * *'
 5
 6jobs:
 7  sync:
 8    runs-on: ubuntu-latest
 9    steps:
10      - name: Install ingestr
11        run: curl -LsSf https://getbruin.com/install/ingestr | sh
12
13      - name: Sync orders
14        env:
15          SOURCE_URI: ${{ secrets.SOURCE_DB_URI }}
16          DESTINATION_URI: ${{ secrets.DEST_BQ_URI }}
17          INGESTR_DISABLE_TELEMETRY: 'true'
18        run: |
19          ingestr ingest \
20            --source-table 'public.orders' \
21            --dest-table 'raw.orders' \
22            --incremental-strategy merge \
23            --incremental-key updated_at \
24            --merge-key id

8.4 Server 模式(Web UI)

1ingestr server --port 8080
2# 瀏覽器開啟 http://localhost:8080

§9 與同類工具比較

特性ingestrAirbyteFivetrandlt
部署方式單一二進位Docker Compose / K8sSaaSPython library
來源數量113300+500+100+
主要語言GoJava/Python閉源Python
增量載入支援支援支援支援
CDCPostgreSQL多種多種有限
Schema Evolution自動自動自動手動
成本免費開源/商業付費免費
學習曲線極低中等中等
適合場景Ad-hoc / CI/CD持續同步企業級Python 生態

ingestr 的獨特優勢

  1. 零設定檔:不需要 YAML / JSON 設定,純 CLI 參數
  2. 單一二進位:不需要 Docker、JVM 或 Python runtime
  3. 效能:Go 原生實作 + Arrow columnar 格式,記憶體效率高
  4. 113 → 27 的矩陣:任意來源到任意目的地的組合

§10 常見問題與疑難排解

Q1:如何處理大量資料?

ingestr 使用 DataBuffer 機制,支援記憶體與檔案兩種模式。大量資料時會自動切換到檔案模式,避免 OOM。

Q2:如何處理 schema 變更?

使用 --schema-evolution-mode 參數:

  • add(預設):自動新增欄位
  • discard_row:跳過不符合 schema 的資料列
  • discard_value:不符合的欄位值設為 null

Q3:如何除錯連線問題?

1# 啟用詳細日誌
2ingestr ingest --source-uri '...' --dest-uri '...' --verbose
3
4# 使用 server 模式的 Web UI 測試連線
5ingestr server

Q4:如何關閉 telemetry?

1export INGESTR_DISABLE_TELEMETRY=true
2# 或
3export DISABLE_TELEMETRY=true

Q5:支援自訂欄位型別嗎?

1# 使用 --columns 參數覆寫型別
2ingestr ingest \
3    --source-uri '...' \
4    --source-table 'public.data' \
5    --dest-uri '...' \
6    --dest-table 'raw.data' \
7    --columns 'id:bigint,name:string,amount:decimal(18,2)'

Q6:如何同步多張表?

 1# 方法 1:使用 glob pattern
 2ingestr ingest \
 3    --source-uri '...' \
 4    --source-table 'public.*' \
 5    --dest-uri '...' \
 6    --dest-table 'raw.*'
 7
 8# 方法 2:CDC 多表模式(PostgreSQL)
 9ingestr ingest \
10    --source-uri 'postgres_cdc://...' \
11    --dest-uri '...' \
12    --dest-table 'cdc.*'

§11 總結與建議

11.1 專案成熟度評估

面向評分說明
活躍度⭐⭐⭐⭐⭐每日有 commit,每 1-2 天發版
程式碼品質⭐⭐⭐⭐清晰的模組化架構,有 lint / test 流程
文件完整度⭐⭐⭐⭐官方文件齊全,但進階用法較少範例
社群活力⭐⭐⭐團隊主導開發,外部貢獻者較少
資安表現⭐⭐⭐⭐已配置 gitleaks,無嚴重漏洞
生產就緒度⭐⭐⭐⭐v1.0.x 穩定版,可用於生產

11.2 使用建議

推薦使用場景

  • Ad-hoc 資料搬遷(一次性或定期排程)
  • CI/CD pipeline 中的資料初始化
  • 從 SaaS API 拉資料到 data warehouse
  • 開發/測試環境的資料準備

不推薦使用場景

  • 需要即時串流同步(建議用 Kafka / Debezium)
  • 需要複雜轉換邏輯(建議用 dbt + ingestr 組合)
  • 需要 GUI 管理的企業級方案(建議用 Airbyte / Fivetran)

11.3 與現有工具鏈的整合

1# 典型 Modern Data Stack 整合
2# 1. ingestr 負責 EL(Extract + Load)
3ingestr ingest --source-uri '...' --dest-uri 'bigquery://...'
4
5# 2. dbt 負責 T(Transform)
6dbt run --models staging.orders
7
8# 3. 排程用 cron / Airflow / GitHub Actions

11.4 注意事項

  1. 授權:FSL-1.1 不是傳統 OSS 授權,商業使用前請確認合規性
  2. Telemetry:預設會收集匿名使用資料,生產環境建議關閉
  3. Go 版本:需要 Go 1.25+,確認開發環境版本
  4. 供應鏈:292 個 Go 相依項目,建議使用 go mod verify 驗證