Ce document fournit des instructions détaillées pour déployer une passerelle AI Gateway dans des environnements Google Distributed Cloud (GDC) air-gapped. La passerelle est basée sur Envoy Gateway, l'implémentation de l'API Kubernetes Gateway basée sur le proxy Envoy, et Envoy Agent Router (anciennement Envoy AI Gateway), l'extension qui transforme Envoy Gateway en point d'entrée unifié et compatible avec OpenAI pour le trafic des grands modèles de langage (LLM). Il explique comment amorcer les images de conteneur et les graphiques Helm dans le registre Harbor local, comment installer les deux plans de contrôle sur un cluster standard, comment préparer le backend facultatif de limitation du débit basée sur les jetons et comment valider l'installation avec des exemples de charges de travail.
Les backends de mise en service du modèle (Ollama, vLLM) sont déployés avec l'ensemble de guides associés Modèles Open Weight sur GDC sous air gap. Le Guide de l'utilisateur sur le routage basé sur le corps avec Envoy Agent Router montre comment acheminer les requêtes vers eux par nom de modèle.
Architecture
La solution s'exécute dans un cluster GDC standard. Une station de travail administrateur amorce les images et les graphiques Helm dans le registre Harbor du projet, et installe les deux plans de contrôle : le contrôleur Envoy Gateway, qui programme le plan de données du proxy Envoy à partir des ressources de l'API Gateway (GatewayClass, Gateway, HTTPRoute), et le contrôleur Envoy Agent Router, qui étend ce plan de données avec un processeur externe (ExtProc) pour le trafic d'IA (AIGatewayRoute, AIServiceBackend, InferencePool). Les clients d'application envoient des requêtes compatibles avec OpenAI au proxy Envoy, qui les achemine vers les backends de mise en service du modèle ou les InferencePool. Une instance Redis facultative stocke les compteurs du service de limitation du débit Envoy pour la limitation du débit basée sur les jetons.

Envoy Gateway
Envoy Gateway est un projet Open Source basé sur Envoy Proxy. Il simplifie l'adoption, l'utilisation et la gestion d'Envoy Proxy en tant que passerelle d'API Kubernetes. Elle implémente et étend l'API Kubernetes Gateway, qui succède à l'API Ingress. Les ressources GatewayClass et Gateway décrivent les points d'entrée, les ressources de route telles que HTTPRoute décrivent comment le trafic est mis en correspondance et transféré, et la conception orientée rôle sépare les responsabilités des équipes d'infrastructure et d'application. Envoy Gateway ajoute ses propres API d'extension, par exemple EnvoyProxy (paramètres du plan de données), Backend (points de terminaison en dehors du cluster ou référencés par un nom de domaine complet) et ClientTrafficPolicy (paramètres de connexion tels que les limites de mémoire tampon).
Routeur d'agent Envoy
Envoy Agent Router (anciennement Envoy AI Gateway) est un projet Open Source qui utilise Envoy Gateway pour gérer le trafic de requêtes des clients d'applications vers les services d'IA générative. Il fournit une couche unifiée pour le routage et la gestion du trafic LLM avec un routage adapté aux modèles, une authentification en amont, une limitation du débit basée sur les jetons et l'observabilité. Il s'intègre à l'extension Gateway API Inference (InferencePool, sélecteur de points de terminaison) pour la sélection de points de terminaison tenant compte des métriques. Le contrôleur surveille les ressources aigateway.envoyproxy.io/v1beta1 et injecte un processeur externe à côté du proxy Envoy. Le processeur externe analyse le corps de la requête (par exemple, le champ model d'une requête de saisie semi-automatique de chat OpenAI), définit les en-têtes de routage tels que x-ai-eg-model et effectue la traduction entre les schémas d'API si nécessaire.
Avant de commencer
Avant de procéder au déploiement, assurez-vous que votre environnement répond à toutes les conditions préalables nécessaires et que les utilitaires de ligne de commande requis sont correctement configurés. Il est essentiel de configurer ces outils sur votre station de travail pour gérer les registres de conteneurs, interagir avec les clusters et automatiser le processus de déploiement.
- L'environnement GDC sous air gap 1.16.2-hf1 ou version ultérieure est disponible avec un cluster standard exécutant Kubernetes v1.32.13-gke.400 ou version ultérieure.
- Cluster standard créé avec des ressources suffisantes. Les composants de la passerelle s'exécutent uniquement sur le processeur. Les backends de mise en service du modèle ont leurs propres exigences en matière d'accélérateur (consultez les guides Modèles Open Weight sur GDC sous air gap).
- L'instance Harbor est disponible et accessible.
- Autorisations IAM nécessaires appliquées.
- Un poste de travail disposant de la connectivité nécessaire à l'environnement et à Internet
Configuration de l'environnement
La configuration de l'environnement couvre les identités et les autorisations, le poste de travail et l'accès à l'environnement GDC et au cluster.
Identity and Access Management
Assurez-vous que les comptes, rôles et autorisations IAM nécessaires sont correctement configurés.
Rôles Utilisateur GDC sur le projet (RoleBinding dans l'espace de noms du projet, accordés par un administrateur IAM de projet) :
- Lecteur d'instance Harbor (
harbor-instance-viewer) - Créateur de projet Harbor (
harbor-project-creator, uniquement si le projet Harbor n'existe pas encore) - Administrateur de cluster standard (
standard-cluster-admin, requis pourgdcloud clusters get-credentials)
Rôle Utilisateur GDC sur le cluster standard : les rôles de projet précédents n'accordent aucune autorisation dans le cluster. Un administrateur IAM de projet doit également associer l'utilisateur à StandardClusterRole cluster-admin avec un StandardClusterRoleBinding dans l'espace de noms du projet sur le serveur de l'API Management. L'association est propagée aux clusters standards du projet en quelques secondes (status.clusters[].conditions affiche Propagated=True). Des autorisations à l'échelle du cluster sont requises, car ce guide installe des définitions de ressources personnalisées, des ClusterRole et 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
Remplacez les éléments suivants :
MANAGEMENT_API_SERVER: chemin d'accès au fichier kubeconfig du serveur d'API de gestion.USER: utilisateur.PROJECT: projet.
Autorisations du compte robot crane (crane) Harbor :
- Lister le dépôt
- Extraire le dépôt
- Dépôt Push
- Lire un artefact
- Lister les artefacts
- Créer un tag
- Balise de liste
Autorisations du compte robot Harbor Kubernetes image pull (kubernetes-image-puller) :
- Lister le dépôt
- Extraire le dépôt
- Lire un artefact
- Lister les artefacts
- Balise de liste
Station de travail
Ce guide nécessite un poste de travail disposant de la connectivité nécessaire à l'environnement et à Internet.
Conditions requises
Les outils suivants doivent être installés sur le poste de travail :
crane: gérez et copiez les images de conteneurs et les artefacts OCI entre les registres (documentation).gdcloud: interface de ligne de commande (CLI) pour gérer les ressources GDC (documentation).kubectl: interface de ligne de commande (CLI) utilisée pour communiquer avec un cluster Kubernetes et le gérer.helm: gestionnaire de packages pour Kubernetes, version 3.8 ou ultérieure (compatibilité avec le registre OCI) (documentation).curl: outil de ligne de commande permettant de transférer des données avec des URL.jq: processeur JSON en ligne de commande léger et flexible.yq: processeur YAML portable en ligne de commande.
Exécutez toutes les commandes de ce guide à partir du poste de travail, sauf indication contraire.
Configuration de la station de travail
Les informations suivantes sur l'environnement sont requises pour la configuration de la station de travail :
GDC_STANDARD_CLUSTER_NAME: nom du cluster GDC standard.GDC_DOMAIN_SUFFIX: suffixe de domaine pour l'environnement GDC (par exemple,gdc.example.com).GDC_ORG: nom de l'organisation GDC.GDC_PROJECT: nom du projet GDC.GDC_ZONE: nom de la zone de déploiement GDC.GDC_HARBOR_INSTANCE_NAME: nom de l'instance Harbor dans le projet.GDCS_HARBOR_PROJECT_NAME: nom du projet Harbor à utiliser pour l'image (par défaut :solutions)GDCS_HARBOR_CRANE_ROBOT_NAME: nom du compte robot Harborcrane.GDCS_HARBOR_CRANE_ROBOT_TOKEN: jeton d'authentification pour le compte robot Harborcrane.GDCS_HARBOR_K8S_ROBOT_NAME: nom du compte robot Harbor Kubernetes pour l'extraction d'images.GDCS_HARBOR_K8S_ROBOT_TOKEN: jeton d'authentification pour le compte robot Harbor Kubernetes Image Pull.
Une fois que vous avez collecté les valeurs de toutes les variables requises, passez à la génération du fichier de variables d'environnement. Une fois le fichier créé, vous pouvez le modifier manuellement à tout moment.
Créez les répertoires de solution racine et le dossier des secrets :
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/*Créez le fichier de configuration de l'environnement de plate-forme :
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}" EOFRemplacez les éléments suivants :
STANDARD_CLUSTER_NAME: nom de cluster standard GDC.DOMAIN_SUFFIX: suffixe du domaine GDC.ORG: organisation GDC.PROJECT: projet GDC.ZONE: zone GDC.HARBOR_INSTANCE_NAME: nom de l'instance GDC Harbor.
Créez le fichier de configuration de l'environnement du registre :
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}" EOFRemplacez les éléments suivants :
HARBOR_CRANE_ROBOT_NAME: nom du compte robot GDC Harbor.HARBOR_K8S_ROBOT_NAME: nom du compte robot GDC Harbor.
Ajoutez vos jetons aux fichiers secrets :
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 historyRemplacez les éléments suivants :
CRANE_ROBOT_TOKEN: jeton de robot de grue.KUBERNETES_ROBOT_TOKEN: jeton de robot Kubernetes.
Créez le fichier du chargeur d'environnement racine :
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
Configurer les variables de solution
Créez le répertoire d'implémentation de la solution :
mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.dCréez le fichier de configuration de l'environnement de solution :
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" EOFCréez le fichier du chargeur d'environnement d'implémentation :
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" EOFModifiez et examinez les fichiers d'environnement avec votre éditeur préféré :
${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.shSourcez le fichier d'environnement :
source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.shLe résultat ressemble à ce qui suit :
GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
GDC
Ce guide suppose que votre station de travail est configurée pour faire confiance aux certificats TLS de votre environnement GDC et de votre instance Harbor.
Configurez
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}"Authentifiez-vous auprès de l'environnement GDC :
gdcloud auth login
Cluster
Récupérez les identifiants du cluster :
gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \ --project="${GDC_PROJECT}" \ --standard \ --zone="${GDC_ZONE}"Vérifiez la connectivité au cluster :
kubectl get nodes -L node.cluster.private.gdc.goog/machine-classVérifiez que chaque nœud exécute la version de Kubernetes requise dans la section Avant de commencer de ce guide :
kubectl get nodes -o custom-columns='NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion'
Préparation de la migration des artefacts
- Vérifiez la connectivité et la configuration du registre d'artefacts.
Créez un fichier de configuration Docker pour Crane. Un compte robot est utilisé pour envoyer des calques d'image volumineux afin d'éviter les délais d'expiration des jetons d'authentification lorsque vous utilisez le programme d'assistance pour les identifiants Managed Harbor Service (MHS) (docker-credential-mhs) avec un compte utilisateur :
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 historyCréez un fichier de configuration Docker pour 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 historyConnectez-vous au registre Harbor OCI avec
helmà l'aide du compte robot de récupération d'image Kubernetes.helmconserve ses propres identifiants de registre et en a besoin pour extraire les graphiques de Harbor :set +o history helm registry login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_K8S_ROBOT_NAME}" set -o historyLe résultat ressemble à ce qui suit :
Login SucceededCréez le 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"Créez le script
seed_charts.sh. Les charts Helm publiés en tant qu'artefacts OCI sont également copiés aveccrane, sans sélection de plate-forme et sans le tagcreateutilisé pour les dépôts d'images de conteneur :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"Remplacez les éléments suivants :
REGISTRY_HOST: hôte du registre.REPOSITORY: repository.CHART_VERSION: version du graphique.
Définissez la liste des images de conteneurs requises pour la solution :
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)Transférez les images de conteneurs requises vers Artifact Registry :
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
Définissez la liste des charts Helm requis pour la solution :
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)Ajoutez les charts Helm requis au registre d'artefacts :
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shVérifiez que les graphiques peuvent être relus à partir de 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):'Le résultat ressemble à ce qui suit :
name: gateway-helm version: v1.8.5 name: ai-gateway-helm version: v1.1.0Téléchargez les fichiers manifestes de l'extension d'inférence de l'API Gateway. Ils sont publiés en tant qu'éléments de version, et non en tant que graphiques :
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"Le résultat ressemble à ce qui suit :
4
Envoy Gateway
Envoy Gateway est installé en premier et validé seul avec le guide de démarrage rapide en amont. L'intégration d'Envoy Agent Router suit dans la section suivante.
Espace de noms
Créez l'espace de noms pour Envoy Gateway. Les
Deploymentde proxy Envoy de chaqueGatewaysont également créés dans cet espace de noms :kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"Ajoutez le
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 -
Définitions de ressources personnalisées
Installez l'API Gateway (canal standard) et les définitions de ressources personnalisées (CRD) Envoy Gateway à partir du graphique initialisé :
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=-Vérifiez que les CRD sont enregistrées :
kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
Contrôleur
Créez le fichier de valeurs Helm pour Envoy Gateway. Les images sont extraites de Harbor avec le secret d'extraction d'image ;
crds.enabled=false, car les CRD ont été installés séparément :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} EOFInstallez 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}"Attendez que le contrôleur Envoy Gateway soit disponible :
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'"Vérifiez que les images du contrôleur et de son job de génération de certificat proviennent de Harbor :
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Proxy Envoy et classe de passerelle
Créez le fichier manifeste pour le modèle de plan de données
EnvoyProxyetGatewayClass.EnvoyProxydéfinit l'image de proxy, le secret d'extraction d'image et les demandes de ressources desPodde proxy.GatewayClassest partagé par les guides de l'utilisateur :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} EOFAppliquez le fichier manifeste pour
EnvoyProxyetGatewayClass:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"Vérifiez que la
GatewayClassest acceptée :kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"Le résultat ressemble à ce qui suit :
NAME CONTROLLER ACCEPTED AGE envoy-ai-gateway gateway.envoyproxy.io/gatewayclass-controller True 5s
Validation
La validation déploie le guide de démarrage rapide Envoy Gateway (un backend d'écho derrière un HTTPRoute) dans l'espace de noms Envoy Gateway, puis le supprime.
Créez le fichier manifeste pour la charge de travail du guide de démarrage rapide :
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: / EOFAppliquez le fichier manifeste pour la charge de travail du guide de démarrage rapide :
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"Attendez que
Gatewaysoit programmé :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'"Attendez que le backend
Deploymentsoit disponible :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'"Envoyez une requête de test via la passerelle à l'aide du transfert de port. L'Envoy
Serviced'unGatewayest identifié par les libellés de sa passerelle propriétaire :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}Le résultat ressemble à ce qui suit :
{ "path": "/get", "host": "www.example.com", "method": "GET", ... "namespace": "envoy-gateway-system", "pod": "eg-quickstart-backend-...", ... }Supprimez la charge de travail du guide de démarrage rapide :
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
Routeur d'agent Envoy
Le routeur Envoy Agent est installé dans son propre espace de noms. Envoy Gateway est ensuite reconfiguré pour l'appeler en tant que serveur d'extension.
Espace de noms
Créez l'espace de noms pour le contrôleur Envoy Agent Router :
kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Ajoutez le
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 -
Définitions de ressources personnalisées
Installez les CRD du routeur Envoy Agent à partir du graphique initialisé :
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=-Installez les CRD de l'extension d'inférence de l'API Gateway (
InferencePool,InferenceObjective) à partir des fichiers manifestes téléchargés :kubectl apply --server-side \ --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"Vérifiez que les CRD sont enregistrées :
kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'Le résultat ressemble à ce qui suit :
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 limitation du débit basée sur les jetons est appliquée par le service de limitation du débit Envoy, qui stocke ses compteurs dans Redis. Ce guide déploie un service Redis à réplique unique sans persistance. Vous pouvez utiliser un service Redis existant à la place en modifiant la valeur rateLimit.backend.redis.url dans la section suivante.
Créez le fichier manifeste pour le
DeploymentRedis :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 EOFAppliquez le fichier manifeste pour le
DeploymentRedis :kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"Attendez que le
DeploymentRedis soit disponible :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'"
Contrôleur
Créez le fichier de valeurs Helm pour 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} EOFInstallez le routeur Envoy Agent :
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}"Attendez que le contrôleur Envoy Agent Router soit disponible :
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'"
Intégration d'Envoy Gateway
Envoy Gateway doit être reconfiguré pour appeler le contrôleur Envoy Agent Router en tant que serveur d'extension, pour accepter les ressources InferencePool en tant que backends et pour utiliser le service de limitation du débit basé sur Redis.
Créez le fichier de valeurs Helm pour l'intégration :
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 EOFMettez à niveau Envoy Gateway avec les deux fichiers de valeurs :
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}"Créez le fichier manifeste pour le
ClusterRolequi permet au contrôleur Envoy Gateway de surveiller les ressourcesInferencePool. Le graphique n'accorde pas cette autorisation. Un élémentClusterRoleBindingdistinct survit aux mises à niveau du graphique, contrairement à un correctif de l'élémentClusterRolegéré par le graphique :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} EOFAppliquez le fichier manifeste pour
ClusterRole:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"Redémarrez le contrôleur Envoy Gateway pour qu'il prenne en compte la nouvelle configuration et les nouvelles autorisations, puis attendez qu'il soit disponible :
kubectl rollout restart deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" kubectl rollout status deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --timeout=5mVérifiez que le service de limitation du débit a été déployé et qu'il est disponible :
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'"
Validation
La validation déploie l'exemple de base Envoy Agent Router (un backend compatible avec OpenAI simulé derrière un AIGatewayRoute) dans l'espace de noms Envoy Agent Router, puis le supprime.
Créez le fichier manifeste pour la charge de travail de validation :
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 EOFAppliquez le fichier manifeste pour la charge de travail de validation :
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Attendez que
Gatewaysoit programmé :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'"Attendez que le mock en amont
Deploymentsoit disponible :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'"Vérifiez que le proxy Envoy
PoddeGatewayexécute le side-car du processeur externe injecté par 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}'Le résultat ressemble à ce qui suit :
envoy-envoy-ai-gateway-system-aieg-basic-... envoy shutdown-manager ai-gateway-extprocEnvoyez une requête de complétion de conversation via la passerelle à l'aide du transfert de port. Le processeur externe lit le champ
modeldu corps de la requête et l'achemine vers le mock en amont :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}Le résultat ressemble à ce qui suit :
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { ... } }Supprimez la charge de travail de validation :
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
Opérations
Tâches du deuxième jour pour les plans de contrôle de la passerelle.
Mettre à niveau
- Insérez les images et les graphiques des nouvelles versions (mettez à jour les variables de version dans
env.sh, réexécutezseed_registry.shetseed_charts.sh), appliquez les nouveaux graphiques CRD aveckubectl apply --server-side, puis exécutez les mêmes commandeshelm upgrade --installavec le nouveau--version. Consultez la matrice de compatibilité de l'Envoy Agent Router pour connaître les versions d'Envoy Gateway et de l'API Gateway compatibles avec la version cible. Envoy Agent Router 1.1.0 est conçu pour Envoy Gateway 1.8.
Désinstaller
- Supprimez d'abord les ressources
Gateway,AIGatewayRouteetInferencePooldes guides de l'utilisateur, puishelm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}",helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}",ClusterRoleenvoy-gateway-inferencepool-reader,GatewayClass,DeploymentRedis et enfin les CRD.
Dépannage
| Problème constaté | Cause probable | Action |
|---|---|---|
helm show chart ou helm upgrade échoue avec unauthorized ou FetchReference |
helm n'a pas d'identifiants pour Harbor (il n'utilise pas la configuration Docker crane). |
Exécutez à nouveau l'étape helm registry login avec le compte robot Kubernetes pour l'extraction d'images. |
Les passerelles Envoy ou les routeurs d'agent Envoy Pod restent dans l'état ImagePullBackOff. |
L'image n'est pas initialisée ou le secret d'extraction de l'image est manquant dans l'espace de noms. | Vérifiez kubectl describe pod, comparez le chemin d'accès à l'image avec crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway", puis vérifiez que le secret existe dans ${GDCS_ENVOY_GATEWAY_NAMESPACE} et ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}. |
Gateway reste Programmed=False après l'intégration |
Le contrôleur Envoy Gateway ne parvient pas à accéder au serveur d'extension ou n'a pas été redémarré après la mise à niveau. | kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" ; vérifiez que service/ai-gateway-controller existe dans ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} et que le port 1063 est listé ; répétez le redémarrage du déploiement. |
AIGatewayRoute faisant référence à un InferencePool n'est pas accepté |
La passerelle Envoy ne dispose pas de l'autorisation de lire inferencepools, ou les CRD InferencePool sont manquants. |
Vérifiez le ClusterRoleBinding envoy-gateway-inferencepool-reader et le CRD inferencepools.inference.networking.k8s.io. Consultez les journaux du contrôleur pour forbidden. |
La requête de saisie semi-automatique de chat renvoie 413 ou la connexion est réinitialisée pour les requêtes volumineuses |
La limite de mémoire tampon Envoy par défaut (32 Kio) est trop petite pour les charges utiles d'IA. | Associez un ClientTrafficPolicy avec connection.bufferLimit (la validation utilise 50 Mi) au Gateway. |
Le service de limitation du débit Pod est CrashLoopBackOff |
Redis n'est pas accessible à l'URL configurée. | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}" : corrigez rateLimit.backend.redis.url dans le fichier de valeurs d'intégration, puis effectuez à nouveau la mise à niveau. |
Autres ressources
- Documentation Envoy Agent Router
- Notes de version et matrice de compatibilité d'Envoy Agent Router
- Documentation Envoy Gateway
- API Kubernetes Gateway
- Extension Gateway API Inference
- Créer un cluster standard | Google Distributed Cloud sous air gap
Créer des projets Harbor | Google Distributed Cloud sous air gap
Guide de l'utilisateur du routeur Envoy Agent pour le routage basé sur le corps