Questo documento fornisce istruzioni passo passo per il deployment di un AI Gateway negli ambienti Google Distributed Cloud (GDC) con air gap. Il gateway è costituito da Envoy Gateway, l'implementazione dell'API Gateway di Kubernetes basata sul proxy Envoy, e da Envoy Agent Router (precedentemente Envoy AI Gateway), l'estensione che trasforma Envoy Gateway in un punto di ingresso unificato compatibile con OpenAI per il traffico dei modelli linguistici di grandi dimensioni (LLM). Vengono trattati argomenti come il seeding delle immagini container e dei grafici Helm nel registry Harbor locale, l'installazione di entrambi i control plane su un cluster standard, la preparazione del backend di limitazione di frequenza facoltativo basato su token e la convalida dell'installazione con workload di esempio.
I backend di erogazione dei modelli (Ollama, vLLM) vengono implementati con il set di guide complementari Modelli open weight su GDC con air gap; la guida dell'utente Routing basato sul corpo con Envoy Agent Router mostra come instradare le richieste ai backend in base al nome del modello.
Architettura
La soluzione viene eseguita in un cluster GDC standard. Una workstation amministratore inserisce le immagini e i grafici Helm nel registry Harbor del progetto e installa i due control plane: il controller Envoy Gateway, che programma il data plane del proxy Envoy dalle risorse dell'API Gateway (GatewayClass, Gateway, HTTPRoute), e il controller Envoy Agent Router, che estende il data plane con un processore esterno (ExtProc) per il traffico AI (AIGatewayRoute, AIServiceBackend, InferencePool). I client dell'applicazione inviano richieste compatibili con OpenAI al proxy Envoy, che le indirizza ai backend di erogazione del modello o ai InferencePool. Un'istanza Redis facoltativa archivia i contatori del servizio di limitazione di frequenza di Envoy per la limitazione di frequenza basata su token.

Envoy Gateway
Envoy Gateway è un progetto open source, basato sul proxy Envoy, che semplifica l'adozione, l'utilizzo e la gestione del proxy Envoy come API Gateway Kubernetes. Implementa ed estende l'API Gateway di Kubernetes, il successore dell'API Ingress: le risorse GatewayClass e Gateway descrivono i punti di ingresso, le risorse di route come HTTPRoute descrivono il modo in cui il traffico viene abbinato e inoltrato e la progettazione orientata ai ruoli separa le responsabilità dei team di infrastruttura e di applicazione. Envoy Gateway aggiunge le proprie API di estensione, ad esempio EnvoyProxy (impostazioni del piano dati), Backend (endpoint esterni al cluster o a cui viene fatto riferimento tramite FQDN) e ClientTrafficPolicy (impostazioni di connessione come i limiti del buffer).
Router dell'agente Envoy
Envoy Agent Router (in precedenza Envoy AI Gateway) è un progetto open source che utilizza Envoy Gateway per gestire il traffico delle richieste dai client delle applicazioni ai servizi di AI generativa. Fornisce un livello unificato per il routing e la gestione del traffico LLM con routing basato sul modello, autenticazione upstream, limitazione di frequenza basata su token e osservabilità, oltre a integrarsi con l'estensione di inferenza dell'API Gateway (InferencePool, selettore di endpoint) per la selezione degli endpoint basata sulle metriche. Il controller monitora le risorse aigateway.envoyproxy.io/v1beta1 e inserisce un processore esterno accanto al proxy Envoy; il processore esterno analizza il corpo della richiesta (ad esempio il campo model di una richiesta di completamento della chat di OpenAI), imposta le intestazioni di routing come x-ai-eg-model e traduce tra gli schemi dell'API, se necessario.
Prima di iniziare
Prima di procedere con il deployment, assicurati che il tuo ambiente soddisfi tutti i prerequisiti necessari e che le utilità a riga di comando richieste siano configurate correttamente. La configurazione di questi strumenti sulla tua workstation è essenziale per gestire i Container Registry, interagire con i cluster e automatizzare il processo di deployment.
- L'ambiente GDC con air gap 1.16.2-hf1 o versioni successive è disponibile con un cluster standard che esegue Kubernetes v1.32.13-gke.400 o versioni successive.
- Cluster standard creato con risorse sufficienti. I componenti del gateway vengono eseguiti solo sulla CPU; i backend di erogazione del modello hanno i propri requisiti di acceleratore (consulta le guide sui modelli con pesi aperti su GDC con air gap).
- Istanza Harbor disponibile e accessibile.
- IAM necessario applicato.
- Workstation con la connettività necessaria all'ambiente e a internet
Configurazione dell'ambiente
La configurazione dell'ambiente riguarda le identità e le autorizzazioni, la workstation e l'accesso all'ambiente GDC e al cluster.
Identity and Access Management
Assicurati che gli account, i ruoli e le autorizzazioni IAM necessari siano configurati correttamente.
Ruoli Utente GDC sul progetto (RoleBinding nello spazio dei nomi del progetto, concessi da un amministratore IAM del progetto):
- Visualizzatore istanze Harbor (
harbor-instance-viewer) - Creatore di progetti Harbor (
harbor-project-creator, solo se il progetto Harbor non esiste ancora) - Standard Cluster Admin (
standard-cluster-admin, richiesto pergdcloud clusters get-credentials)
Ruolo Utente GDC nel cluster standard: i ruoli di progetto precedenti non concedono autorizzazioni all'interno del cluster. Un amministratore IAM del progetto deve inoltre associare l'utente al StandardClusterRole cluster-admin con un StandardClusterRoleBinding nello spazio dei nomi del progetto sul server API di gestione; l'associazione viene propagata ai cluster standard del progetto entro pochi secondi (status.clusters[].conditions mostra Propagated=True). Le autorizzazioni a livello di cluster sono necessarie perché questa guida installa definizioni di risorse personalizzate, ClusterRole e un 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
Sostituisci quanto segue:
MANAGEMENT_API_SERVER: il percorso del file kubeconfig del server API di gestione.USER: utente.PROJECT: progetto.
Autorizzazioni dell'account robot Harbor crane (crane):
- Elenco dei repository
- Repository di pull
- Repository push
- Leggi l'artefatto
- Elenca artefatto
- Crea tag
- Tag elenco
Autorizzazioni account robot Harbor Kubernetes image pull (kubernetes-image-puller):
- Elenco dei repository
- Repository di pull
- Leggi l'artefatto
- Elenca artefatto
- Tag elenco
Workstation
Esegui tutti i comandi di questa guida da una workstation con gli strumenti e la connettività necessari per l'ambiente e internet, se non diversamente indicato in un passaggio.
Requisiti
Sulla workstation devono essere installati i seguenti strumenti:
crane: gestisci e copia immagini container e artefatti OCI tra i registry (documentazione).gdcloud: interfaccia a riga di comando (CLI) per la gestione delle risorse GDC (documentazione).kubectl: interfaccia a riga di comando (CLI) utilizzata per comunicare con un cluster Kubernetes e gestirlo.helm: gestore di pacchetti per Kubernetes, versione 3.8 o successive (supporto del registry OCI) (documentazione).curl: strumento a riga di comando per il trasferimento di dati con URL.jq: processore JSON a riga di comando leggero e flessibile.yq: processore YAML portatile da riga di comando.
Esegui tutti i comandi di questa guida dalla workstation, a meno che un passaggio non indichi diversamente.
Configurazione workstation
Per la configurazione della workstation sono necessarie le seguenti informazioni sull'ambiente:
GDC_STANDARD_CLUSTER_NAME: il nome del cluster standard GDC.GDC_DOMAIN_SUFFIX: il suffisso di dominio per l'ambiente GDC (ad esempiogdc.example.com).GDC_ORG: il nome dell'organizzazione GDC.GDC_PROJECT: il nome del progetto GDC.GDC_ZONE: il nome della zona di deployment di GDC.GDC_HARBOR_INSTANCE_NAME: il nome dell'istanza Harbor nel progetto.GDCS_HARBOR_PROJECT_NAME: il nome del progetto Harbor da utilizzare per l'immagine (valore predefinito:solutions)GDCS_HARBOR_CRANE_ROBOT_NAME: il nome dell'account robot Harborcrane.GDCS_HARBOR_CRANE_ROBOT_TOKEN: il token di autenticazione per l'account robot Harborcrane.GDCS_HARBOR_K8S_ROBOT_NAME: il nome dell'account robot di pull delle immagini Kubernetes di Harbor.GDCS_HARBOR_K8S_ROBOT_TOKEN: il token di autenticazione per l'account robot di pull delle immagini Kubernetes di Harbor.
Una volta raccolti i valori per tutte le variabili richieste, procedi con la generazione del file delle variabili di ambiente. Una volta creato, puoi modificare manualmente il file in qualsiasi momento.
Crea le directory della soluzione root e la cartella dei secret:
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/*Crea il file di configurazione dell'ambiente della piattaforma:
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}" EOFSostituisci quanto segue:
STANDARD_CLUSTER_NAME: il nome del cluster standard GDC.DOMAIN_SUFFIX: suffisso di dominio GDC.ORG: l'organizzazione GDC.PROJECT: progetto GDC.ZONE: zona GDC.HARBOR_INSTANCE_NAME: il nome dell'istanza Harbor GDC.
Crea il file di configurazione dell'ambiente del registry:
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}" EOFSostituisci quanto segue:
HARBOR_CRANE_ROBOT_NAME: il nome dell'account robot GDC Harbor.HARBOR_K8S_ROBOT_NAME: il nome dell'account robot GDC Harbor.
Aggiungi i token ai file 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 historySostituisci quanto segue:
CRANE_ROBOT_TOKEN: token del robot Crane.KUBERNETES_ROBOT_TOKEN: token del robot Kubernetes.
Crea il file del caricatore dell'ambiente root:
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
Configura le variabili della soluzione
Crea la directory di implementazione della soluzione:
mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.dCrea il file di configurazione dell'ambiente della soluzione:
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" EOFCrea il file del caricatore dell'ambiente di implementazione:
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" EOFModifica e rivedi i file dell'ambiente con il tuo editor preferito:
${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.shEsegui il sourcing del file di ambiente:
source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.shL'output è simile al seguente:
GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
GDC
Questa guida presuppone che la tua workstation sia configurata per considerare attendibili i certificati TLS per l'ambiente GDC e l'istanza Harbor.
Configura
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}"Esegui l'autenticazione nell'ambiente GDC:
gdcloud auth login
Cluster
Recupera le credenziali del cluster:
gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \ --project="${GDC_PROJECT}" \ --standard \ --zone="${GDC_ZONE}"Verifica la connettività al cluster:
kubectl get nodes -L node.cluster.private.gdc.goog/machine-class
Preparazione della migrazione degli artefatti
- Verifica la connettività e la configurazione per Artifact Registry.
Crea un file di configurazione Docker per crane. Un account robot viene utilizzato per eseguire il push di livelli di immagini di grandi dimensioni per evitare timeout dei token di autenticazione quando si utilizza l'helper per le credenziali di Managed Harbor Service (MHS) (docker-credential-mhs) con un account utente:
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 historyCrea un file di configurazione Docker per Kubernetes:
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 historyAccedi al registry Harbor OCI con
helmutilizzando l'account robot di pull delle immagini Kubernetes.helmconserva le proprie credenziali del registry e ne ha bisogno per recuperare i grafici da Harbor:set +o history helm registry login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_K8S_ROBOT_NAME}" set -o historyL'output è simile al seguente:
Login SucceededCrea lo script
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"Crea lo script
seed_charts.sh. Anche i grafici Helm pubblicati come artefatti OCI vengono copiati concrane, senza selezione della piattaforma e senza il tagcreateutilizzato per i repository di immagini container: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"Sostituisci quanto segue:
REGISTRY_HOST: l'host del registry.REPOSITORY: repository.CHART_VERSION: la versione del grafico.
Definisci l'elenco delle immagini container richieste per la soluzione:
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)Esegui il seeding delle immagini container richieste in Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
Definisci l'elenco dei grafici Helm richiesti per la soluzione:
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)Esegui il seeding dei grafici Helm richiesti in Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shVerifica che i grafici possano essere letti da 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):'L'output è simile al seguente:
name: gateway-helm version: v1.8.5 name: ai-gateway-helm version: v1.1.0Scarica i manifest dell'estensione di inferenza dell'API Gateway. Vengono pubblicati come asset di uscita, non come classifica:
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"L'output è simile al seguente:
4
Envoy Gateway
Envoy Gateway viene installato per primo e convalidato autonomamente con la guida rapida upstream; l'integrazione di Envoy Agent Router segue nella sezione successiva.
Spazio dei nomi
Crea lo spazio dei nomi per Envoy Gateway. Anche i proxy Envoy
Deploymentdi ogniGatewayvengono creati in questo spazio dei nomi:kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"Aggiungi
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 -
Definizioni di risorse personalizzate
Installa l'API Gateway (canale standard) e le CustomResourceDefinition (CRD) di Envoy Gateway dal grafico di seeding:
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=-Verifica che i CRD siano registrati:
kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
Controller
Crea il file dei valori Helm per Envoy Gateway. Le immagini vengono estratte da Harbor con il secret di pull delle immagini;
crds.enabled=falseperché i CRD sono stati installati separatamente: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} EOFInstalla 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}"Attendi che il controller Envoy Gateway sia disponibile:
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'"Verifica che le immagini del controller e il relativo job di generazione dei certificati provengano da Harbor:
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Proxy Envoy e classe Gateway
Crea il manifest per il template del piano dati
EnvoyProxye perGatewayClass.EnvoyProxyimposta l'immagine proxy, il secret di pull dell'immagine e le richieste di risorse deiPodproxy;GatewayClassè condiviso dalle guide dell'utente: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} EOFApplica il manifest per
EnvoyProxyeGatewayClass:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"Verifica che il codice
GatewayClasssia stato accettato:kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"L'output è simile al seguente:
NAME CONTROLLER ACCEPTED AGE envoy-ai-gateway gateway.envoyproxy.io/gatewayclass-controller True 5s
Convalida
La convalida esegue il deployment della guida rapida di Envoy Gateway (un backend echo dietro un HTTPRoute) nello spazio dei nomi di Envoy Gateway e lo rimuove in seguito.
Crea il manifest per il workload della guida rapida:
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: / EOFApplica il manifest per il workload della guida rapida:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"Attendi che
Gatewayvenga programmato: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'"Attendi che il backend
Deploymentsia disponibile: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'"Invia una richiesta di test tramite il gateway utilizzando il port forwarding. L'Envoy
Servicedi unGatewayviene trovato tramite le etichette del gateway proprietario: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}L'output è simile al seguente:
{ "path": "/get", "host": "www.example.com", "method": "GET", ... "namespace": "envoy-gateway-system", "pod": "eg-quickstart-backend-...", ... }Rimuovi il workload della guida rapida:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
Router dell'agente Envoy
Envoy Agent Router viene installato nel proprio spazio dei nomi; Envoy Gateway viene quindi riconfigurato per chiamarlo come server di estensione.
Spazio dei nomi
Crea lo spazio dei nomi per il controller Envoy Agent Router:
kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Aggiungi
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 -
Definizioni di risorse personalizzate
Installa i CRD di Envoy Agent Router dal grafico di seeding:
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=-Installa le CRD dell'estensione di inferenza dell'API Gateway (
InferencePool,InferenceObjective) dai manifest scaricati:kubectl apply --server-side \ --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"Verifica che i CRD siano registrati:
kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'L'output è simile al seguente:
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
La limitazione di frequenza basata su token viene applicata dal servizio di limitazione di frequenza Envoy, che archivia i contatori in Redis. Questa guida esegue il deployment di un Redis a replica singola senza persistenza; in alternativa, è possibile utilizzare un servizio Redis esistente modificando il valore rateLimit.backend.redis.url nella sezione successiva.
Crea il manifest per 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 EOFApplica il manifest per Redis
Deployment:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"Attendi che l'istanza Redis
Deploymentsia disponibile: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'"
Controller
Crea il file dei valori Helm per Envoy Agent Router:
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} EOFInstalla 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}"Attendi che il controller Envoy Agent Router sia disponibile:
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'"
Integrazione di Envoy Gateway
Envoy Gateway deve essere riconfigurato per chiamare il controller Envoy Agent Router come server di estensione, per accettare le risorse InferencePool come backend e per utilizzare il servizio di limitazione di frequenza basato su Redis.
Crea il file dei valori Helm per l'integrazione:
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 EOFEsegui l'upgrade di Envoy Gateway con entrambi i file dei valori:
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}"Crea il manifest per
ClusterRoleche consente al controller Envoy Gateway di controllare le risorseInferencePool. Il grafico non concede questa autorizzazione; unClusterRoleBindingseparato sopravvive agli upgrade del grafico, a differenza di una patch delClusterRolegestito dal grafico: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} EOFApplica il manifest per
ClusterRole:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"Riavvia il controller Envoy Gateway in modo che applichi la nuova configurazione e le nuove autorizzazioni e attendi che sia disponibile:
kubectl rollout restart deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" kubectl rollout status deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --timeout=5mVerifica che sia stato eseguito il deployment del servizio di limitazione di frequenza e che sia disponibile:
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'"
Convalida
La convalida esegue il deployment dell'esempio di base di Envoy Agent Router (un upstream fittizio compatibile con OpenAI dietro un AIGatewayRoute) nello spazio dei nomi di Envoy Agent Router e lo rimuove in seguito.
Crea il manifest per il workload di convalida:
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 EOFApplica il manifest per il workload di convalida:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Attendi che
Gatewayvenga programmato: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'"Attendi che l'upstream fittizio
Deploymentsia disponibile: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'"Verifica che il proxy Envoy
PoddiGatewayesegua il sidecar del processore esterno inserito da Envoy Agent Router: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}'L'output è simile al seguente:
envoy-envoy-ai-gateway-system-aieg-basic-... envoy shutdown-manager ai-gateway-extprocInvia una richiesta di completamento della chat tramite il gateway utilizzando il port forwarding. Il processore esterno legge il campo
modeldel corpo della richiesta e lo indirizza all'upstream fittizio: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}L'output è simile al seguente:
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { ... } }Rimuovi il workload di convalida:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
Operazioni
Attività day-2 per i control plane dei gateway.
Esegui l'upgrade
- Esegui il seeding delle immagini e dei grafici delle nuove versioni (aggiorna le variabili di versione in
env.sh, esegui nuovamenteseed_registry.sheseed_charts.sh), applica i nuovi grafici CRD conkubectl apply --server-side, quindi esegui gli stessi comandihelm upgrade --installcon il nuovo--version. Consulta la matrice di compatibilità di Envoy Agent Router per le versioni di Envoy Gateway e dell'API Gateway supportate dalla release di destinazione. Envoy Agent Router 1.1.0 è basato su Envoy Gateway 1.8.
Disinstalla
- Elimina prima le risorse
Gateway,AIGatewayRouteeInferencePooldelle guide dell'utente, poihelm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}",helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}",ClusterRoleenvoy-gateway-inferencepool-reader,GatewayClass,DeploymentRedis e infine i CRD.
Risoluzione dei problemi
| Sintomo | Causa probabile | Azione |
|---|---|---|
helm show chart o helm upgrade non va a buon fine con unauthorized o FetchReference |
helm non dispone di credenziali per Harbor (non utilizza la configurazione Docker crane) |
Esegui di nuovo il passaggio helm registry login con l'account robot di pull delle immagini Kubernetes. |
Envoy Gateway o Envoy Agent Router Pod rimangono in ImagePullBackOff |
Immagine non sottoposta a seeding o secret di pull dell'immagine mancante nello spazio dei nomi | Controlla kubectl describe pod, confronta il percorso dell'immagine con crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway" e verifica che il secret esista in ${GDCS_ENVOY_GATEWAY_NAMESPACE} e ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}. |
Gateway rimane Programmed=False dopo l'integrazione |
Il controller Envoy Gateway non riesce a raggiungere il server di estensione o non è stato riavviato dopo l'upgrade | kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"; verifica che service/ai-gateway-controller esista in ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} e che la porta 1063 sia elencata; ripeti il riavvio dell'implementazione. |
AIGatewayRoute che fa riferimento a un InferencePool non è accettato |
Envoy Gateway non dispone dell'autorizzazione per leggere inferencepools oppure i CRD InferencePool non sono presenti |
Verifica la CRD ClusterRoleBinding envoy-gateway-inferencepool-reader e inferencepools.inference.networking.k8s.io; controlla i log del controller per forbidden. |
La richiesta di completamento della chat restituisce 413 o la connessione viene reimpostata per i prompt di grandi dimensioni |
Il limite predefinito del buffer di Envoy (32 KiB) è troppo piccolo per i payload AI | Collega un ClientTrafficPolicy con connection.bufferLimit (la convalida utilizza 50 Mi) a Gateway. |
Il servizio di limitazione di frequenza Pod è CrashLoopBackOff |
Redis non è raggiungibile all'URL configurato | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}"; correggi rateLimit.backend.redis.url nel file dei valori di integrazione ed esegui di nuovo l'upgrade. |
Materiali aggiuntivi
- Documentazione di Envoy Agent Router
- Note di rilascio e matrice di compatibilità di Envoy Agent Router
- Documentazione di Envoy Gateway
- API Kubernetes Gateway
- Estensione Gateway API Inference
- Crea un cluster standard | Google Distributed Cloud con air gap
Guida dell'utente per il routing basato sul corpo con Envoy Agent Router