AI SREClickHouse Workshops

故障排查

一份症状、原因和修复方法的参考,涵盖课程构建和测试过程中出现过的每一个故障,并按出现位置分组。

Your computer
macOS terminal: Run workshop commands in Terminal using zsh or bash.

下面的每一条都是课程构建和测试过程中真实发生过的故障。找到你的症状,读懂原因,套用修复 方法。如果这里没有匹配的内容,就把问题交给你的编码助手, 自主学习指南 里有一段可直接粘贴的提示词,能把它变成你的讲师。

Windows 与 WSL 2

wsl --install 不可用或只打印帮助信息

  • 症状:管理员 PowerShell 不识别 wsl --install,或者它打印帮助信息而不是安装 Ubuntu。
  • 原因:Windows 低于本课程的最低要求、待安装的更新尚未应用,或者公司策略禁用了 WSL。
  • 修复:运行 Windows Update,并确认系统是 Windows 11 或 Windows 10 版本 2004 (build 19041)及更高版本。重启,然后按照 Microsoft 的 WSL 手动安装步骤 操作。 在受管控的机器上,需要管理员放开所需的 Windows 功能。

某条命令在 PowerShell 中「无法识别」

  • 症状:PowerShell 拒绝执行课程提供的 ./preflight.sh、export、source 或其他 Bash 命令。

  • 原因:Windows 的环境准备只在明确标注的 WSL 引导环节使用 PowerShell。 实训命令都在 WSL 2 上的 Ubuntu 里运行。

  • 修复:从开始菜单打开 Ubuntu,然后回到应用目录并在那里运行 preflight:

    cd ~/ClickHouse_Demos/workshops/build_workshop/app
    ./preflight.sh

仓库位于 /mnt/c 下

  • 症状:Docker 的 bind mount 很慢、脚本出现权限或行尾符相关的故障,或者仓库路径以 /mnt/c/Users/... 开头。

  • 原因:仓库被克隆到了 Windows 文件系统上,而不是 WSL 的 Linux 文件系统。

  • 修复:只有在你需要保留未提交的工作时才留着旧副本。否则,打开 Ubuntu 并在你的 Linux 主目录中克隆一份干净的副本:

    cd ~
    git config --global core.autocrlf input
    git clone https://github.com/ClickHouse/ClickHouse_Demos.git
    cd ClickHouse_Demos
    git switch build-workshop-v1
    cd workshops/build_workshop/app
    cp .env.workshop.example .env.workshop

Ubuntu 以 WSL 1 方式运行

  • 症状:wsl --list --verbose 显示 Ubuntu 的 VERSION 1,或者 Docker Desktop 无法与该发行版集成。

  • 原因:这个发行版早于 WSL 2,或者安装时默认使用了 WSL 1。

  • 修复:以 管理员身份打开 PowerShell,转换它,然后重新打开 Ubuntu:

    wsl --set-version Ubuntu 2
    wsl --set-default-version 2
    wsl --list --verbose

在 Ubuntu 内 docker 不可用

  • 症状:Docker Desktop 正在运行,但 Ubuntu 提示 docker: command not found 或者 连不上守护进程。
  • 原因:Docker Desktop 的 WSL 引擎或 Ubuntu 集成被禁用了。
  • 修复:启用 Docker Desktop -> Settings -> General -> Use the WSL 2 based engine 和 Resources -> WSL Integration -> Ubuntu,应用改动,然后在 PowerShell 中运行 wsl --shutdown 并重新打开 Ubuntu。之后 docker version 必须同时显示 Client 和 Server 两部分。

WSL 或 Docker 的内存不足 6 GB

  • 症状:preflight 报告内存不足,或者 docker info --format 'Docker memory: {{.MemTotal}} bytes' 打印出小于 6442450944 字节的值。

  • 原因:Docker Desktop 的 WSL 2 后端使用的是 WSL 虚拟机的内存上限。

  • 修复:关闭 Docker Desktop,打开 PowerShell,并创建一个 8 GB 的 WSL 上限:

    @('[wsl2]', 'memory=8GB', 'processors=4') |
      Set-Content -Encoding ascii "$env:USERPROFILE\.wslconfig"
    wsl --shutdown

    启动 Docker Desktop 并重新打开 Ubuntu。重新运行那条 docker info 命令和 preflight。

某个脚本报告 /usr/bin/env: 'bash\r': No such file or directory

  • 症状:某个 .sh 文件立即失败,错误信息中包含 bash\r 或 ^M。

  • 原因:Windows 的 CRLF 行尾符替换了仓库要求的 LF 行尾符。

  • 修复:在 Ubuntu 中设置 Git 的 WSL 策略,并恢复一份干净的检出:

    git config --global core.autocrlf input
    git status --short
    git add --renormalize .

    在丢弃或提交任何东西之前,先检查 git status。如果这份检出里没有你需要的工作, 在 ~/ClickHouse_Demos 下重新克隆一份干净副本是最安全的恢复方式。

OAuth 没有打开 Windows 浏览器

  • 症状:MCP 登录打印出一个 URL,但没有浏览器窗口打开。
  • 原因:编码助手运行在 WSL 内部,而浏览器转发不可用或被公司策略阻止。
  • 修复:从 Ubuntu 中复制完整的登录 URL,粘贴到普通的 Windows 浏览器里。 在那里完成授权,然后回到 Ubuntu 终端。

Docker

容器卡在 "Created" 状态从不启动

  • 症状:docker info 响应正常,但 docker compose ... up 让容器停留在 Created 状态,且从来没有任何容器变为 healthy。
  • 原因:Docker 引擎卡死了:守护进程有响应,但它实际上无法启动容器。曾在一次现场启动中 于 OrbStack 上出现过。
  • 修复:重启你的 Docker 引擎(Docker Desktop、OrbStack 或 Colima),等到它报告 Running,然后再次启动这套技术栈。在克隆仓库内的任何位置运行 cd "$(git rev-parse --show-toplevel)/workshops/build_workshop/app" && ./preflight.sh; 它会通过运行一个一次性容器作为测试,在你启动技术栈之前就捕获这个问题。

启动时出现 "port is already allocated"

  • 症状:docker compose ... up 失败,提示 Bind for 0.0.0.0:8080 failed: port is already allocated(或 :8000)。
  • 原因:另一个进程,或者一个旧的实训容器,已经占用了那个宿主机端口。
  • 修复:在克隆仓库内的任何位置运行 cd "$(git rev-parse --show-toplevel)/workshops/build_workshop/app" && ./preflight.sh。 它会指出是什么占用了端口,并按照「基础端口 + 20000」的约定打印出确切的覆盖设置,例如 set FRONTEND_HOST_PORT=28080 in .env.workshop。可用的覆盖变量是 FRONTEND_HOST_PORT、BACKEND_HOST_PORT,以及用于可观测性 overlay 的 OTEL_GRPC_HOST_PORT / OTEL_HTTP_HOST_PORT。设置建议的值、重新运行 preflight,然后启动技术栈。只有宿主机端口发生了变化;容器内的端口不变,所以这是安全的。

"platform does not match" 告警

  • 症状:Docker 在 pull 或 up 时打印平台不匹配告警(例如 linux/amd64 对 linux/arm64)。
  • 原因:某个镜像是为与你的机器不同的 CPU 架构构建的,这在 Apple Silicon 上很常见。
  • 修复:无害。这是告警而不是失败;镜像会在模拟下运行。让它继续即可。

ClickHouse Cloud

空闲之后的第一个请求很慢,或偶尔返回一次 500

  • 症状:服务空闲之后的第一个查询或看板加载很慢,或者某个请求返回一次 500 然后就正常了。
  • 原因:Cloud 服务会空闲缩容到零,唤醒需要约 30 秒;第一个请求要承担这个唤醒开销。 后端已经为首次连接设置了更长的超时,并会重试一次。
  • 修复:直接重试,或者等约 30 秒。这不是故障。这一点在 07 测试、失败与修复 中也很重要: 一个正在唤醒的服务会让故障 03 的超时更容易触发。

服务密码丢了

  • 症状:你没有保存 default 用户的密码,现在找不到它了。
  • 原因:离开创建流程之后,服务密码不会再次显示。
  • 修复:打开该服务,进入它的 Settings 并重置 default 用户的密码, 然后更新 .env.workshop 中的 CLICKHOUSE_PASSWORD。主机名随时可以从 Connect 弹窗中获取。

托管 Postgres 的密码丢了

  • 症状:你没有保存 clickhousectl cloud postgres create 给出的一次性 postgres 管理员密码。
  • 原因:它只显示一次,而且处于 beta 阶段的 postgres get / list API 即使在实例 健康时也可能返回空结果或 FORBIDDEN。
  • 修复:执行 clickhousectl cloud postgres reset-password <service-id>,然后在 .env.workshop(PGPASSWORD)和 ClickPipe 连接中使用新密码。

ClickHouse Cloud 无法访问

  • 症状:preflight 的连通性检查 FAIL,或者后端连不上; the command below 失败。

    CLICKHOUSE_HOST=$(sed -n 's/^CLICKHOUSE_HOST=//p' .env.workshop | tail -n 1)
    CLICKHOUSE_PORT=$(sed -n 's/^CLICKHOUSE_PORT=//p' .env.workshop | tail -n 1)
    curl "https://$CLICKHOUSE_HOST:$CLICKHOUSE_PORT/ping"
  • 原因:wifi、VPN 或防火墙;主机名错误(把协议前缀或端口粘进了 CLICKHOUSE_HOST);TLS 或端口不匹配;或者 Cloud 的 IP 访问列表阻止了你的 IP。

  • 修复:确认 CLICKHOUSE_HOST 是纯主机名(不带 https://,不带端口)、 CLICKHOUSE_PORT=8443、CLICKHOUSE_SECURE=true;检查 VPN 和防火墙;确认该 服务的 IP 访问列表允许你的地址。preflight 会指出具体的失败类型,DNS、 连接被拒、超时或 TLS 握手。

客户端打印 Unknown settings: ... skipping

  • 症状:查询能成功,但每次调用都会打印一条未知设置的告警。
  • 原因:本地安装的客户端比 Cloud 服务端更新,发送了该服务端版本不认识的设置项。
  • 修复:重做模块 00 第 6 步中匹配客户端版本的那几条命令。它们会通过 clickhousectl 读取 Cloud 服务端的版本,并选择对应的主/次版本客户端 发行版。不要用 --no-warnings 把所有客户端告警都隐藏掉。

CDC(模块 03)

创建 ClickPipe 时提示 table realtime_trips exists and is not empty

  • 症状:并不存在任何 ClickPipe 资源,但重新创建它却失败了,因为 default.realtime_trips 中已经有数据行。

  • 原因:删除一个 ClickPipe 会移除它在源端的复制槽,但可能会把目标表留下来。 新的 pipe 不会覆盖那张非空的表。

  • 修复:用带时间戳的备份名保留旧的原始数据行,然后重新创建这个 pipe。只需替换一次服务 ID 占位符;下面这些命令在旧的 materialized view 存在时 也会把它保留下来:

    CH_SERVICE_ID=<clickhouse-service-id>
    BACKUP_SUFFIX=$(date -u +%Y%m%d%H%M%S)
    
    if clickhousectl cloud service query --id "$CH_SERVICE_ID" \
      --query "EXISTS TABLE nyc_tlc_data.realtime_trips_to_taxi_trips_mv" | grep -q 1; then
      clickhousectl cloud service query --id "$CH_SERVICE_ID" --query "
        RENAME TABLE nyc_tlc_data.realtime_trips_to_taxi_trips_mv
        TO nyc_tlc_data.realtime_trips_to_taxi_trips_mv_backup_${BACKUP_SUFFIX}
      "
    fi
    
    clickhousectl cloud service query --id "$CH_SERVICE_ID" --query "
      RENAME TABLE default.realtime_trips
      TO default.realtime_trips_backup_${BACKUP_SUFFIX}
    "

    重新执行模块 03 的第 3 步,等新的 default.realtime_trips 表出现之后, 再在第 4 步中重新创建标准的 materialized view。只有在你确认不再需要这些备份中的数据之后, 才在之后删除那些带时间戳的备份。

ClickPipe 卡在 "Provisioning"

  • 症状:你创建 pipe 之后,它有一段时间一直显示 Provisioning。
  • 原因:快照和基础设施启动通常要几分钟,但即使对这张小表,也可能超过 10 分钟。
  • 修复:在控制台中查看进度,或者同时使用 clickhousectl cloud clickpipe list <clickhouse-service-id> 和 clickhousectl cloud clickpipe get <clickhouse-service-id> <clickpipe-id>。在最初的 几分钟里,只要它的状态或 updatedAt 值在往前推进,就继续等待。如果 10 分钟后它 仍然是 Provisioning 且没有任何更新,请确认 pg-trip-writer 日志 仍在插入数据,重新检查主机名、凭据、publication 和表映射,并 查看 pipe 报告的错误。在第一个 pipe 还在 provisioning 时,不要创建第二个 pipe 或者 materialized view。如果源端检查都通过、并且 Cloud 没有报告可处理的错误,请保存 get 的 输出,并升级给讲师或 ClickHouse Cloud 支持团队。

数据行没有到达 ClickHouse

  • 症状:pipe 处于 Running,但目标表的行数没有增长,Ops 看板也没有变化。
  • 原因:默认的同步间隔约为 60 秒,所以有延迟是正常的;或者生成器没有在插入数据; 或者 pipe 要读取的 publication 不存在。
  • 修复:至少等 60 秒。检查 pg-trip-writer 日志中出现了 inserted N trips,以及 created publication pub_taxi(你自己的实例)或 publication ... already exists(讲师提供的托管兜底实例)。确认 pipe 状态为 Running。如果 publication 不存在,pipe 就没有任何东西可读,在你拥有管理员权限的实例上,生成器会在首次运行时 创建它。

Materialized view 中没有数据行

  • 症状:realtime_trips 在增长,但(由 CDC materialized view 供给的)taxi_trips 一直是空的。

  • 原因:这个 materialized view 是在 ClickPipe 目标表存在之前创建的,或者它读取的 不是位于 default.realtime_trips 的 CLI 目标表。

  • 修复:等目标表出现,然后从 模块 03 第 4 步 复制完整的 materialized view 命令。先验证源表:

    clickhousectl cloud service query --id <clickhouse-service-id> --query "
      SELECT database, name, engine
      FROM system.tables
      WHERE name = 'realtime_trips'
    "

    materialized view 只处理它存在之后插入的数据行;创建之后请让行程写入器继续运行。

复制槽停滞

  • 症状:pipe 停滞,源 Postgres 上的 WAL 不断增长。
  • 原因:停滞的复制槽会保留 WAL;重新同步会创建一个新的复制槽。
  • 修复:在你自己的托管 Postgres 上(只有一个复制槽、余量充足),从控制台重新同步这个 pipe 即可。删除一个 pipe 会在源端删掉它的复制槽。任何由讲师提供的托管兜底资源池 属于讲师侧的事情,参见 infra/README.md。

环境变量

shell 中的 export 覆盖了 .env.workshop

  • 症状:你在 .env.workshop 中设置了一个值,但容器用的却是另一个值 (常见的是过期的 OPENAI_API_KEY、某个 LANGFUSE_*,或 CLICKHOUSE_PASSWORD)。
  • 原因:docker compose 会先从你的 shell 插值 ${VAR},而已导出的 shell 变量会「胜出」,压过文件里的值。
  • 修复:在你运行 compose 的那个 shell 里执行 unset OPENAI_API_KEY LANGFUSE_PUBLIC_KEY LANGFUSE_SECRET_KEY LANGFUSE_BASE_URL CLICKHOUSE_PASSWORD, 然后重新启动这套技术栈。preflight 检测到这种情况时会发出告警。

.env.workshop 中有重复的键

  • 症状:你在文件中设置的某个值被忽略了。
  • 原因:同一个键出现了两次;最后一次出现的胜出,这与 docker compose 的语义一致(preflight 也按同样方式读取它)。
  • 修复:删掉靠前的那个重复项,只留下你想要的那个值。

聊天(模块 08)

POST /api/chat 返回 503 并附带一条配置提示

  • 症状:聊天面板显示一条配置提示,/api/chat 返回 503;应用的其他部分都正常。
  • 原因:后端没有设置 OPENAI_API_KEY。
  • 修复:把 OPENAI_API_KEY 加进 .env.workshop,然后执行 docker compose --env-file .env.workshop -f docker-compose.workshop.yml -f docker-compose.otel.yml up -d --build backend。 聊天是唯一需要它的功能。

无法创建第一个 OpenAI key

  • 症状:OpenAI 不给新账号发放 API key。
  • 原因:新账号需要一次性的手机验证,而且没有免费额度。
  • 修复:完成手机验证,然后进入 Settings -> Billing:添加一种支付方式 并购买最低 5 美元 的预付额度。关闭自动充值(在设置过程中它默认是打开的), 这样你就绝不会被扣超过你充入的那 5 美元。

MCP 与 OAuth(模块 00 和 06)

MCP 端点返回 401

  • 症状:访问 https://mcp.clickhouse.cloud/mcp(或 /clickstack)返回 401。

  • 原因:在你完成浏览器 OAuth 流程之前,这是预期行为;该端点需要认证。

  • 修复:把这个服务器添加到你的 agent,然后运行 OAuth 流程并在浏览器中授权, 使用你所用工具对应的命令:

    • Claude Code:运行 /mcp,选择该服务器并授权(或者 claude mcp login <name>)。
    • Codex CLI:运行 codex mcp login <name>。
    • Cursor:打开 MCP 设置面板,点击该服务器的授权/登录控件。

    同时确认你的服务已打开 Connect with MCP 开关。

公司笔记本阻止了 MCP 或 OAuth

  • 症状:你的 agent 无法添加 MCP 服务器,或者 OAuth 重定向被阻止。
  • 原因:受管控笔记本的策略阻止添加 MCP 服务器或对外的 OAuth。
  • 修复:用个人电脑是最快的兜底方案。

Windsurf 无法通过原生 HTTP 连接

  • 症状:Windsurf 连不上 MCP 端点,或者它的 OAuth 不稳定。
  • 原因:Windsurf 是通过 mcp-remote 连接的,而不是原生的 streamable HTTP。
  • 修复:使用 mcp-remote 的命令形式: { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.clickhouse.cloud/mcp"] } (在模块 06 中接入 ClickStack MCP 时,把 /mcp 换成 /clickstack)。

本页内容

Track your progress?

Optional. We email a link to confirm your address; progress records once you open it.

Please use your work email address, not a personal one.

Progress tracking also requires accepting the current Terms of Service in Privacy settings.

ZH