本文档提供了在 Google Distributed Cloud (GDC) 网闸隔离环境中部署 AI Gateway 的分步说明。该网关由 Envoy Gateway(基于 Envoy 代理的 Kubernetes Gateway API 实现)和 Envoy Agent Router(前身为 Envoy AI Gateway,可将 Envoy Gateway 转换为与 OpenAI 兼容的大语言模型 [LLM] 流量统一入口点)构建而成。内容涵盖了将容器映像和 Helm 图表植入本地 Harbor 注册表、在标准集群上安装两个控制平面、准备可选的基于令牌的速率限制后端,以及使用示例工作负载验证安装。
模型部署后端(Ollama、vLLM)通过配套指南集在 GDC 网闸隔离配置上部署开放权重模型进行部署;使用 Envoy 代理路由器进行基于正文的路由用户指南展示了如何按模型名称将请求路由到这些后端。
架构
该解决方案在 GDC 标准集群中运行。管理员工作站会将映像和 Helm 图表植入项目的 Harbor 注册表中,并安装两个控制平面:Envoy Gateway 控制器(用于根据 Gateway API 资源 [GatewayClass、Gateway、HTTPRoute] 对 Envoy 代理数据平面进行编程)和 Envoy Agent Router 控制器(用于通过外部处理器 [ExtProc] 扩展该数据平面,以处理 AI 流量 [AIGatewayRoute、AIServiceBackend、InferencePool])。应用客户端向 Envoy 代理发送与 OpenAI 兼容的请求,Envoy 代理会将这些请求路由到模型部署后端或 InferencePool。可选的 Redis 实例存储 Envoy 速率限制服务的计数器,用于基于令牌的速率限制。

Envoy Gateway
Envoy Gateway 是一个基于 Envoy 代理构建的开源项目,可简化 Envoy 代理作为 Kubernetes API Gateway 的采用、使用和管理。它实现并扩展了 Kubernetes Gateway API(Ingress API 的后继者):GatewayClass 和 Gateway 资源描述了入口点,HTTPRoute 等路由资源描述了流量的匹配和转发方式,而面向角色的设计则分离了基础架构团队和应用团队的职责。Envoy Gateway 会添加自己的扩展 API,例如 EnvoyProxy(数据平面设置)、Backend(集群外部或由 FQDN 引用的端点)和 ClientTrafficPolicy(连接设置,例如缓冲区限制)。
Envoy 代理路由器
Envoy Agent Router(以前称为 Envoy AI Gateway)是一个开源项目,它使用 Envoy Gateway 处理从应用客户端到生成式 AI 服务的请求流量。它提供了一个统一层,用于通过模型感知路由、上游身份验证、基于令牌的速率限制和可观测性来路由和管理 LLM 流量,并与 Gateway API Inference Extension (InferencePool, Endpoint Picker) 集成,以实现指标感知端点选择。控制器会监视 aigateway.envoyproxy.io/v1beta1 资源,并在 Envoy 代理旁边注入一个外部处理器;外部处理器会解析请求正文(例如 OpenAI 聊天补全请求的 model 字段),设置 x-ai-eg-model 等路由标头,并在需要时在 API schema 之间进行转换。
准备工作
在继续部署之前,请确保您的环境满足所有必要的前提条件,并且所需的命令行实用程序已正确配置。在工作站上设置这些工具对于管理 Container Registry、与集群交互以及自动执行部署流程至关重要。
- GDC 网闸隔离配置 1.16.2-hf1 或更高版本环境可与运行 Kubernetes v1.32.13-gke.400 或更高版本的标准集群搭配使用。
- 已创建具有充足资源的标准集群。网关组件仅在 CPU 上运行;模型部署后端有自己的加速器要求(请参阅在 GDC 网闸隔离配置上运行开放权重模型指南)。
- Harbor 实例可用且可访问。
- 已应用必要的 IAM。
- 与环境和互联网具有必要连接的工作站
环境配置
环境配置涵盖身份和权限、工作站以及对 GDC 环境和集群的访问权限。
Identity and Access Management
确保已正确配置必要的 IAM 账号、角色和权限。
项目上的 GDC 用户角色(项目命名空间中的 RoleBinding,由 IAM 项目管理员授予):
- Harbor Instance Viewer (
harbor-instance-viewer) - Harbor Project Creator(
harbor-project-creator,仅当 Harbor 项目尚不存在时) - 标准集群管理员(
standard-cluster-admin,gdcloud clusters get-credentials必需)
标准集群上的 GDC 用户角色:上述项目角色不会授予集群内的任何权限。项目 IAM 管理员还必须在管理 API 服务器上的项目命名空间中,使用 StandardClusterRoleBinding 将用户绑定到 StandardClusterRole cluster-admin;绑定会在几秒钟内传播到项目的标准集群(status.clusters[].conditions 显示 Propagated=True)。由于本指南会安装自定义资源定义、ClusterRole 和 GatewayClass,因此需要集群级权限。
cat <<EOF | kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f -
apiVersion: iam.gdc.goog/v1
kind: StandardClusterRoleBinding
metadata:
name: user-USER-cluster-admin
namespace: PROJECT
spec:
roleRef:
apiGroup: iam.gdc.goog
kind: StandardClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: USER
EOF
替换以下内容:
MANAGEMENT_API_SERVER:管理 API 服务器 kubeconfig 文件的路径。USER:用户。PROJECT:项目。
Harbor crane (crane) 机器人账号权限:
- 列出代码库
- 拉取代码库
- 推送代码库
- 读取制品
- 列出制品
- 创建标记
- 列表代码
Harbor Kubernetes 映像拉取 (kubernetes-image-puller) 机器人账号权限:
- 列出代码库
- 拉取代码库
- 读取制品
- 列出制品
- 列表代码
工作站
除非某个步骤另有说明,否则请在具有所需工具且可连接到环境和互联网的工作站上运行本指南中的所有命令。
要求
工作站上需要安装以下工具:
crane:在注册表之间管理和复制容器映像和 OCI 工件(文档)。gdcloud:用于管理 GDC 资源的命令行界面 (CLI)(文档)。kubectl:用于与 Kubernetes 集群通信和管理 Kubernetes 集群的命令行界面 (CLI)。helm:Kubernetes 的软件包管理器,版本 3.8 或更高版本(OCI 注册表支持)(文档)。curl:用于通过网址传输数据的命令行工具。jq:轻量级且灵活的命令行 JSON 处理器。yq:可移植的命令行 YAML 处理器。
除非某个步骤另有说明,否则请从工作站运行本指南中的所有命令。
工作站配置
工作站配置需要以下有关环境的信息:
GDC_STANDARD_CLUSTER_NAME:GDC 标准集群的名称。GDC_DOMAIN_SUFFIX:GDC 环境的域名后缀(例如gdc.example.com)。GDC_ORG:GDC 组织的名称。GDC_PROJECT:GDC 项目的名称。GDC_ZONE:GDC 部署可用区的名称。GDC_HARBOR_INSTANCE_NAME:项目中 Harbor 实例的名称。GDCS_HARBOR_PROJECT_NAME:要用于映像的 Harbor 项目的名称(默认:solutions)GDCS_HARBOR_CRANE_ROBOT_NAME:Harborcrane机器人账号的名称。GDCS_HARBOR_CRANE_ROBOT_TOKEN:Harborcrane机器人账号的身份验证令牌。GDCS_HARBOR_K8S_ROBOT_NAME:Harbor Kubernetes 映像拉取机器人账号的名称。GDCS_HARBOR_K8S_ROBOT_TOKEN:Harbor Kubernetes 映像拉取机器人账号的身份验证令牌。
收集完所有必需变量的值后,继续生成环境变量文件。创建后,您可以随时手动修改该文件。
创建根解决方案目录和密钥文件夹:
mkdir -p ${HOME}/gdcag-solutions/env.d mkdir -p ${HOME}/gdcag-solutions/secrets touch ${HOME}/gdcag-solutions/secrets/harbor_crane_robot_token touch ${HOME}/gdcag-solutions/secrets/harbor_k8s_robot_token chmod u=rwx,go= ${HOME}/gdcag-solutions/secrets chmod -R u=rw,go= ${HOME}/gdcag-solutions/secrets/*创建平台环境配置文件:
cat << 'EOF' > ${HOME}/gdcag-solutions/env.d/platform.sh && echo "Successfully created." || echo "Failed to create!" # Infrastructure (Platform Native) export GDC_STANDARD_CLUSTER_NAME="STANDARD_CLUSTER_NAME" export GDC_DOMAIN_SUFFIX="DOMAIN_SUFFIX" export GDC_ORG="ORG" export GDC_PROJECT="PROJECT" export GDC_ZONE="ZONE" export GDC_HARBOR_INSTANCE_NAME="HARBOR_INSTANCE_NAME" # Derived platform values export GDC_ZONAL_HOSTNAME="${GDC_ORG}.${GDC_ZONE}.${GDC_DOMAIN_SUFFIX}" export GDC_ZONAL_CONSOLE_URL="https://console.${GDC_ZONAL_HOSTNAME}" export GDC_HARBOR_HOST="${GDC_HARBOR_INSTANCE_NAME}-${GDC_PROJECT}.${GDC_ORG}.${GDC_ZONE}.${GDC_DOMAIN_SUFFIX}" EOF替换以下内容:
STANDARD_CLUSTER_NAME:GDC 标准集群名称。DOMAIN_SUFFIX:GDC 域名后缀。ORG:GDC 组织。PROJECT:GDC 项目。ZONE:GDC 可用区。HARBOR_INSTANCE_NAME:GDC Harbor 实例名称。
创建注册表环境配置文件:
cat << 'EOF' > ${HOME}/gdcag-solutions/env.d/registry.sh && echo "Successfully created." || echo "Failed to create!" # GDC Solutions Registry & Secrets export GDCS_HARBOR_PROJECT_NAME="solutions" export GDCS_HARBOR_CRANE_ROBOT_NAME="HARBOR_CRANE_ROBOT_NAME" export GDCS_HARBOR_CRANE_ROBOT_TOKEN="$(cat ${GDCS_ROOT_HOME}/secrets/harbor_crane_robot_token)" export GDCS_HARBOR_K8S_ROBOT_NAME="HARBOR_K8S_ROBOT_NAME" export GDCS_HARBOR_K8S_ROBOT_TOKEN="$(cat ${GDCS_ROOT_HOME}/secrets/harbor_k8s_robot_token)" export GDCS_HARBOR_K8S_PULL_SECRET="gdcs-image-pull-secret" # Derived registry values export GDCS_HARBOR_PROJECT_URI="${GDC_HARBOR_HOST}/${GDCS_HARBOR_PROJECT_NAME}" export GDCS_HARBOR_CHART_OCI_URI="oci://${GDCS_HARBOR_PROJECT_URI}" EOF替换以下内容:
HARBOR_CRANE_ROBOT_NAME:GDC Harbor 机器人账号名称。HARBOR_K8S_ROBOT_NAME:GDC Harbor 机器人账号名称。
将令牌添加到 Secret 文件中:
set +o history echo "CRANE_ROBOT_TOKEN" > ${HOME}/gdcag-solutions/secrets/harbor_crane_robot_token echo "KUBERNETES_ROBOT_TOKEN" > ${HOME}/gdcag-solutions/secrets/harbor_k8s_robot_token set -o history替换以下内容:
CRANE_ROBOT_TOKEN:吊车机器人令牌。KUBERNETES_ROBOT_TOKEN:Kubernetes 机器人令牌。
创建根环境加载器文件:
cat << 'EOF' > ${HOME}/gdcag-solutions/env.sh && echo "Successfully created." || echo "Failed to create!" export GDCS_ROOT_HOME="${HOME}/gdcag-solutions" echo "GDCS_ROOT_HOME=${GDCS_ROOT_HOME}" # Sourced in dependency order source "${GDCS_ROOT_HOME}/env.d/platform.sh" source "${GDCS_ROOT_HOME}/env.d/registry.sh" EOF
配置解决方案变量
创建解决方案实现目录:
mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.d创建解决方案环境配置文件:
cat << 'EOF' > ${HOME}/gdcag-solutions/ai-gateway/envoy/env.d/envoy.sh && echo "Successfully created." || echo "Failed to create!" # Envoy Gateway export GDCS_ENVOY_GATEWAY_NAMESPACE="envoy-gateway-system" export GDCS_ENVOY_GATEWAY_VERSION="v1.8.5" export GDCS_ENVOY_PROXY_IMAGE_TAG="distroless-v1.38.4" export GDCS_ENVOY_RATELIMIT_IMAGE_TAG="8fe6ea42" export GDCS_GATEWAY_API_ECHO_IMAGE_TAG="v1.5.1" # Envoy Agent Router (formerly Envoy AI Gateway; the images and charts keep the ai-gateway names) export GDCS_ENVOY_AGENT_ROUTER_NAMESPACE="envoy-ai-gateway-system" export GDCS_ENVOY_AGENT_ROUTER_VERSION="v1.1.0" # Gateway API Inference Extension (InferencePool, Endpoint Picker) export GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION="v1.5.0" # Redis (token-based rate limiting backend) export GDCS_REDIS_IMAGE_TAG="8.10.2-alpine3.23" export GDCS_REDIS_NAMESPACE="${GDCS_ENVOY_GATEWAY_NAMESPACE}" # Gateway class shared by the user guides export GDCS_GATEWAY_CLASS_NAME="envoy-ai-gateway" # Docker configuration directories for crane and Kubernetes export GDCS_HARBOR_CRANE_DOCKER_CONFIG="${GDCS_IMPLEMENTATION_HOME}/docker/crane" export GDCS_HARBOR_K8S_DOCKER_CONFIG="${GDCS_IMPLEMENTATION_HOME}/docker/k8s" EOF创建实现环境加载器文件:
cat << 'EOF' > ${HOME}/gdcag-solutions/ai-gateway/envoy/env.sh && echo "Successfully created." || echo "Failed to create!" source "${HOME}/gdcag-solutions/env.sh" export GDCS_IMPLEMENTATION_HOME="${HOME}/gdcag-solutions/ai-gateway/envoy" echo "GDCS_IMPLEMENTATION_HOME=${GDCS_IMPLEMENTATION_HOME}" # Sourced in dependency order source "${GDCS_IMPLEMENTATION_HOME}/env.d/envoy.sh" EOF使用您首选的编辑器修改和查看环境文件:
${EDITOR:-vi} ${HOME}/gdcag-solutions/env.d/platform.sh ${EDITOR:-vi} ${HOME}/gdcag-solutions/env.d/registry.sh ${EDITOR:-vi} ${HOME}/gdcag-solutions/ai-gateway/envoy/env.d/envoy.sh获取环境文件:
source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.sh输出类似于以下内容:
GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
GDC
本指南假定您的工作站已配置为信任 GDC 环境和 Harbor 实例的 TLS 证书。
配置
gdcloud:gdcloud config set core/account "default-user" gdcloud config set core/organization_console_url "${GDC_ZONAL_CONSOLE_URL}" gdcloud config set core/project "${GDC_PROJECT}" gdcloud config set core/zone "${GDC_ZONE}"向 GDC 环境进行身份验证:
gdcloud auth login
集群
检索集群凭据:
gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \ --project="${GDC_PROJECT}" \ --standard \ --zone="${GDC_ZONE}"验证与集群的连接:
kubectl get nodes -L node.cluster.private.gdc.goog/machine-class
制品迁移准备工作
为 crane 创建 Docker 配置文件。机器人账号用于推送大型映像层,以避免在使用托管 Harbor 服务 (MHS) 凭据辅助程序 (docker-credential-mhs) 和用户账号时出现身份验证令牌超时:
set +o history export DOCKER_CONFIG="${GDCS_HARBOR_CRANE_DOCKER_CONFIG}" crane auth login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_CRANE_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_CRANE_ROBOT_NAME}" set -o history为 Kubernetes 创建 Docker 配置文件:
set +o history export DOCKER_CONFIG="${GDCS_HARBOR_K8S_DOCKER_CONFIG}" crane auth login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_K8S_ROBOT_NAME}" set -o history使用 Kubernetes 映像拉取机器人账号通过
helm登录 Harbor OCI 注册表。helm会保留自己的注册表凭据,并且需要这些凭据才能从 Harbor 提取图表:set +o history helm registry login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_K8S_ROBOT_NAME}" set -o history输出类似于以下内容:
Login Succeeded创建
seed_registry.sh脚本:cat << 'EOF' > ${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh && echo "Successfully created." || echo "Failed to create!" #!/bin/bash # seed_registry.sh: Modular artifact migration for GDC Solutions # Requires the env.sh file to be sourced first. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" set -o nounset source "${SCRIPT_DIR}/env.sh" # Set the Docker config export DOCKER_CONFIG="${GDCS_HARBOR_CRANE_DOCKER_CONFIG}" eval "${SERIALIZED_IMAGES}" # Ensure GDCS_REGISTRY_IMAGES is set if [[ ${#GDCS_REGISTRY_IMAGES[@]} -eq 0 ]]; then echo "GDCS_REGISTRY_IMAGES must be set, exiting..." exit 1 fi # Migrate the images for source_image in "${GDCS_REGISTRY_IMAGES[@]}"; do # Strip the registry host only when the first path segment is a host (contains a dot or a port) first_segment="${source_image%%/*}" if [[ "${first_segment}" == *.* || "${first_segment}" == *:* ]]; then image_path="${source_image#*/}" else image_path="${source_image}" fi destination_image="${GDCS_HARBOR_PROJECT_URI}/${image_path}" # Ensure the folder structure is created crane append \ --new_layer=<(tar czf - -T /dev/null) \ --new_tag="${destination_image%:*}:create" \ --oci-empty-base 2> /dev/null || true # Copy the linux/amd64 platform only to avoid transferring multi-arch layers over air-gapped links crane copy --platform linux/amd64 "${source_image}" "${destination_image}" 2> /dev/null done echo "Migration complete: Images are available at ${GDCS_HARBOR_PROJECT_URI}" EOF chmod u+x "${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh"创建
seed_charts.sh脚本。作为 OCI 工件发布的 Helm 图表也会通过crane进行复制,无需选择平台,也无需使用容器映像代码库所用的create标记:cat << 'EOF' > ${GDCS_IMPLEMENTATION_HOME}/seed_charts.sh && echo "Successfully created." || echo "Failed to create!" #!/bin/bash # seed_charts.sh: OCI Helm chart migration for GDC Solutions # Requires the env.sh file to be sourced first. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" set -o nounset source "${SCRIPT_DIR}/env.sh" # Set the Docker config export DOCKER_CONFIG="${GDCS_HARBOR_CRANE_DOCKER_CONFIG}" eval "${SERIALIZED_CHARTS}" # Ensure GDCS_REGISTRY_CHARTS is set if [[ ${#GDCS_REGISTRY_CHARTS[@]} -eq 0 ]]; then echo "GDCS_REGISTRY_CHARTS must be set, exiting..." exit 1 fi # Migrate the charts (source format: REGISTRY_HOST/REPOSITORY:CHART_VERSION) for source_chart in "${GDCS_REGISTRY_CHARTS[@]}"; do chart_path="${source_chart#*/}" destination_chart="${GDCS_HARBOR_PROJECT_URI}/${chart_path}" crane copy "${source_chart}" "${destination_chart}" || { echo "Failed to copy ${source_chart} to ${destination_chart}"; exit 1; } done echo "Migration complete: Charts are available at ${GDCS_HARBOR_CHART_OCI_URI}" EOF chmod u+x "${GDCS_IMPLEMENTATION_HOME}/seed_charts.sh"替换以下内容:
REGISTRY_HOST:注册表主机。REPOSITORY:代码库。CHART_VERSION:图表版本。
定义解决方案所需的容器映像列表:
declare -a GDCS_REGISTRY_IMAGES=( "docker.io/envoyproxy/gateway:${GDCS_ENVOY_GATEWAY_VERSION}" "docker.io/envoyproxy/envoy:${GDCS_ENVOY_PROXY_IMAGE_TAG}" "docker.io/envoyproxy/ratelimit:${GDCS_ENVOY_RATELIMIT_IMAGE_TAG}" "docker.io/envoyproxy/ai-gateway-controller:${GDCS_ENVOY_AGENT_ROUTER_VERSION}" "docker.io/envoyproxy/ai-gateway-extproc:${GDCS_ENVOY_AGENT_ROUTER_VERSION}" "docker.io/envoyproxy/ai-gateway-testupstream:${GDCS_ENVOY_AGENT_ROUTER_VERSION}" "docker.io/library/redis:${GDCS_REDIS_IMAGE_TAG}" "registry.k8s.io/gateway-api/echo-basic:${GDCS_GATEWAY_API_ECHO_IMAGE_TAG}" ) export SERIALIZED_IMAGES=$(declare -p GDCS_REGISTRY_IMAGES)将所需的容器映像植入到制品库:
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
定义解决方案所需的 Helm 图表列表:
declare -a GDCS_REGISTRY_CHARTS=( "docker.io/envoyproxy/gateway-crds-helm:${GDCS_ENVOY_GATEWAY_VERSION}" "docker.io/envoyproxy/gateway-helm:${GDCS_ENVOY_GATEWAY_VERSION}" "docker.io/envoyproxy/ai-gateway-crds-helm:${GDCS_ENVOY_AGENT_ROUTER_VERSION}" "docker.io/envoyproxy/ai-gateway-helm:${GDCS_ENVOY_AGENT_ROUTER_VERSION}" ) export SERIALIZED_CHARTS=$(declare -p GDCS_REGISTRY_CHARTS)将所需的 Helm 图表植入到制品库:
${GDCS_IMPLEMENTATION_HOME}/seed_charts.sh验证是否可以从 Harbor 读回图表:
helm show chart "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/gateway-helm" --version "${GDCS_ENVOY_GATEWAY_VERSION}" | grep -E '^(name|version):' helm show chart "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/ai-gateway-helm" --version "${GDCS_ENVOY_AGENT_ROUTER_VERSION}" | grep -E '^(name|version):'输出类似于以下内容:
name: gateway-helm version: v1.8.5 name: ai-gateway-helm version: v1.1.0下载 Gateway API 推理扩展程序清单。它们作为发布资产(而非图表)发布:
mkdir -p "${GDCS_IMPLEMENTATION_HOME}/manifests" curl --fail --location --show-error --silent \ --output "${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml" \ "https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}/manifests.yaml" grep --count '^kind: CustomResourceDefinition' "${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"输出类似于以下内容:
4
Envoy Gateway
首先安装 Envoy Gateway,并使用上游快速入门自行验证;下一部分将介绍 Envoy Agent Router 集成。
命名空间
为 Envoy Gateway 创建命名空间。每个
Gateway的 Envoy 代理Deployment也会在此命名空间中创建:kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"添加
imagePullSecret:kubectl create secret docker-registry "${GDCS_HARBOR_K8S_PULL_SECRET}" \ --dry-run=client \ --from-file=.dockerconfigjson=${GDCS_HARBOR_K8S_DOCKER_CONFIG}/config.json \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=yaml | kubectl apply -f -
自定义资源定义
从种子图表中安装 Gateway API(标准渠道)和 Envoy Gateway 自定义资源定义 (CRD):
helm template eg-crds "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/gateway-crds-helm" \ --set crds.gatewayAPI.channel=standard \ --set crds.gatewayAPI.enabled=true \ --set crds.envoyGateway.enabled=true \ --version "${GDCS_ENVOY_GATEWAY_VERSION}" | kubectl apply --server-side --filename=-验证 CRD 是否已注册:
kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
控制器
为 Envoy Gateway 创建 Helm 值文件。这些映像是使用映像拉取密钥
crds.enabled=false从 Harbor 中拉取的,因为 CRD 是单独安装的:cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-values.yaml" && echo "Successfully created." || echo "Failed to create!" config: envoyGateway: extensionApis: enableBackend: true enableEnvoyPatchPolicy: true gateway: controllerName: gateway.envoyproxy.io/gatewayclass-controller logging: level: default: info provider: type: Kubernetes crds: enabled: false global: imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} imageRegistry: ${GDCS_HARBOR_PROJECT_URI} images: envoyProxy: image: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/envoy:${GDCS_ENVOY_PROXY_IMAGE_TAG} pullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} EOF安装 Envoy Gateway:
helm upgrade --install eg "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/gateway-helm" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --values="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-values.yaml" \ --version="${GDCS_ENVOY_GATEWAY_VERSION}"等待 Envoy Gateway 控制器变为“Available”(可用):
watch --color --interval 5 --no-title \ "kubectl get deployment/envoy-gateway \ --namespace=${GDCS_ENVOY_GATEWAY_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e '1/1 1 1'"验证控制器及其证书生成作业的映像是否来自 Harbor:
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Envoy 代理和 Gateway 类
为
EnvoyProxy数据平面模板和GatewayClass创建清单。EnvoyProxy设置代理映像、映像拉取密钥和代理Pod的资源请求;GatewayClass由用户指南共享:cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml" && echo "Successfully created." || echo "Failed to create!" apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: ${GDCS_GATEWAY_CLASS_NAME} namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE} spec: provider: type: Kubernetes kubernetes: envoyDeployment: container: image: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/envoy:${GDCS_ENVOY_PROXY_IMAGE_TAG} resources: limits: memory: 2Gi requests: cpu: 250m memory: 512Mi pod: imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} --- apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: ${GDCS_GATEWAY_CLASS_NAME} spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller parametersRef: group: gateway.envoyproxy.io kind: EnvoyProxy name: ${GDCS_GATEWAY_CLASS_NAME} namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE} EOF应用
EnvoyProxy和GatewayClass的清单:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"验证
GatewayClass是否已接受:kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"输出类似于以下内容:
NAME CONTROLLER ACCEPTED AGE envoy-ai-gateway gateway.envoyproxy.io/gatewayclass-controller True 5s
验证
验证会将 Envoy Gateway 快速入门(HTTPRoute 后面的 echo 后端)部署到 Envoy Gateway 命名空间中,并在之后将其移除。
为快速入门工作负载创建清单:
cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" && echo "Successfully created." || echo "Failed to create!" apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: eg-quickstart spec: gatewayClassName: ${GDCS_GATEWAY_CLASS_NAME} listeners: - name: http protocol: HTTP port: 80 --- apiVersion: v1 kind: ServiceAccount metadata: name: eg-quickstart-backend --- apiVersion: v1 kind: Service metadata: name: eg-quickstart-backend labels: app: eg-quickstart-backend spec: ports: - name: http port: 3000 targetPort: 3000 selector: app: eg-quickstart-backend --- apiVersion: apps/v1 kind: Deployment metadata: name: eg-quickstart-backend spec: replicas: 1 selector: matchLabels: app: eg-quickstart-backend template: metadata: labels: app: eg-quickstart-backend spec: serviceAccountName: eg-quickstart-backend containers: - image: ${GDCS_HARBOR_PROJECT_URI}/gateway-api/echo-basic:${GDCS_GATEWAY_API_ECHO_IMAGE_TAG} imagePullPolicy: IfNotPresent name: backend ports: - containerPort: 3000 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: eg-quickstart-backend spec: parentRefs: - name: eg-quickstart hostnames: - "www.example.com" rules: - backendRefs: - group: "" kind: Service name: eg-quickstart-backend port: 3000 weight: 1 matches: - path: type: PathPrefix value: / EOF应用快速入门工作负载的清单:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"等待
Gateway编程完成:watch --color --interval 5 --no-title \ "kubectl get gateway/eg-quickstart \ --namespace=${GDCS_ENVOY_GATEWAY_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e 'True'"等待后端
Deployment变为可用状态:watch --color --interval 5 --no-title \ "kubectl get deployment/eg-quickstart-backend \ --namespace=${GDCS_ENVOY_GATEWAY_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e '1/1 1 1'"使用端口转发通过网关发送测试请求。
Gateway的 EnvoyService通过其所属网关标签找到:export ENVOY_SERVICE=$(kubectl get service --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" --selector="gateway.envoyproxy.io/owning-gateway-namespace=${GDCS_ENVOY_GATEWAY_NAMESPACE},gateway.envoyproxy.io/owning-gateway-name=eg-quickstart" --output=jsonpath='{.items[0].metadata.name}') echo "ENVOY_SERVICE=${ENVOY_SERVICE}" kubectl port-forward "service/${ENVOY_SERVICE}" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" 8888:80 & PF_PID=$! sleep 2 curl --header "Host: www.example.com" \ --no-progress-meter \ --show-error \ http://127.0.0.1:8888/get | jq kill -9 ${PF_PID}输出类似于以下内容:
{ "path": "/get", "host": "www.example.com", "method": "GET", ... "namespace": "envoy-gateway-system", "pod": "eg-quickstart-backend-...", ... }移除快速入门工作负载:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
Envoy 代理路由器
Envoy Agent Router 会安装到其自己的命名空间中;然后,Envoy Gateway 会重新配置为将其作为扩展服务器进行调用。
命名空间
为 Envoy Agent Router 控制器创建命名空间:
kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"添加
imagePullSecret:kubectl create secret docker-registry "${GDCS_HARBOR_K8S_PULL_SECRET}" \ --dry-run=client \ --from-file=.dockerconfigjson=${GDCS_HARBOR_K8S_DOCKER_CONFIG}/config.json \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}" \ --output=yaml | kubectl apply -f -
自定义资源定义
从种子图表安装 Envoy Agent Router CRD:
helm template aieg-crds "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/ai-gateway-crds-helm" \ --version "${GDCS_ENVOY_AGENT_ROUTER_VERSION}" | kubectl apply --server-side --filename=-通过下载的清单安装 Gateway API 推理扩展程序 CRD(
InferencePool、InferenceObjective):kubectl apply --server-side \ --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"验证 CRD 是否已注册:
kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'输出类似于以下内容:
aigatewayroutes.aigateway.envoyproxy.io ... aiservicebackends.aigateway.envoyproxy.io ... backendsecuritypolicies.aigateway.envoyproxy.io ... gatewayconfigs.aigateway.envoyproxy.io ... inferencemodelrewrites.inference.networking.x-k8s.io ... inferenceobjectives.inference.networking.x-k8s.io ... inferencepoolimports.inference.networking.x-k8s.io ... inferencepools.inference.networking.k8s.io ... mcproutes.aigateway.envoyproxy.io ... quotapolicies.aigateway.envoyproxy.io ...
Redis
基于令牌的速率限制由 Envoy 速率限制服务强制执行,该服务将其计数器存储在 Redis 中。本指南部署了一个没有持久性的单副本 Redis;您也可以通过更改下一部分中的 rateLimit.backend.redis.url 值来改用现有 Redis 服务。
为 Redis
Deployment创建清单:cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/redis.yaml" && echo "Successfully created." || echo "Failed to create!" apiVersion: v1 kind: Service metadata: name: redis labels: app: redis spec: ports: - name: redis port: 6379 selector: app: redis --- apiVersion: apps/v1 kind: Deployment metadata: name: redis spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - image: ${GDCS_HARBOR_PROJECT_URI}/library/redis:${GDCS_REDIS_IMAGE_TAG} imagePullPolicy: IfNotPresent name: redis ports: - name: redis containerPort: 6379 resources: limits: memory: 512Mi requests: cpu: 100m memory: 128Mi imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} restartPolicy: Always EOF应用 Redis
Deployment的清单:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"等待 Redis
Deployment变为可用状态:watch --color --interval 5 --no-title \ "kubectl get deployment/redis \ --namespace=${GDCS_REDIS_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e '1/1 1 1'"
控制器
为 Envoy 代理路由器创建 Helm 值文件:
cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-agent-router-values.yaml" && echo "Successfully created." || echo "Failed to create!" controller: image: repository: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/ai-gateway-controller imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} envoyGateway: namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE} extProc: image: repository: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/ai-gateway-extproc imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} global: imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} EOF安装 Envoy Agent Router:
helm upgrade --install aieg "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/ai-gateway-helm" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}" \ --values="${GDCS_IMPLEMENTATION_HOME}/envoy-agent-router-values.yaml" \ --version="${GDCS_ENVOY_AGENT_ROUTER_VERSION}"等待 Envoy Agent Router 控制器变为可用状态:
watch --color --interval 5 --no-title \ "kubectl get deployment/ai-gateway-controller \ --namespace=${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e '1/1 1 1'"
Envoy Gateway 集成
必须重新配置 Envoy Gateway,以调用 Envoy Agent Router 控制器作为其扩展服务器,接受 InferencePool 资源作为后端,并使用 Redis 支持的速率限制服务。
为集成创建 Helm 值文件:
cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-agent-router-values.yaml" && echo "Successfully created." || echo "Failed to create!" config: envoyGateway: extensionManager: backendResources: - group: inference.networking.k8s.io kind: InferencePool version: v1 hooks: xdsTranslator: post: - Translation - Cluster - Route translation: cluster: includeAll: true listener: includeAll: true route: includeAll: true secret: includeAll: true service: fqdn: hostname: ai-gateway-controller.${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}.svc.cluster.local port: 1063 rateLimit: backend: redis: url: redis.${GDCS_REDIS_NAMESPACE}.svc.cluster.local:6379 type: Redis EOF使用这两个值文件升级 Envoy Gateway:
helm upgrade --install eg "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/gateway-helm" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --values="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-values.yaml" \ --values="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-agent-router-values.yaml" \ --version="${GDCS_ENVOY_GATEWAY_VERSION}"为
ClusterRole创建清单,以便 Envoy Gateway 控制器监控InferencePool资源。该图表不会授予此权限;与图表管理的ClusterRole的补丁不同,单独的ClusterRoleBinding在图表升级后仍然存在:cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml" && echo "Successfully created." || echo "Failed to create!" apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: envoy-gateway-inferencepool-reader rules: - apiGroups: - inference.networking.k8s.io resources: - inferencepools verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: envoy-gateway-inferencepool-reader roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: envoy-gateway-inferencepool-reader subjects: - kind: ServiceAccount name: envoy-gateway namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE} EOF应用
ClusterRole的清单:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"重启 Envoy Gateway 控制器,使其获取新的配置和权限,然后等待其变为“可用”状态:
kubectl rollout restart deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" kubectl rollout status deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --timeout=5m验证速率限制服务是否已部署且可用:
watch --color --interval 5 --no-title \ "kubectl get deployment/envoy-ratelimit \ --namespace=${GDCS_ENVOY_GATEWAY_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e '1/1 1 1'"
验证
验证过程会将 Envoy Agent Router 基本示例(AIGatewayRoute 后面的模拟 OpenAI 兼容上游)部署到 Envoy Agent Router 命名空间中,并在验证后将其移除。
为验证工作负载创建清单:
cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" && echo "Successfully created." || echo "Failed to create!" apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: aieg-basic spec: gatewayClassName: ${GDCS_GATEWAY_CLASS_NAME} listeners: - name: http protocol: HTTP port: 80 --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: ClientTrafficPolicy metadata: name: aieg-basic-buffer-limit spec: targetRefs: - group: gateway.networking.k8s.io kind: Gateway name: aieg-basic connection: bufferLimit: 50Mi --- apiVersion: aigateway.envoyproxy.io/v1beta1 kind: AIGatewayRoute metadata: name: aieg-basic spec: parentRefs: - name: aieg-basic kind: Gateway group: gateway.networking.k8s.io rules: - matches: - headers: - type: Exact name: x-ai-eg-model value: some-cool-self-hosted-model backendRefs: - name: aieg-basic-testupstream --- apiVersion: aigateway.envoyproxy.io/v1beta1 kind: AIServiceBackend metadata: name: aieg-basic-testupstream spec: schema: name: OpenAI backendRef: name: aieg-basic-testupstream kind: Backend group: gateway.envoyproxy.io --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: Backend metadata: name: aieg-basic-testupstream spec: endpoints: - fqdn: hostname: aieg-basic-testupstream.${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}.svc.cluster.local port: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: aieg-basic-testupstream spec: replicas: 1 selector: matchLabels: app: aieg-basic-testupstream template: metadata: labels: app: aieg-basic-testupstream spec: containers: - name: testupstream image: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/ai-gateway-testupstream:${GDCS_ENVOY_AGENT_ROUTER_VERSION} imagePullPolicy: IfNotPresent ports: - containerPort: 8080 env: - name: TESTUPSTREAM_ID value: test readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 20 imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} --- apiVersion: v1 kind: Service metadata: name: aieg-basic-testupstream spec: selector: app: aieg-basic-testupstream ports: - protocol: TCP port: 80 targetPort: 8080 type: ClusterIP EOF应用验证工作负载的清单:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"等待
Gateway编程完成:watch --color --interval 5 --no-title \ "kubectl get gateway/aieg-basic \ --namespace=${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e 'True'"等待模拟上游
Deployment变为可用状态:watch --color --interval 5 --no-title \ "kubectl get deployment/aieg-basic-testupstream \ --namespace=${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} | GREP_COLORS='mt=01;92' egrep --color=always -e '^' -e '1/1 1 1'"验证
Gateway的 Envoy 代理Pod是否运行由 Envoy Agent Router 注入的外部处理器 Sidecar:kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --selector="gateway.envoyproxy.io/owning-gateway-name=aieg-basic" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'输出类似于以下内容:
envoy-envoy-ai-gateway-system-aieg-basic-... envoy shutdown-manager ai-gateway-extproc使用端口转发通过网关发送对话补全请求。 外部处理器读取请求正文的
model字段,并将其路由到模拟上游:export ENVOY_SERVICE=$(kubectl get service --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" --selector="gateway.envoyproxy.io/owning-gateway-namespace=${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE},gateway.envoyproxy.io/owning-gateway-name=aieg-basic" --output=jsonpath='{.items[0].metadata.name}') echo "ENVOY_SERVICE=${ENVOY_SERVICE}" kubectl port-forward "service/${ENVOY_SERVICE}" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" 8888:80 & PF_PID=$! sleep 2 curl http://127.0.0.1:8888/v1/chat/completions \ --data '{"model": "some-cool-self-hosted-model", "messages": [{"role": "user", "content": "Say this is a test."}]}' \ --header "Content-Type: application/json" \ --no-progress-meter \ --show-error | jq kill -9 ${PF_PID}输出类似于以下内容:
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { ... } }移除验证工作负载:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
操作
网关控制平面的日常任务。
升级
- 为新版本的映像和图表设定种子(更新
env.sh中的版本变量,重新运行seed_registry.sh和seed_charts.sh),使用kubectl apply --server-side应用新的 CRD 图表,然后使用新的--version运行相同的helm upgrade --install命令。查看 Envoy 代理路由器兼容性矩阵,了解目标版本支持的 Envoy Gateway 和 Gateway API 版本;Envoy 代理路由器 1.1.0 是针对 Envoy Gateway 1.8 构建的。
卸载
- 首先删除用户指南的
Gateway、AIGatewayRoute和InferencePool资源,然后删除helm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"、helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"、ClusterRoleenvoy-gateway-inferencepool-reader、GatewayClass、RedisDeployment,最后删除 CRD。
问题排查
| 症状 | 可能的原因 | 操作 |
|---|---|---|
helm show chart 或 helm upgrade 失败,并显示 unauthorized 或 FetchReference |
helm 没有 Harbor 的凭据(它不使用 crane Docker 配置) |
使用 Kubernetes 映像拉取机器人账号再次运行 helm registry login 步骤。 |
Envoy Gateway 或 Envoy Agent Router Pod 仍处于 ImagePullBackOff 阶段 |
映像未播种,或命名空间中缺少映像拉取 Secret | 检查 kubectl describe pod,将映像路径与 crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway" 进行比较,并验证 ${GDCS_ENVOY_GATEWAY_NAMESPACE} 和 ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} 中是否存在该 Secret。 |
集成后,Gateway 仍为 Programmed=False |
Envoy Gateway 控制器无法访问扩展服务器,或者在升级后未重启 | kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}";确认 service/ai-gateway-controller 存在于 ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} 中,并且列出了端口 1063;重复发布重启。 |
引用 InferencePool 的 AIGatewayRoute 不被接受 |
Envoy Gateway 缺少读取 inferencepools 的权限,或者缺少 InferencePool CRD |
验证 ClusterRoleBinding envoy-gateway-inferencepool-reader 和 inferencepools.inference.networking.k8s.io CRD;检查 forbidden 的控制器日志。 |
Chat 补全请求返回 413,或者连接因提示过大而重置 |
默认 Envoy 缓冲区限制 (32 KiB) 对于 AI 载荷而言太小 | 将具有 connection.bufferLimit(验证使用 50Mi)的 ClientTrafficPolicy 挂接到 Gateway。 |
速率限制服务 Pod 为 CrashLoopBackOff |
无法通过配置的网址访问 Redis | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}";请在集成值文件中修正 rateLimit.backend.redis.url,然后重新升级。 |