Cloud Run 多区域高可用升级:用就绪探针实现秒级自动故障转移

2026-07-21 34 预计阅读时间: 1 分钟
来源: cloud.google.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

Cloud Run 的多区域部署正在从“复制几份服务”走向真正可自动恢复的高可用架构。新的就绪探针与服务健康状态能力,可以把容器实例的检查结果汇总到区域级服务健康状态,并通过 Serverless NEG 暴露给应用负载均衡器。当某个区域无法正常提供服务时,负载均衡器可以在数秒内停止向该区域发送流量。

这项变化解决了一个关键问题:部署到多个区域并不等于具备故障转移能力。只有流量入口能够识别区域故障,并自动选择健康区域,多区域部署才真正构成可用性方案。

从实例检查到区域故障转移

新的健康判断链路可以拆成四层:

  1. Cloud Run 使用 readiness probe 检查每个容器实例是否已经具备接收流量的条件。
  2. 服务健康功能汇总同一区域内健康与不健康实例的状态。
  3. 区域级健康结果通过对应区域的 Serverless NEG 提供给负载均衡器。
  4. 全局外部应用负载均衡器或跨区域内部应用负载均衡器,根据健康状态避开故障区域。

这里的 readiness 不能只回答“进程是否还活着”。一个进程可能仍在运行,但数据库连接池已经耗尽、配置尚未加载,或者关键依赖无法访问。就绪端点应该验证服务是否具备处理真实请求的最低条件,同时避免执行耗时查询或修改数据。

对公网网站和 API,应使用全局外部应用负载均衡器。对只在 VPC 内提供服务的应用,应使用跨区域内部应用负载均衡器。两种模式的入口不同,但核心链路相同:区域 Serverless NEG 提供服务健康信息,负载均衡器据此完成自动故障转移。

可以这样实践:构建真正反映就绪状态的端点

下面是一个可直接运行的 Flask 示例。它将存活检查与就绪检查分开,并通过环境变量模拟关键依赖是否可用。

app.py

import os
from flask import Flask, jsonify

app = Flask(__name__)


@app.get("/live")
def live():
    return jsonify(status="alive"), 200


@app.get("/ready")
def ready():
    dependency_ready = os.getenv("DEPENDENCY_READY", "true").lower() == "true"
    if not dependency_ready:
        return jsonify(status="not_ready", reason="dependency unavailable"), 503
    return jsonify(status="ready"), 200


@app.get("/")
def index():
    return jsonify(
        message="Cloud Run multi-region example",
        region=os.getenv("REGION", "unknown"),
    )


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=int(os.getenv("PORT", "8080")))

requirements.txt

Flask==3.1.0
gunicorn==23.0.0

Dockerfile

FROM python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .

ENV PORT=8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "2", "--threads", "4", "app:app"]

本地验证:

docker build -t cloud-run-ha-demo .
docker run --rm -p 8080:8080 cloud-run-ha-demo

另开一个终端执行:

curl -i http://localhost:8080/live
curl -i http://localhost:8080/ready
curl -i http://localhost:8080/

DEPENDENCY_READY=false 传给容器时,/ready 会返回 HTTP 503:

docker run --rm -p 8080:8080 -e DEPENDENCY_READY=false cloud-run-ha-demo
curl -i http://localhost:8080/ready

生产环境中,应把这个布尔值替换成有明确超时的依赖检查。不要在每次探测中执行大表查询,也不要因为非关键依赖短暂抖动就让整个区域退出流量池。

在 Cloud Run 服务中声明 readiness probe

下面的 YAML 展示了可以如何为 Cloud Run 容器配置 HTTP 就绪探针。请先把 PROJECT_ID 替换成项目 ID,并将镜像推送到对应的 Artifact Registry 仓库。具体可用字段应以当前 Cloud Run 和 gcloud 版本为准。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: cloud-run-ha-demo
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "1"
    spec:
      containerConcurrency: 80
      containers:
        - image: us-docker.pkg.dev/PROJECT_ID/apps/cloud-run-ha-demo:latest
          ports:
            - containerPort: 8080
          env:
            - name: DEPENDENCY_READY
              value: "true"
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 0
            timeoutSeconds: 1
            periodSeconds: 5
            failureThreshold: 2

可以将同一份配置部署到两个区域:

PROJECT_ID="your-project-id"
SERVICE="cloud-run-ha-demo"
IMAGE="us-docker.pkg.dev/${PROJECT_ID}/apps/${SERVICE}:latest"

for REGION in us-central1 us-east1; do
  sed \
    -e "s|PROJECT_ID|${PROJECT_ID}|g" \
    -e "s|us-docker.pkg.dev/${PROJECT_ID}/apps/cloud-run-ha-demo:latest|${IMAGE}|g" \
    service.yaml > "service-${REGION}.yaml"

  gcloud run services replace "service-${REGION}.yaml" \
    --project="${PROJECT_ID}" \
    --region="${REGION}"
done

这段命令适合说明“相同配置、多个区域”的基本实践。Cloud Run 的多区域服务进一步简化了跨区域配置管理;负载均衡器、每个区域的 Serverless NEG、域名和 TLS 证书仍需按公网或私网入口类型完成配置。

将最小实例数设置为 1 可以减少区域切换后的冷启动影响,但会产生持续的 CPU、内存或实例费用。就绪探针本身没有额外功能费用,不过执行探针仍会消耗标准计算资源。

active-active 为什么更适合快速恢复

服务健康能力最适合 active-active 架构:两个或更多区域平时都承接真实流量,因此容器、连接池、缓存和数据访问路径一直处于工作状态。某个区域故障后,负载均衡器只需要把流量移向其他健康区域。

active-passive 虽然可能节省部分运行成本,但切换时容易遇到冷启动、容量不足、缓存未预热以及依赖连接尚未建立等问题。如果采用 active-active,应提前确认每个剩余区域能否承受故障区域转移过来的峰值流量,并设置合理的扩缩容上限。

还要警惕把 Cloud Run 做成多区域后留下其他单点:

  • 数据库只有一个区域,应用故障转移后仍无法读写。
  • 多个区域共享同一个区域性缓存、消息代理或私有网络出口。
  • DNS、密钥、配置或制品只在一个区域可用。
  • 就绪探针只检查 HTTP 进程,没有覆盖真正关键的依赖。

对于三层应用,可以分别设计入口:Web 层通过全局外部负载均衡器接收公网流量,应用层通过跨区域内部负载均衡器处理 VPC 内部请求。每一层都应拥有自己的区域冗余和健康判断。

数据层决定高可用方案的上限

自动转移计算流量并不能保证数据零丢失。设计时需要明确恢复点目标 RPO:应用能否接受几秒钟的复制延迟,还是要求已确认写入在任何区域故障后都不能丢失?

Cloud Run 服务健康更适合数据已经在多个区域持续同步的读写型应用。可以结合 Firestore、Spanner、Cloud Storage 或 Cloud SQL 的托管多区域能力,但必须根据产品的复制语义、写入延迟、故障行为和数据驻留要求选择配置。多区域数据库也不意味着所有配置都天然满足数据主权要求,实际落地区域和复制边界仍需核对。

上线前检查清单

  • 为公网和私网流量选择正确的全局或跨区域负载均衡器。
  • 确保每个区域的 Serverless NEG 已连接到对应 Cloud Run 服务。
  • 让 readiness probe 检查关键依赖,并设置严格超时。
  • 用 503 明确表示实例暂时不能接收流量。
  • 验证单个健康区域能够承接故障后的总流量。
  • 检查数据库、缓存、消息系统、密钥和网络出口是否仍有区域单点。
  • 在预生产环境主动制造区域不可用状态,记录检测和切换时间。
  • 同时监控健康实例数、5xx、延迟、流量区域分布和数据库复制状态。

Cloud Run 的新能力缩短了从实例异常到区域流量切换的自动化链路,但它不是完整灾难恢复方案。把就绪探针、负载均衡、区域容量和数据复制一起验证,才能把“部署在多个区域”变成可量化、可演练的高可用系统。


相关推荐