Docker-Compose生产级编排:健康检查与自愈设计实战

发布时间:2026/7/9 16:08:15
Docker-Compose生产级编排:健康检查与自愈设计实战 1. 项目概述为什么“docker-compose 编排与健康检查”是 OpenClaw 生产落地的临门一脚你已经跑通了前四天的内容环境准备、核心组件拆解、基础服务部署、网关配置。现在站在第七天的门槛上手里的 OpenClaw 看似能动但离“生产级”还差一口气——这口气就卡在编排的确定性和运行的自愈力上。不是所有能docker run起来的服务都叫生产级真正的生产级是当 MySQL 挂了Redis 响应慢了甚至 Gateway 自己卡在 GC 里时系统能自己发现、自己报警、自己重启、自己恢复而不是等你半夜被 PagerDuty 的电话吵醒。这就是docker-compose.yml不再是一份静态配置清单而是一份具备“生命体征监测”和“故障响应逻辑”的运维契约。标题里“7天从零”不是营销话术而是真实节奏前六天解决“能不能跑”第七天解决“敢不敢托付”。docker-compose在这里绝非只是把几个docker run命令打包成一个文件那么简单。它承担着三重不可替代的角色第一依赖拓扑定义者——明确声明 MySQL 必须先于 Gateway 启动Redis 必须在 Gateway 就绪后才接受连接第二资源仲裁者——为每个容器划出 CPU 份额、内存上限、磁盘 IO 权重避免一个失控的 Skill Agent 吃光整台服务器的资源第三健康状态中枢——通过/healthz和/readyz这两个轻量 HTTP 探针把容器内部的“心跳”和“呼吸”实时翻译成 Docker 引擎能理解的healthy/unhealthy状态码进而触发restart_policy或通知 Prometheus 告警。网络热词里反复出现的openclaw部署、nas部署openclaw、docker-compose up 报错unable to get image mysql:8.0.34背后全是编排层缺失导致的连锁故障镜像拉取失败没人兜底端口冲突没人协调依赖启动顺序错乱没人校验。而spring boot 邮件服务健康检查、langchain中chain与agent应用编排的区别这些对比性热词恰恰说明开发者正在从单体思维转向服务化治理——OpenClaw 的agent不是孤立的函数调用它需要与数据库、缓存、消息队列、外部 API 形成可观察、可编排、可伸缩的有机整体。所以本篇不讲怎么写 YAML 语法而是带你亲手把一份“能跑”的docker-compose.yml打磨成一份“敢放线上”的生产契约。你会看到一个healthcheck的interval参数设为 30 秒还是 5 秒直接决定故障发现是分钟级还是秒级一个depends_on的condition是service_started还是service_healthy决定了你的 Gateway 是在 MySQL 容器刚创建时就急着连还是等到 MySQL 真正监听 3306 端口后再握手。这才是第七天真正的价值把不确定性变成可计算、可验证、可交付的确定性。2. 核心设计思路从“能用”到“可靠”的四层编排演进很多初学者拿到 OpenClaw 的docker-compose.yml模板第一反应是“照着改端口、改密码、up -d就完事”。结果上线三天MySQL 容器因磁盘满自动退出Gateway 因连不上 DB 卡死整个智能体系统静默瘫痪日志里只有一行connection refused。问题不在代码而在编排设计本身停留在“能用”层没进入“可靠”层。我带过十几个团队落地 OpenClaw总结出四层递进式编排设计模型每一层都对应一个关键风险点也对应本篇要攻克的核心2.1 第一层基础服务编排解决“启动顺序”问题这是最原始的depends_on。官方模板里常见services: openclaw-gateway: depends_on: - mysql - redis但它只保证容器启动顺序不保证服务就绪。实测中MySQL 容器started后可能还要 10-15 秒才能真正接受 TCP 连接。此时 Gateway 已开始初始化数据库连接池必然失败。解决方案是升级depends_on条件services: openclaw-gateway: depends_on: mysql: condition: service_healthy # 关键等待 mysql 容器健康检查通过 redis: condition: service_healthy这要求mysql和redis服务自身必须定义healthcheck。比如 MySQL 的健康检查不能只curl http://localhost:3306HTTP 端口不存在而必须用mysqladmin pingservices: mysql: image: mysql:8.0.34 healthcheck: test: [CMD, mysqladmin, ping, -h, localhost, -u, root, -p$$MYSQL_ROOT_PASSWORD] interval: 30s timeout: 10s retries: 5 start_period: 40s # 给 MySQL 充足的冷启动时间提示start_period是关键参数。MySQL 8.0 初始化 InnoDB 缓冲池可能耗时 30 秒以上若start_period设为 20 秒健康检查会在 MySQL 完全就绪前就开始执行必然失败并标记为unhealthy导致依赖它的 Gateway 永远无法启动。这个值必须根据你的服务器磁盘 IOPS 实测调整SSD 服务器设 40 秒HDD 服务器建议 90 秒。2.2 第二层资源隔离编排解决“资源争抢”问题OpenClaw 的 Skill Agent 可能调用 Playwright 启动 Chromium瞬间吃掉 2GB 内存而 MySQL 默认会申请 50% 物理内存作为 buffer pool。若不加限制两者在 8GB 内存的 NAS 上必然 OOM。docker-compose的deploy.resources是唯一解services: openclaw-gateway: deploy: resources: limits: memory: 3g cpus: 1.5 reservations: memory: 1.5g cpus: 0.5 mysql: deploy: resources: limits: memory: 2.5g # 明确限制防止 buffer pool 无节制增长 cpus: 1.0 reservations: memory: 1.2g cpus: 0.3reservations是调度器分配资源的“保底额度”limits是硬性“封顶额度”。OpenClaw Gateway 的reservations.memory: 1.5g意味着 Swarm 或 Kubernetes 调度时会确保该节点有至少 1.5G 内存空闲才调度此容器而limits.memory: 3g则是 OOM Killer 的红线——一旦容器 RSS 内存超 3G内核会立即杀死其进程。实操心得我在一台 16GB 内存的 Hetzner VPS 上部署时将mysql.limits.memory设为2.5gopenclaw-gateway.limits.memory设为3g剩余10.5g专门留给redis1g、nginx反向代理512m和系统缓冲区。这样即使 Agent 执行一个内存泄漏的 Python 脚本也只会 kill 掉该容器不会拖垮整个服务器。2.3 第三层网络与安全编排解决“信任边界”问题OpenClaw 的openclaw-cli容器默认使用network_mode: service:openclaw-gateway共享同一网络命名空间。这带来便利也埋下隐患CLI 容器若被注入恶意命令可直接访问 Gateway 的127.0.0.1:18789管理接口。生产环境必须打破这种隐式信任。正确做法是启用显式桥接网络并精确控制端口暴露networks: openclaw-net: driver: bridge ipam: config: - subnet: 172.20.0.0/16 services: openclaw-gateway: networks: - openclaw-net ports: - 18789:18789 # 仅暴露 UI 端口给宿主机 # - 18788:18788 # 绝对禁止暴露 gRPC 端口 # 移除 network_mode: service:...强制走桥接网络 openclaw-cli: networks: - openclaw-net # 不暴露任何端口仅通过 openclaw-net 内部通信同时必须禁用 CLI 容器的危险 Linux Capabilities。官方模板默认cap_drop: [NET_RAW, NET_ADMIN]这是正确的。但如果你曾为调试临时添加cap_add: [ALL]上线前务必删除。一个血泪教训某客户在测试环境为openclaw-cli开启了SYS_ADMIN结果一个第三方 Skill 调用mount命令意外将宿主机/etc目录挂载进容器导致 Gateway 配置被覆盖整个系统失联 6 小时。2.4 第四层可观测性与自愈编排解决“故障盲区”问题前三层让服务“跑起来”这一层让它“活下来”。OpenClaw 内置的/healthzliveness和/readyzreadiness是黄金探针但它们的价值只有被docker-compose正确消费时才释放。liveness探针失败Docker 会kill -9并重启容器readiness探针失败Docker 会将容器从负载均衡池中剔除但不重启。二者必须配合使用services: openclaw-gateway: healthcheck: test: [CMD, curl, -f, http://localhost:18789/healthz] interval: 10s timeout: 5s retries: 3 start_period: 60s # Gateway 启动复杂需更长预热期 # 注意readiness 探针需由反向代理如 nginx调用不在 docker-compose 中定义 restart: unless-stopped deploy: restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 120s # 2分钟内最多重启3次防雪崩window: 120s是精髓。没有它当 Gateway 因数据库连接池耗尽而持续unhealthy时Docker 会每 10 秒重启一次形成“重启风暴”加剧数据库压力。有了windowDocker 会记录 2 分钟内的重启次数超限则永久停止给你留出人工介入窗口。这才是生产级的“自愈”——不是盲目重启而是有节制、有策略、有退路的恢复。3. 核心细节解析docker-compose.yml中 7 个必调参数的深度拆解一份生产级的docker-compose.yml表面是几十行 YAML内里是七处精密调节的阀门。任何一个参数设错都可能让整个系统在高负载下悄然崩溃。下面逐个拆解这些参数背后的物理意义、计算逻辑和实操陷阱。3.1healthcheck.test不只是curl而是服务状态的“翻译器”test: [CMD, curl, -f, http://localhost:18789/healthz]看似简单但-f参数至关重要。它让curl在 HTTP 状态码非 2xx 时返回非零退出码Docker 才会判定为unhealthy。若漏掉-fcurl即使收到503 Service Unavailable也会返回 0健康检查永远“成功”。更深层的问题是/healthz只检查 Gateway 进程是否存活不检查其依赖。一个健壮的生产探针应该包含依赖检查。OpenClaw 官方文档提到docker compose exec openclaw-gateway node dist/index.js health --token $OPENCLAW_GATEWAY_TOKEN这是一个认证的深度健康快照。但docker-compose的healthcheck无法直接执行带 token 的命令因为 token 存在.env文件中healthcheck无法读取。解决方案是编写一个 shell 脚本封装#!/bin/sh # /health-check.sh inside gateway container if curl -fsS http://localhost:18789/healthz; then # 主服务健康再检查关键依赖 if mysqladmin ping -h mysql -u root -p$MYSQL_ROOT_PASSWORD /dev/null 21 \ redis-cli -h redis ping /dev/null 21; then exit 0 else exit 1 fi else exit 1 fi然后在docker-compose.yml中调用healthcheck: test: [/health-check.sh] # ... 其他参数注意此脚本必须 COPY 进 Gateway 镜像且mysql和redis是容器名Docker DNS 解析不是127.0.0.1。实测中我们发现某次 MySQL 密码含特殊字符$未用双引号包裹导致 shell 解析错误健康检查永远失败。因此脚本中必须用$MYSQL_ROOT_PASSWORD。3.2healthcheck.interval与timeout时间窗口的博弈interval: 10s和timeout: 5s不是随意写的。它们共同定义了一个“探测周期”。interval是两次探测的间隔timeout是单次探测的最长容忍时间。若timeout太短如1s网络抖动或 GC 暂停会导致误判若timeout太长如30s故障发现延迟会飙升。计算公式是故障发现时间 ≈ interval × (retries 1)。设interval10s,retries3则最坏情况下需10s × 4 40s才能确认故障。这对金融分析类 Skill 可能太长需压到interval5s, retries215s 发现。但代价是探测频率翻倍增加 Gateway 负载。我的折中方案对healthzliveness用interval5s, timeout3s, retries215s 发现对readyzreadiness由 nginx 调用用interval30s, timeout10s, retries3120s 发现因为 readiness 失败只影响流量接入不触发重启。3.3start_period给慢启动服务的“喘息权”start_period是healthcheck的起始宽限期。它从容器created状态开始计时在此期间内即使健康检查失败Docker 也不会标记为unhealthy。OpenClaw Gateway 启动涉及 Node.js 加载、TypeScript 编译、插件初始化、数据库连接池建立实测在 4 核 8GB 服务器上平均耗时 45 秒。若start_period设为30s第 31 秒的第一次健康检查就会失败Gateway 被标记unhealthyrestart_policy开始工作形成“启动即失败”的死循环。如何精准设定方法是在开发机上执行time docker compose up -d openclaw-gateway docker compose logs -f openclaw-gateway | grep Server listening on记录从up到日志出现listening的时间再加 20% 余量。我们最终在生产环境将start_period设为60s经受住了连续 30 天的压测。3.4restart_policy.delay与window防雪崩的“熔断器”delay: 10s是重启前的冷却时间window: 120s是熔断时间窗口。二者结合构成一个简单的指数退避熔断器。max_attempts: 3意味着在任意连续 120 秒内如果 Gateway 重启超过 3 次Docker 就会彻底放弃将容器状态置为failed。这防止了“数据库慢 - Gateway 连接超时 - Gateway 重启 - 更多连接请求打向数据库 - 数据库更慢”的恶性循环。关键经验window值必须大于start_period interval × (retries 1)。例如start_period60s,interval10s,retries3则最小window应为6010×4100s。我们设120s是为了留出日志分析和人工干预的时间。3.5deploy.resources.limits.memoryOOM Killer 的“判决书”limits.memory: 3g不是建议值而是内核 OOM Killer 的判决依据。当容器 RSSResident Set Size内存持续超过 3GBLinux 内核会触发 OOM Killer选择一个进程杀死。但谁会被杀内核按oom_score_adj值排序值越高越容易被杀。Node.js 进程默认oom_score_adj0而 MySQL 的mysqld进程默认oom_score_adj-1000极难被杀。这意味着若mysql.limits.memory设得过低如1g而openclaw-gateway.limits.memory设得过高如4gOOM 时 MySQL 会幸存Gateway 会被杀系统反而更不稳定。正确策略是“厚此薄彼”给 MySQL 更高的limits.memory因其内存管理更成熟给 Gateway 略低但够用的值因其 JS 堆内存易泄漏并开启 Node.js 的--max-old-space-size2048参数严格限制 V8 堆大小从应用层堵住内存泄漏源头。3.6environment与.env文件密钥管理的“安全边界”OpenClaw 的OPENCLAW_GATEWAY_TOKEN、MYSQL_ROOT_PASSWORD等敏感信息绝不能硬编码在docker-compose.yml中。必须使用.env文件# .env 文件git ignore OPENCLAW_GATEWAY_TOKENsk-xxx MYSQL_ROOT_PASSWORDmysecretpass REDIS_PASSWORDredispass然后在docker-compose.yml中引用services: openclaw-gateway: environment: - OPENCLAW_GATEWAY_TOKEN${OPENCLAW_GATEWAY_TOKEN} mysql: environment: - MYSQL_ROOT_PASSWORD${MYSQL_ROOT_PASSWORD}致命陷阱.env文件必须与docker-compose.yml同目录且文件名必须是.env不能是.env.local或其他。Docker Compose 只认这个文件名。曾有团队将.env放在子目录up时所有变量为空Gateway 启动报token is required排查 2 小时才发现是路径问题。3.7volumes绑定挂载持久化的“数据锚点”OpenClaw 的OPENCLAW_CONFIG_DIR、OPENCLAW_WORKSPACE_DIR必须挂载到宿主机否则容器重启后所有 Skill 配置、会话历史、插件安装记录全部丢失。官方推荐volumes: - ./openclaw-config:/home/node/.openclaw - ./openclaw-workspace:/home/node/.openclaw/workspace - ./openclaw-auth:/home/node/.config/openclaw但权限问题会毁掉一切。OpenClaw 镜像以node用户UID 1000运行若宿主机目录./openclaw-config属主是rootUID 0容器内进程将无权写入启动时抛出EACCES错误。必须在docker-compose up前执行sudo chown -R 1000:1000 ./openclaw-config ./openclaw-workspace ./openclaw-auth提示在 NAS 部署时Synology DSM 的共享文件夹默认属主是adminUID 非 1000。必须在 DSM 控制面板中将文件夹权限设为“读写”给users群组并在docker-compose.yml中显式指定user: 1000:1000services: openclaw-gateway: user: 1000:1000 volumes: - /volume1/docker/openclaw/config:/home/node/.openclaw4. 实操过程从零构建一份生产可用的docker-compose.yml现在我们把前面所有理论落地为一份可直接cp、paste、docker compose up -d的完整配置。这不是官方模板的复制而是融合了 12 个生产环境踩坑经验的精炼版。我会逐段解释每一行的“为什么”以及它如何解决你在热搜词里看到的那些报错。4.1 完整docker-compose.yml配置已脱敏可直接使用version: 3.8 # 定义专用网络避免与宿主机其他容器冲突 networks: openclaw-net: driver: bridge ipam: config: - subnet: 172.20.0.0/16 # 定义全局变量便于统一管理 x-common-env: common-env TZ: Asia/Shanghai NODE_ENV: production # 定义全局健康检查模板避免重复 x-healthcheck: healthcheck interval: 10s timeout: 5s retries: 3 start_period: 60s services: # MySQL 8.0.34生产级配置 mysql: image: mysql:8.0.34 restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: openclaw MYSQL_USER: openclaw MYSQL_PASSWORD: ${MYSQL_PASSWORD} volumes: - ./mysql-data:/var/lib/mysql - ./mysql-conf:/etc/mysql/conf.d networks: - openclaw-net # 关键生产级 MySQL 配置防止 OOM command: --default-authentication-pluginmysql_native_password --max-connections200 --innodb-buffer-pool-size1536M --innodb-log-file-size256M --wait_timeout28800 healthcheck: test: [CMD, mysqladmin, ping, -h, localhost, -u, root, -p$$MYSQL_ROOT_PASSWORD] : *healthcheck deploy: resources: limits: memory: 2.5g cpus: 1.0 reservations: memory: 1.2g cpus: 0.3 # Redis 7用于缓存和会话 redis: image: redis:7-alpine restart: unless-stopped environment: REDIS_PASSWORD: ${REDIS_PASSWORD} volumes: - ./redis-data:/data networks: - openclaw-net command: redis-server /usr/local/etc/redis.conf healthcheck: test: [CMD, redis-cli, -h, localhost, -a, $$REDIS_PASSWORD, ping] : *healthcheck deploy: resources: limits: memory: 512m cpus: 0.5 reservations: memory: 256m cpus: 0.2 # OpenClaw Gateway核心服务 openclaw-gateway: image: ghcr.io/openclaw/openclaw:latest restart: unless-stopped environment: : *common-env OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN} OPENCLAW_CONFIG_DIR: /home/node/.openclaw OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace OPENCLAW_AUTH_PROFILE_SECRET_DIR: /home/node/.config/openclaw # 关键告诉 Gateway 如何连接依赖服务 DATABASE_URL: mysql://openclaw:${MYSQL_PASSWORD}mysql:3306/openclaw REDIS_URL: redis://:${REDIS_PASSWORD}redis:6379/0 # 关键绑定模式LAN 模式允许宿主机访问 GATEWAY_BIND: lan # 关键禁用 Bonjour避免 Docker 网络多播问题 OPENCLAW_DISABLE_BONJOUR: 1 volumes: - ./openclaw-config:/home/node/.openclaw - ./openclaw-workspace:/home/node/.openclaw/workspace - ./openclaw-auth:/home/node/.config/openclaw networks: - openclaw-net ports: - 18789:18789 # 仅暴露 UI 端口 # 关键依赖必须健康才启动 depends_on: mysql: condition: service_healthy redis: condition: service_healthy # 关键Gateway 自身健康检查 healthcheck: test: [CMD, curl, -f, http://localhost:18789/healthz] : *healthcheck deploy: resources: limits: memory: 3g cpus: 1.5 reservations: memory: 1.5g cpus: 0.5 restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 120s # OpenClaw CLI用于日常管理 openclaw-cli: image: ghcr.io/openclaw/openclaw:latest restart: no # CLI 是一次性命令不自动重启 environment: : *common-env OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN} # 关键CLI 通过 openclaw-net 网络访问 Gateway GATEWAY_URL: http://openclaw-gateway:18789 volumes: - ./openclaw-config:/home/node/.openclaw - ./openclaw-workspace:/home/node/.openclaw/workspace - ./openclaw-auth:/home/node/.config/openclaw networks: - openclaw-net # 关键移除危险 capabilities cap_drop: - NET_RAW - NET_ADMIN - SYS_ADMIN # 关键以 node 用户运行匹配挂载目录权限 user: 1000:1000 # Nginx 反向代理可选但强烈推荐 nginx: image: nginx:alpine restart: unless-stopped volumes: - ./nginx-conf:/etc/nginx/conf.d - ./nginx-logs:/var/log/nginx ports: - 80:80 - 443:443 networks: - openclaw-net # 关键Nginx 负责 readiness 探针检查 Gateway 是否可服务 healthcheck: test: [CMD, curl, -f, http://openclaw-gateway:18789/readyz] : *healthcheck depends_on: openclaw-gateway: condition: service_healthy4.2 配套.env文件安全第一# .env 文件 - 请勿提交到 Git # 生成强密码openssl rand -base64 32 MYSQL_ROOT_PASSWORDyour_strong_mysql_root_password_here MYSQL_PASSWORDyour_strong_openclaw_db_password_here REDIS_PASSWORDyour_strong_redis_password_here OPENCLAW_GATEWAY_TOKENyour_strong_gateway_token_here # 可选用于 HTTPS 的域名 DOMAIN_NAMEyour-domain.com4.3 初始化与启动流程一步到位创建目录结构mkdir -p openclaw-config openclaw-workspace openclaw-auth mysql-data mysql-conf redis-data nginx-conf nginx-logs设置目录权限关键# 确保 UID 1000 拥有所有目录 sudo chown -R 1000:1000 openclaw-config openclaw-workspace openclaw-auth sudo chown -R 1000:1000 mysql-data redis-data # nginx 日志目录可由 root 拥有nginx 进程会自行处理 sudo chown -R 1000:1000 nginx-logs配置 MySQL可选提升稳定性# 创建 ./mysql-conf/my.cnf cat ./mysql-conf/my.cnf EOF[mysqld]生产级优化skip_log_bin innodb_flush_log_at_trx_commit2 sync_binlog0 max_connections200 wait_timeout28800 interactive_timeout28800 EOF 配置 Nginx可选但推荐# 创建 ./nginx-conf/default.conf cat ./nginx-conf/default.conf EOFupstream openclaw_backend { server openclaw-gateway:18789; }server { listen 80; server_name _;location / { proxy_pass http://openclaw_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; # 关键将 readiness 探针路由到 Gateway location /readyz { proxy_pass http://openclaw_backend/readyz; } }} EOF 启动服务# 第一次启动会拉取镜像、初始化数据库 docker compose up -d # 查看启动日志确认无 ERROR docker compose logs -f --tail50 # 等待 2 分钟检查健康状态 docker compose ps # 输出应为mysql, redis, openclaw-gateway, nginx 状态均为 healthy # 若 openclaw-gateway 显示 unhealthy执行 docker compose logs openclaw-gateway | tail -50 # 常见原因MySQL 未就绪等 60 秒再查、密码错误检查 .env、端口冲突检查 18789 是否被占用首次配置浏览器访问打开http://localhost:18789或你的 NAS IP在设置页粘贴.env中的OPENCLAW_GATEWAY_TOKEN完成新手引导配置 Telegram/Discord 等渠道4.4 验证健康检查是否生效不要只信docker compose ps的healthy字样要亲手验证手动触发 liveness 探针# 进入容器内部模拟健康检查 docker compose exec openclaw-gateway curl -fsS http://localhost:18789/healthz # 应返回 200 OK无输出 # 故意制造故障停掉 MySQL docker compose stop mysql # 等待 30 秒3次检查 × 10s 间隔再查状态 docker compose ps | grep mysql # 应显示 Unhealthy 状态 # 查看 Gateway 是否因依赖失败而重启 docker compose logs openclaw-gateway | grep Server listening # 应看到多次启动日志证明 restart_policy 生效验证 readiness 探针通过 Nginx# 检查 Nginx 的健康检查 docker compose exec nginx curl -fsS http://openclaw-gateway:18789/readyz # 模拟 Gateway 过载用 ab 压测使其暂时无响应 # ab -n 1000 -c 100 http://localhost:18789/api/v1/chat/completions # 观察 Nginx 日志应有 upstream timed out 错误证明 readiness 探针在起作用5. 常见问题与排查技巧实录热搜词背后的真实战场网络热词是用户痛点的晴