SpyBara
Go Premium

claude-apps-gateway-on-gcp.md 2026-06-29 23:02 UTC to 2026-06-30 23:02 UTC

This page contains 330 additions and 0 deletions.

2026
Tue 30 23:02

Развертывание Claude apps gateway на Google Cloud

Практический пример запуска Claude apps gateway на Google Cloud: Cloud Run или GKE, Cloud SQL для PostgreSQL, Secret Manager и аутентификация через сервисный аккаунт для Agent Platform.

Этот пример развертывает Claude apps gateway на Google Cloud с использованием Agent Platform Google Cloud в качестве вышестоящего поставщика моделей, используя либо Cloud Run, либо GKE для вычислений. Google Workspace используется в качестве примера поставщика идентификации (IdP), но работает любой поставщик, совместимый с OpenID Connect (OIDC); изменяется только блок oidc. Подробности для каждого IdP см. в разделе Настройка поставщика идентификации.

Что вы создадите

Диаграмма Claude apps gateway на Google Cloud: клиенты Claude Code подключаются по HTTPS к шлюзу (Cloud Run или GKE), который работает внутри VPC рядом с приватной базой данных Cloud SQL для состояния сеанса. Шлюз выполняет вход пользователей через OIDC для Google Workspace, читает конфигурацию и секреты из Secret Manager, перенаправляет запросы моделей в Agent Platform и извлекает свой образ из Artifact Registry при развертывании.

Эталонная конфигурация подготавливает:

  • Сервис Cloud Run или развертывание GKE, запускающие контейнер шлюза
  • Репозиторий Artifact Registry для образа шлюза
  • Экземпляр Cloud SQL для PostgreSQL, только с приватным IP, для хранилища шлюза
  • Секреты Secret Manager для gateway.yaml, ключа подписи JWT, секрета клиента OIDC и URL Postgres
  • Сервисный аккаунт с roles/aiplatform.user, подключённый непосредственно на Cloud Run или привязанный через Workload Identity на GKE
  • Внутренний Application Load Balancer на Cloud Run или внутренний GKE Ingress класса gce-internal на GKE для HTTPS

Предварительные требования

  • Проект GCP с включённым биллингом и разрешением на создание указанных выше ресурсов
  • CLI gcloud, аутентифицированный с помощью gcloud auth login, и Docker, установленный локально
  • Для трека GKE: kubectl и кластер GKE на VPC, созданный в пошаговом руководстве ниже
  • Доступ к необходимым моделям Claude в Model Garden в регионе, который их публикует
  • Веб-приложение OAuth 2.0 Google Workspace с URI перенаправления https://<gateway-host>/oauth/callback; см. Настройка поставщика идентификации
  • TLS имя хоста для шлюза, обычно внутреннее имя DNS, указывающее на балансировщик нагрузки

Установите проект и регион один раз:

export PROJECT_ID=<your-project>
export REGION=us-east5   # a region where the Claude models you need are published in Model Garden
gcloud config set project "$PROJECT_ID"

Развертывание шлюза

Приведённые ниже шаги подготавливают полное развертывание с помощью команд gcloud.

1

Включение API

Включите API сервисов, которые использует пошаговое руководство:

gcloud services enable \
aiplatform.googleapis.com \
artifactregistry.googleapis.com \
sqladmin.googleapis.com \
secretmanager.googleapis.com \
iamcredentials.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
servicenetworking.googleapis.com \
run.googleapis.com \
container.googleapis.com

Необходимые API зависят от пути развертывания:

  • compute и servicenetworking: требуются для пути приватного IP Cloud SQL
  • run: только Cloud Run
  • container: только GKE
2

Создание сервисного аккаунта и предоставление IAM

Шлюз работает как выделенный сервисный аккаунт с разрешением на вызов Agent Platform. Он достигает Cloud SQL через VPC с пользователем пароля, поэтому роль Cloud SQL IAM не требуется:

gcloud iam service-accounts create claude-gateway --display-name="Claude apps gateway"
SA="claude-gateway@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:${SA}" --role="roles/aiplatform.user" --condition=None

Затем включите модели Claude для проекта в Model Garden; модели публикуются в определённых регионах, поэтому проверьте каждую карточку модели.

3

Построение и отправка образа в Artifact Registry

Постройте образ в соответствии с требованиями к образу контейнера, используя двоичный файл linux-x64 glibc, и отправьте его:

gcloud artifacts repositories create claude-gateway \
--repository-format=docker --location="$REGION"
gcloud auth configure-docker "${REGION}-docker.pkg.dev" --quiet

# Cloud Run requires linux/amd64. --provenance=false avoids a buildx OCI
# image index that Cloud Run rejects.
docker build --platform=linux/amd64 --provenance=false \
-t "${REGION}-docker.pkg.dev/${PROJECT_ID}/claude-gateway/gateway:<version>" .
docker push "${REGION}-docker.pkg.dev/${PROJECT_ID}/claude-gateway/gateway:<version>"
4

Подготовка Cloud SQL для PostgreSQL

Создайте экземпляр на VPC через Private Services Access, чтобы он не имел публичного IP; это также удовлетворяет проектам, где применяется constraints/sql.restrictPublicIp:

VPC=cc-gateway-vpc
gcloud compute networks create "$VPC" --subnet-mode=custom
gcloud compute networks subnets create cc-gateway-subnet \
--network="$VPC" --region="$REGION" --range=10.0.0.0/24

# Private Services Access: one-time per VPC
gcloud compute addresses create "google-managed-services-${VPC}" \
--global --purpose=VPC_PEERING --prefix-length=16 --network="$VPC"
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges="google-managed-services-${VPC}" --network="$VPC"

gcloud sql instances create claude-gateway-db \
--database-version=POSTGRES_16 --tier=db-g1-small --region="$REGION" \
--network="projects/${PROJECT_ID}/global/networks/${VPC}" --no-assign-ip
gcloud sql databases create claude_gateway --instance=claude-gateway-db
PGPASS="$(openssl rand -hex 24)"
gcloud sql users create gateway --instance=claude-gateway-db --password="$PGPASS"

PRIVATE_IP="$(gcloud sql instances describe claude-gateway-db \
--format='value(ipAddresses[0].ipAddress)')"
GATEWAY_POSTGRES_URL="postgres://gateway:${PGPASS}@${PRIVATE_IP}:5432/claude_gateway?sslmode=require"

Среда выполнения Cloud Run или GKE должна находиться на этом VPC или маршрутизироваться в него.

5

Написание gateway.yaml

Блок upstreams указывает на Agent Platform с auth: {}, поэтому шлюз аутентифицируется через Application Default Credentials из сервисного аккаунта среды выполнения. Полное описание каждого поля см. в справочнике конфигурации.

Два поля listen зависят от того, что находится перед шлюзом:

  • public_url: требуется за Cloud Run или GKE Ingress. Шлюз строит redirect_uri IdP и документ обнаружения только из этого значения, никогда из заголовков X-Forwarded-*.
  • trusted_proxies: диапазоны источников переднего конца. Шлюз соблюдает X-Forwarded-For только когда TCP-пир находится в этом списке, затем проходит по цепи мимо доверенных переходов, поэтому ограничения скорости входа на IP и события аудита записывают IP-адреса разработчиков вместо адреса балансировщика нагрузки.

Установите trusted_proxies в соответствии с вашим передним концом. Внешний GKE Ingress класса gce не указан: он подготавливает адрес публичного правила переадресации, который проверка приватной сети /login отклоняет.

Передний конец trusted_proxies
Cloud Run, достигнутый напрямую, без балансировщика нагрузки [169.254.0.0/16]
Internal Application Load Balancer перед Cloud Run 169.254.0.0/16 плюс CIDR вашей подсети только для прокси
GKE внутренний Ingress, класс gce-internal CIDR вашей подсети только для прокси

Пример ниже использует значения внутреннего балансировщика нагрузки перед Cloud Run.

listen:
host: 0.0.0.0
port: 8080
public_url: https://claude-gateway.internal.example.com
trusted_proxies: [169.254.0.0/16, <your-proxy-only-subnet-cidr>]

oidc:
issuer: https://accounts.google.com
client_id: <your-oauth-client-id>
client_secret: ${OIDC_CLIENT_SECRET}           # GKE: ${file:/secrets/oidc-client-secret}
allowed_email_domains: [example.com]
# Google ignores offline_access; these yield refresh tokens:
scopes: [openid, profile, email]
extra_auth_params: { access_type: offline, prompt: consent }

session:
jwt_secret: ${GATEWAY_JWT_SECRET}              # GKE: ${file:/secrets/jwt-secret}

store:
postgres_url: ${GATEWAY_POSTGRES_URL}          # GKE: ${file:/secrets/postgres-url}

upstreams:
- provider: vertex
region: <your-region>                        # must match $REGION
project_id: <your-project>
auth: {} # ADC via the runtime service account
6

Сохранение секретов в Secret Manager

Создайте четыре секрета и предоставьте roles/secretmanager.secretAccessor сервисному аккаунту claude-gateway:

Секрет Источник
gateway-jwt-secret openssl rand -base64 32
gateway-oidc-client-secret Google Cloud Console → OAuth client
gateway-postgres-url $GATEWAY_POSTGRES_URL из шага Cloud SQL
gateway-config полный gateway.yaml из предыдущего шага

Способ доставки секретов в контейнер отличается в зависимости от трека:

  • На GKE они монтируются как файлы через драйвер Secret Manager CSI, и gateway.yaml ссылается на ${file:/secrets/...}.
  • На Cloud Run, который не может монтировать несколько секретов в один каталог, gateway.yaml монтируется как файл, а остальные три внедряются как переменные окружения, поэтому gateway.yaml ссылается на ${GATEWAY_JWT_SECRET}, ${OIDC_CLIENT_SECRET} и ${GATEWAY_POSTGRES_URL} вместо этого.
7

Развертывание

Команда ниже развертывает для производства за внутренним балансировщиком нагрузки.

gcloud run deploy claude-gateway \
--image="${REGION}-docker.pkg.dev/${PROJECT_ID}/claude-gateway/gateway:<version>" \
--region="$REGION" \
--service-account="claude-gateway@${PROJECT_ID}.iam.gserviceaccount.com" \
--min-instances=1 \
--timeout=3600 \
--ingress=internal-and-cloud-load-balancing \
--network="$VPC" --subnet=cc-gateway-subnet --vpc-egress=private-ranges-only \
--set-secrets=/etc/claude/gateway.yaml=gateway-config:latest,GATEWAY_JWT_SECRET=gateway-jwt-secret:latest,OIDC_CLIENT_SECRET=gateway-oidc-client-secret:latest,GATEWAY_POSTGRES_URL=gateway-postgres-url:latest \
--no-invoker-iam-check

Прямой исход VPC через --network, --subnet и --vpc-egress=private-ranges-only позволяет сервису достичь приватного IP Cloud SQL напрямую. Публичный исход к конечным точкам Agent Platform и accounts.google.com идёт непосредственно в интернет, а не через VPC, поэтому Cloud NAT не требуется.

Проверка IAM вызывающего должна быть открыта или отключена. Шлюз запускает свой собственный OIDC, и его клиенты не несут токен GCP, поэтому проверка вызывающего Cloud Run должна допускать неаутентифицированные запросы. Аутентификация запроса OIDC шлюза происходит после того, как он достигает контейнера, с allowed_email_domains, ограничивающим, какие домены могут входить.

Два флага допускают неаутентифицированные запросы:

  • --no-invoker-iam-check: отключает проверку без привязки allUsers для управления и работает в рамках Domain Restricted Sharing
  • --allow-unauthenticated: предоставляет allUsers роль run.invoker; используйте, если ваша организация не позволяет --no-invoker-iam-check

Ограничение входа через --ingress — это отдельный, независимый слой от проверки вызывающего; держите его установленным, чтобы ограничить сервис вашей корпоративной сетью.

По умолчанию URL Cloud Run *.run.app разрешается на публичный адрес, который проверка приватной сети /login отклоняет. Две топологии дают разработчикам приватно разрешаемое имя хоста, и Cloud Run не подготавливает ни одну для вас:

  • Internal Application Load Balancer, топология, которую предполагает команда развертывания выше: развертывайте с --ingress=internal-and-cloud-load-balancing, подготовьте внутренний Application Load Balancer перед сервисом с внутренним именем DNS и сертификатом, и установите listen.public_url на это имя хоста.
  • Внутренний вход только без балансировщика нагрузки: развертывайте с --ingress=internal и оставьте listen.public_url как URL *.run.app, значение по умолчанию в эталонных активах ниже. Чтобы *.run.app разрешался приватно, ваша команда сети должна уже работать с конечной точкой Private Service Connect для Google APIs, приватной зоной Cloud DNS, разрешающей *.run.app для неё, и маршрутизацией на месте к этой конечной точке.

Руководство Google по приватной сети для Cloud Run охватывает инфраструктуру, которая требуется обоим вариантам. Проверьте вход после того, как шлюз обслуживает приватное имя хоста; до этого подтвердите загрузку контейнера из его журналов в Cloud Run.

Обновите URI перенаправления авторизации клиента OAuth на <public_url>/oauth/callback перед первым входом. Переразверните после изменения public_url, потому что шлюз строит свой публичный источник только из этого параметра и игнорирует X-Forwarded-Host и X-Forwarded-Proto. X-Forwarded-For соблюдается для IP-адресов клиентов только когда установлен listen.trusted_proxies.

8

Отправка URL шлюза на машины разработчиков

Шлюз теперь работает, но разработчики не могут достичь его из /login до тех пор, пока URL шлюза не будет на их машинах. Установите forceLoginMethod и forceLoginGatewayUrl в файле управляемых параметров, который вы развертываете на каждом устройстве через MDM. В средстве выбора входа нет опции шлюза для разработчика, чтобы выбрать вручную.

Справочник Terraform

Эталонные активы развертывания автоматизируют трек Cloud Run на этой странице; активы конфигурации и образа применяются к обоим трекам:

  • setup.sh: идемпотентный подготовщик gcloud, который проходит полный путь Cloud Run, от включения API до первого развертывания
  • terraform/: то же развертывание как инфраструктура как код, для развертывания на зелёном поле: целевое применение для создания репозитория Artifact Registry, затем построение и отправка образа, затем полное применение
  • gateway.yaml.example и Dockerfile для образа среды выполнения distroless

Артефакты по умолчанию используют входящий трафик Cloud Run internal, поэтому балансировщик нагрузки не требуется. Чтобы соответствовать развертыванию этой страницы за ALB для производства, запустите setup.sh с INGRESS=internal-and-cloud-load-balancing или установите переменную Terraform ingress на INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER. Артефакты также по умолчанию используют слой вызывающего как предоставление allUsers run.invoker вместо --no-invoker-iam-check, обратное пошаговому руководству этой страницы; оба работают, и выбор зависит от ограничений политики вашей организации.

Активы предоставляются как рабочие примеры, а не как поддерживаемый артефакт для производства; проверьте и адаптируйте их к своей среде.

Troubleshooting

Для ошибок загрузки и входа шлюза см. независимую от платформы таблицу troubleshooting. Записи ниже относятся к Google Cloud.

Симптом Причина Исправление
Cloud Run возвращает 403 Forbidden перед достижением контейнера Проверка IAM вызывающего всё ещё включена Развертывайте с --no-invoker-iam-check или предоставьте allUsers роль run.invoker с --allow-unauthenticated
--no-invoker-iam-check отклонён с invoker_iam_disabled is not currently available Заблокировано constraints/run.managed.requireInvokerIam Используйте --allow-unauthenticated. Если Domain Restricted Sharing через constraints/iam.allowedPolicyMemberDomains также блокирует это, используйте трек GKE, который предоставляет шлюз на уровне сети без привязки allUsers.
Container manifest type … must support amd64/linux при развертывании Образ был построен на хосте, отличном от amd64, или buildx выдал индекс образа OCI Постройте с --platform=linux/amd64 --provenance=false
Загрузка шлюза завершается с ошибкой тайм-аута подключения Postgres на Cloud Run Сервис не подключён к VPC или Cloud SQL не имеет приватного IP на этом VPC; хранилище перестаёт ждать после 5 секунд Развертывайте с --network и --subnet для прямого исхода VPC и создавайте экземпляр Cloud SQL с --no-assign-ip и --network, указывающим на тот же VPC
Запросы Agent Platform возвращают 403 PERMISSION_DENIED Среда выполнения не использует сервисный аккаунт claude-gateway или модель не включена в Model Garden для проекта Установите --service-account на Cloud Run или привяжите Workload Identity на GKE и включите каждую модель Claude в Model Garden для целевого региона
Потоковые ответы обрезаны после фиксированной продолжительности Тайм-аут запроса переднего конца: сервис бэкенда балансировщика нагрузки за GKE Ingress по умолчанию имеет 30 секунд, а Cloud Run — 300 секунд Присоедините BackendConfig с повышенным timeoutSec на GKE или развертывайте с --timeout=3600 на Cloud Run

Следующие шаги