In diesem Dokument finden Sie eine detaillierte Anleitung zum Bereitstellen eines AI Gateway in GDC-Umgebungen (Google Distributed Cloud) mit Air Gap. Das Gateway basiert auf Envoy Gateway, der Kubernetes Gateway API-Implementierung, die auf dem Envoy-Proxy basiert, und Envoy Agent Router (früher Envoy AI Gateway), der Erweiterung, die Envoy Gateway in einen einheitlichen, OpenAI-kompatiblen Einstiegspunkt für Large Language Model (LLM)-Traffic verwandelt. Es umfasst das Seeding der Container-Images und Helm-Diagramme in die lokale Harbor-Registry, die Installation beider Steuerungsebenen auf einem Standardcluster, die Vorbereitung des optionalen tokenbasierten Backends für die Ratenbegrenzung und die Validierung der Installation mit Beispielarbeitslasten.
Back-Ends für die Modellbereitstellung (Ollama, vLLM) werden mit den zugehörigen Anleitungen Open-Weight-Modelle in GDC mit Air Gap bereitgestellt. Im Nutzerhandbuch zum Body-basierten Routing mit Envoy Agent Router wird gezeigt, wie Anfragen nach Modellname an sie weitergeleitet werden.
Architektur
Die Lösung wird in einem GDC-Standardcluster ausgeführt. Eine Administrator-Workstation stellt die Images und Helm-Diagramme in der Harbor-Registry des Projekts bereit und installiert die beiden Steuerungsebenen: den Envoy Gateway-Controller, der die Envoy-Proxy-Datenebene aus Gateway API-Ressourcen (GatewayClass, Gateway, HTTPRoute) programmiert, und den Envoy Agent Router-Controller, der diese Datenebene um einen externen Prozessor (ExtProc) für KI-Traffic (AIGatewayRoute, AIServiceBackend, InferencePool) erweitert. Anwendungsclients senden OpenAI-kompatible Anfragen an den Envoy-Proxy, der sie an die Back-Ends für die Modellbereitstellung oder InferencePools weiterleitet. In einer optionalen Redis-Instanz werden die Zähler des Envoy-Dienstes zur Ratenbegrenzung für die tokenbasierte Ratenbegrenzung gespeichert.

Envoy Gateway
Envoy Gateway ist ein Open-Source-Projekt, das auf Envoy Proxy basiert und die Einführung, Verwendung und Verwaltung von Envoy Proxy als Kubernetes API-Gateway vereinfacht. Sie implementiert und erweitert die Kubernetes Gateway API, den Nachfolger der Ingress API: GatewayClass- und Gateway-Ressourcen beschreiben die Einstiegspunkte, Routenressourcen wie HTTPRoute beschreiben, wie Traffic abgeglichen und weitergeleitet wird, und das rollenorientierte Design trennt die Verantwortlichkeiten von Infrastruktur- und Anwendungsteams. Envoy Gateway fügt eigene Erweiterungs-APIs hinzu, z. B. EnvoyProxy (Einstellungen für die Datenebene), Backend (Endpunkte außerhalb des Clusters oder mit FQDN-Referenz) und ClientTrafficPolicy (Verbindungseinstellungen wie Pufferlimits).
Envoy-Agent-Router
Envoy Agent Router (früher Envoy AI Gateway) ist ein Open-Source-Projekt, das Envoy Gateway verwendet, um Anfragetraffic von Anwendungsclients an Generative AI-Dienste zu verarbeiten. Es bietet eine einheitliche Ebene für das Routing und die Verwaltung von LLM-Traffic mit modellbewusstem Routing, Upstream-Authentifizierung, tokenbasierter Ratenbegrenzung und Beobachtbarkeit. Außerdem ist es in die Gateway API Inference Extension (InferencePool, Endpoint Picker) für die messwertbasierte Endpunktauswahl eingebunden. Der Controller überwacht die aigateway.envoyproxy.io/v1beta1-Ressourcen und fügt neben dem Envoy-Proxy einen externen Prozessor ein. Der externe Prozessor parst den Anfragetext (z. B. das Feld model einer OpenAI-Chat-Vervollständigungsanfrage), legt Routing-Header wie x-ai-eg-model fest und übersetzt bei Bedarf zwischen API-Schemas.
Hinweis
Bevor Sie mit der Bereitstellung fortfahren, müssen Sie sicherstellen, dass Ihre Umgebung alle erforderlichen Voraussetzungen erfüllt und die erforderlichen Befehlszeilen-Dienstprogramme richtig konfiguriert sind. Die Einrichtung dieser Tools auf Ihrer Workstation ist für die Verwaltung von Container-Registries, die Interaktion mit Clustern und die Automatisierung des Bereitstellungsprozesses unerlässlich.
- Die GDC mit Air Gap-Umgebung ab Version 1.16.2-hf1 ist mit einem Standardcluster verfügbar, auf dem Kubernetes ab Version 1.32.13-gke.400 ausgeführt wird.
- Standardcluster mit ausreichenden Ressourcen erstellt. Die Gateway-Komponenten werden nur auf der CPU ausgeführt. Backends für die Modellbereitstellung haben eigene Anforderungen an Beschleuniger (siehe die Leitfäden zu Open-Weight-Modellen in GDC mit Air Gap).
- Harbor-Instanz verfügbar und zugänglich.
- Erforderliche IAM-Berechtigungen angewendet.
- Workstation mit der erforderlichen Verbindung zur Umgebung und zum Internet
Umgebungskonfiguration
Die Umgebungskonfiguration umfasst die Identitäten und Berechtigungen, die Workstation und den Zugriff auf die GDC-Umgebung und den Cluster.
Identity and Access Management
Prüfen Sie, ob die erforderlichen IAM-Konten, -Rollen und -Berechtigungen richtig konfiguriert sind.
GDC-Nutzerrollen im Projekt (RoleBinding im Projekt-Namespace, zugewiesen von einem IAM-Projektadministrator):
- Harbor-Instanzbetrachter (
harbor-instance-viewer) - Harbor-Projektersteller (
harbor-project-creator, nur wenn das Harbor-Projekt noch nicht vorhanden ist) - Standard-Cluster-Administrator (
standard-cluster-admin, erforderlich fürgdcloud clusters get-credentials)
GDC-Nutzerrolle im Standardcluster: Die vorherigen Projektrollen gewähren keine Berechtigungen innerhalb des Clusters. Ein Projekt-IAM-Administrator muss den Nutzer zusätzlich an die StandardClusterRole cluster-admin mit einer StandardClusterRoleBinding im Projekt-Namespace auf dem Verwaltungs-API-Server binden. Die Bindung wird innerhalb von Sekunden an die Standardcluster des Projekts weitergegeben (status.clusters[].conditions zeigt Propagated=True). Clusterweite Berechtigungen sind erforderlich, da in dieser Anleitung benutzerdefinierte Ressourcendefinitionen, ClusterRoles und ein GatewayClass installiert werden.
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
Ersetzen Sie Folgendes:
MANAGEMENT_API_SERVER: der Pfad zur kubeconfig-Datei des Verwaltungs-API-Servers.USER: Nutzer.PROJECT: Projekt.
Berechtigungen für das Harbor crane (Crane)-Robot-Konto:
- Repository auflisten
- Pull-Repository
- Repository übertragen
- Artefakt lesen
- Artefakt auflisten
- Tag erstellen
- Listen-Tag
Berechtigungen für das Harbor Kubernetes-Image-Pull-Robot-Konto (kubernetes-image-puller):
- Repository auflisten
- Pull-Repository
- Artefakt lesen
- Artefakt auflisten
- Listen-Tag
Workstation
Führen Sie alle Befehle in dieser Anleitung auf einer Workstation mit den erforderlichen Tools und der erforderlichen Verbindung zur Umgebung und zum Internet aus, sofern in einem Schritt nichts anderes angegeben ist.
Voraussetzungen
Die folgenden Tools müssen auf der Workstation installiert sein:
crane: Container-Images und OCI-Artefakte zwischen Registries verwalten und kopieren (Dokumentation).gdcloud: Befehlszeile (CLI) zum Verwalten von GDC-Ressourcen (Dokumentation).kubectl: Befehlszeile (CLI) zur Kommunikation mit einem Kubernetes-Cluster und zu dessen Verwaltung.helm: Paketmanager für Kubernetes, Version 3.8 oder höher (OCI-Registry-Unterstützung) (Dokumentation).curl: Befehlszeilentool zum Übertragen von Daten mit URLs.jq: Ein einfacher und flexibler JSON-Prozessor für die Befehlszeile.yq: portabler YAML-Prozessor für die Befehlszeile.
Führen Sie alle Befehle in dieser Anleitung auf der Workstation aus, sofern in einem Schritt nichts anderes angegeben ist.
Workstationkonfiguration
Die folgenden Informationen zur Umgebung sind für die Workstation-Konfiguration erforderlich:
GDC_STANDARD_CLUSTER_NAME: Der Name des GDC-Standardclusters.GDC_DOMAIN_SUFFIX: Das Domain-Suffix für die GDC-Umgebung (z. B.gdc.example.com).GDC_ORG: Der Name der GDC-Organisation.GDC_PROJECT: Der Name des GDC-Projekts.GDC_ZONE: Der Name der GDC-Bereitstellungszone.GDC_HARBOR_INSTANCE_NAME: Der Name der Harbor-Instanz im Projekt.GDCS_HARBOR_PROJECT_NAME: Der Name des Harbor-Projekts, das für das Image verwendet werden soll (Standard:solutions)GDCS_HARBOR_CRANE_ROBOT_NAME: Der Name des Harbor-crane-Roboterkontos.GDCS_HARBOR_CRANE_ROBOT_TOKEN: Das Authentifizierungstoken für das Harbor-crane-Roboterkonto.GDCS_HARBOR_K8S_ROBOT_NAME: Der Name des Harbor-Kubernetes-Image-Pull-Roboterkontos.GDCS_HARBOR_K8S_ROBOT_TOKEN: Das Authentifizierungstoken für das Harbor-Kubernetes-Image-Pull-Roboterkonto.
Nachdem Sie die Werte für alle erforderlichen Variablen erfasst haben, fahren Sie mit dem Erstellen der Datei für Umgebungsvariablen fort. Nachdem die Datei erstellt wurde, können Sie sie jederzeit manuell bearbeiten.
Erstellen Sie die Stammverzeichnisse der Lösung und den Ordner für 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/*Erstellen Sie die Konfigurationsdatei für die Plattformumgebung:
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}" EOFErsetzen Sie Folgendes:
STANDARD_CLUSTER_NAME: Name des GDC-Standardclusters.DOMAIN_SUFFIX: GDC-Domainsuffix.ORG: GDC-Organisation.PROJECT: GDC-Projekt.ZONE: GDC-Zone.HARBOR_INSTANCE_NAME: Name der GDC Harbor-Instanz.
Erstellen Sie die Konfigurationsdatei für die Registry-Umgebung:
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}" EOFErsetzen Sie Folgendes:
HARBOR_CRANE_ROBOT_NAME: Name des GDC Harbor-Roboterkontos.HARBOR_K8S_ROBOT_NAME: Name des GDC Harbor-Roboterkontos.
Fügen Sie Ihre Tokens den Secret-Dateien hinzu:
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 historyErsetzen Sie Folgendes:
CRANE_ROBOT_TOKEN: Crane-Roboter-Token.KUBERNETES_ROBOT_TOKEN: Kubernetes-Roboter-Token.
Erstellen Sie die Loader-Datei für die Root-Umgebung:
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
Lösungsvariablen konfigurieren
Erstellen Sie das Verzeichnis für die Lösungsimplementierung:
mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.dErstellen Sie die Konfigurationsdatei für die Lösungsumgebung:
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" EOFErstellen Sie die Loader-Datei für die Implementierungsumgebung:
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" EOFBearbeiten und prüfen Sie die Umgebungsdateien mit Ihrem bevorzugten Editor:
${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.shRufen Sie die Umgebungsdatei auf:
source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.shDie Ausgabe sieht etwa so aus:
GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
GDC
In diesem Leitfaden wird davon ausgegangen, dass Ihre Workstation so konfiguriert ist, dass sie den TLS-Zertifikaten für Ihre GDC-Umgebung und Harbor-Instanz vertraut.
Konfigurieren Sie
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}"Authentifizieren Sie sich bei der GDC-Umgebung:
gdcloud auth login
Cluster
Clusteranmeldedaten abrufen:
gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \ --project="${GDC_PROJECT}" \ --standard \ --zone="${GDC_ZONE}"Prüfen Sie die Verbindung zum Cluster:
kubectl get nodes -L node.cluster.private.gdc.goog/machine-class
Artefaktmigration vorbereiten
- Prüfen Sie die Verbindung und Konfiguration für die Artefakt-Registry.
Erstellen Sie eine Docker-Konfigurationsdatei für Crane. Ein Roboterkonto wird verwendet, um große Image-Ebenen zu übertragen und so Zeitüberschreitungen bei Authentifizierungstokens zu vermeiden, wenn der Managed Harbor Service (MHS)-Anmeldedaten-Helper (docker-credential-mhs) mit einem Nutzerkonto verwendet wird:
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 historyErstellen Sie eine Docker-Konfigurationsdatei für 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 historyMelden Sie sich mit
helmin der Harbor-OCI-Registry an. Verwenden Sie dazu das Roboterkonto zum Abrufen von Kubernetes-Images.helmspeichert eigene Registry-Anmeldedaten und benötigt diese, um die Diagramme aus Harbor abzurufen:set +o history helm registry login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_K8S_ROBOT_NAME}" set -o historyDie Ausgabe sieht etwa so aus:
Login SucceededErstellen Sie das Skript
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"Erstellen Sie das Skript
seed_charts.sh. Als OCI-Artefakte veröffentlichte Helm-Diagramme werden ebenfalls mitcranekopiert, ohne Plattformauswahl und ohne das Tagcreate, das für Container-Image-Repositories verwendet wird: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"Ersetzen Sie Folgendes:
REGISTRY_HOST: Registry-Host.REPOSITORY: Repository.CHART_VERSION: Diagrammversion.
Definieren Sie die Liste der erforderlichen Container-Images für die Lösung:
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)Übertragen Sie die erforderlichen Container-Images per Seed an Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
Definieren Sie die Liste der erforderlichen Helm-Diagramme für die Lösung:
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)Übertragen Sie die erforderlichen Helm-Diagramme in die Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shPrüfen Sie, ob die Diagramme aus Harbor zurückgelesen werden können:
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):'Die Ausgabe sieht etwa so aus:
name: gateway-helm version: v1.8.5 name: ai-gateway-helm version: v1.1.0Laden Sie die Manifeste für die Gateway API Inference Extension herunter. Sie werden als Release-Asset und nicht als Diagramm veröffentlicht:
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"Die Ausgabe sieht etwa so aus:
4
Envoy Gateway
Envoy Gateway wird zuerst installiert und mit der Upstream-Kurzanleitung validiert. Die Integration von Envoy Agent Router folgt im nächsten Abschnitt.
Namespace
Erstellen Sie den Namespace für Envoy Gateway. Die Envoy-Proxy-
Deployments allerGatewaywerden ebenfalls in diesem Namespace erstellt:kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"Fügen Sie die
imagePullSecrethinzu: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 -
Benutzerdefinierte Ressourcendefinitionen
Installieren Sie die Gateway API (Standardkanal) und die benutzerdefinierten Ressourcendefinitionen (CRDs) für Envoy Gateway aus dem Seed-Diagramm:
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=-Prüfen Sie, ob die CRDs registriert sind:
kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
Controller
Erstellen Sie die Helm-Wertedatei für Envoy Gateway. Die Images werden mit dem Image-Pull-Secret aus Harbor abgerufen.
crds.enabled=false, da die CRDs separat installiert wurden: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} EOFInstallieren Sie 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}"Warten Sie, bis der Envoy Gateway-Controller verfügbar ist:
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'"Prüfen Sie, ob die Images des Controllers und seines Zertifikatgenerierungsjobs von Harbor stammen:
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Envoy-Proxy und Gateway-Klasse
Erstellen Sie das Manifest für die
EnvoyProxy-Datenebenenvorlage und dieGatewayClass. Mit demEnvoyProxywerden das Proxy-Image, das Image-Pull-Secret und die Ressourcenanfragen der Proxy-Pods festgelegt. DieGatewayClasswird von den Nutzerhandbüchern gemeinsam verwendet: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} EOFWenden Sie das Manifest für
EnvoyProxyundGatewayClassan:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"Prüfen Sie, ob der
GatewayClassakzeptiert wurde:kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"Die Ausgabe sieht etwa so aus:
NAME CONTROLLER ACCEPTED AGE envoy-ai-gateway gateway.envoyproxy.io/gatewayclass-controller True 5s
Validierung
Bei der Validierung wird der Envoy Gateway-Schnellstart (ein Echo-Backend hinter einem HTTPRoute) im Envoy Gateway-Namespace bereitgestellt und anschließend entfernt.
Erstellen Sie das Manifest für die Schnellstart-Arbeitslast:
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: / EOFWenden Sie das Manifest für die Arbeitslast der Kurzanleitung an:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"Warten Sie, bis die
Gatewayprogrammiert ist: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'"Warten Sie, bis das Backend
Deploymentverfügbar ist: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'"Senden Sie eine Testanfrage über das Gateway mithilfe der Portweiterleitung. Der Envoy-
ServiceeinesGatewaywird anhand der Labels des zugehörigen Gateways ermittelt: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}Die Ausgabe sieht etwa so aus:
{ "path": "/get", "host": "www.example.com", "method": "GET", ... "namespace": "envoy-gateway-system", "pod": "eg-quickstart-backend-...", ... }Entfernen Sie die Arbeitslast aus der Kurzanleitung:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
Envoy-Agent-Router
Der Envoy Agent Router wird in einem eigenen Namespace installiert. Das Envoy Gateway wird dann so konfiguriert, dass es als Erweiterungsserver aufgerufen wird.
Namespace
Erstellen Sie den Namespace für den Envoy Agent Router-Controller:
kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Fügen Sie die
imagePullSecrethinzu: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 -
Benutzerdefinierte Ressourcendefinitionen
Installieren Sie die Envoy Agent Router-CRDs aus dem Seed-Diagramm:
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=-Installieren Sie die Gateway API Inference Extension-CRDs (
InferencePool,InferenceObjective) aus den heruntergeladenen Manifesten:kubectl apply --server-side \ --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"Prüfen Sie, ob die CRDs registriert sind:
kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'Die Ausgabe sieht etwa so aus:
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
Die tokenbasierte Ratenbegrenzung wird vom Envoy-Ratenbegrenzungsdienst erzwungen, der seine Zähler in Redis speichert. In diesem Leitfaden wird ein Redis-Dienst mit einem einzelnen Replikat ohne Persistenz bereitgestellt. Sie können stattdessen einen vorhandenen Redis-Dienst verwenden, indem Sie den Wert rateLimit.backend.redis.url im nächsten Abschnitt ändern.
Erstellen Sie das Manifest für den 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 EOFWenden Sie das Manifest für den Redis-
Deploymentan:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"Warten Sie, bis die Redis-
Deploymentverfügbar ist: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
Erstellen Sie die Helm-Wertedatei für den 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} EOFEnvoy-Agent-Router installieren:
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}"Warten Sie, bis der Envoy Agent Router-Controller verfügbar ist:
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-Integration
Envoy Gateway muss neu konfiguriert werden, um den Envoy Agent Router-Controller als Erweiterungsserver aufzurufen, InferencePool-Ressourcen als Backends zu akzeptieren und den Redis-basierten Dienst zur Ratenbegrenzung zu verwenden.
Erstellen Sie die Helm-Wertedatei für die Integration:
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 EOFAktualisieren Sie Envoy Gateway mit beiden Wertedateien:
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}"Erstellen Sie das Manifest für die
ClusterRole, mit der der Envoy Gateway-ControllerInferencePool-Ressourcen beobachten kann. Das Diagramm gewährt diese Berechtigung nicht. Ein separatesClusterRoleBindingbleibt im Gegensatz zu einem Patch des vom Diagramm verwaltetenClusterRolebei Diagrammupgrades erhalten: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} EOFWenden Sie das Manifest für
ClusterRolean:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"Starten Sie den Envoy Gateway-Controller neu, damit er die neue Konfiguration und die neuen Berechtigungen übernimmt, und warten Sie, bis er verfügbar ist:
kubectl rollout restart deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" kubectl rollout status deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --timeout=5mPrüfen Sie, ob der Dienst zur Ratenbegrenzung bereitgestellt wurde und verfügbar ist:
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'"
Validierung
Bei der Validierung wird das einfache Beispiel für den Envoy Agent Router (ein simulierter OpenAI-kompatibler Upstream hinter einem AIGatewayRoute) im Envoy Agent Router-Namespace bereitgestellt und anschließend entfernt.
Erstellen Sie das Manifest für die Validierungsarbeitslast:
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 EOFWenden Sie das Manifest für die Validierungsarbeitslast an:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Warten Sie, bis die
Gatewayprogrammiert ist: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'"Warten Sie, bis der Mock-Upstream
Deploymentverfügbar ist: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'"Prüfen Sie, ob der Envoy-Proxy
PodvonGatewayden Sidecar-Container des externen Prozessors ausführt, der vom Envoy Agent Router eingefügt wurde: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}'Die Ausgabe sieht etwa so aus:
envoy-envoy-ai-gateway-system-aieg-basic-... envoy shutdown-manager ai-gateway-extprocSenden Sie eine Anfrage zur Chatvervollständigung über das Gateway mithilfe der Portweiterleitung. Der externe Prozessor liest das Feld
modeldes Anfragetexts und leitet es an den simulierten Upstream weiter: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}Die Ausgabe sieht etwa so aus:
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { ... } }Entfernen Sie die Validierungsarbeitslast:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
Vorgänge
Day-Two-Aufgaben für die Gateway-Steuerungsebenen.
Upgrade
- Stellen Sie die Images und Diagramme der neuen Versionen bereit (aktualisieren Sie die Versionsvariablen in
env.sh, führen Sieseed_registry.shundseed_charts.shnoch einmal aus), wenden Sie die neuen CRD-Diagramme mitkubectl apply --server-sidean und führen Sie dann dieselbenhelm upgrade --install-Befehle mit der neuen--versionaus. In der Kompatibilitätsmatrix für Envoy Agent Router finden Sie die Envoy Gateway- und Gateway API-Versionen, die vom Zielrelease unterstützt werden. Envoy Agent Router 1.1.0 basiert auf Envoy Gateway 1.8.
Deinstallieren
- Löschen Sie zuerst die Ressourcen
Gateway,AIGatewayRouteundInferencePoolder Nutzerhandbücher, dannhelm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}",helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}", dieClusterRoleenvoy-gateway-inferencepool-reader, dieGatewayClass, die Redis-Deploymentund schließlich die CRDs.
Fehlerbehebung
| Symptom | Wahrscheinliche Ursache | Aktion |
|---|---|---|
helm show chart oder helm upgrade schlägt mit unauthorized oder FetchReference fehl |
helm hat keine Anmeldedaten für Harbor (die Docker-Konfiguration crane wird nicht verwendet) |
Führen Sie den Schritt helm registry login noch einmal mit dem Kubernetes-Image-Pull-Robot-Konto aus. |
Envoy Gateway- oder Envoy Agent Router-Pods bleiben in ImagePullBackOff |
Image wurde nicht per Seeding bereitgestellt oder das Image-Pull-Secret fehlt im Namespace | Prüfen Sie kubectl describe pod, vergleichen Sie den Image-Pfad mit crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway" und prüfen Sie, ob das Secret in ${GDCS_ENVOY_GATEWAY_NAMESPACE} und ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} vorhanden ist. |
Gateway bleibt nach der Integration Programmed=False |
Der Envoy Gateway-Controller kann den Erweiterungsserver nicht erreichen oder wurde nach dem Upgrade nicht neu gestartet. | kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"; prüfen Sie, ob service/ai-gateway-controller in ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} vorhanden ist und Port 1063 aufgeführt ist. Wiederholen Sie den Neustart des Roll-outs. |
AIGatewayRoute, die auf eine InferencePool verweisen, werden nicht akzeptiert |
Envoy Gateway hat keine Berechtigung zum Lesen von inferencepools oder die InferencePool-CRDs fehlen |
Prüfen Sie die ClusterRoleBinding-envoy-gateway-inferencepool-reader und die inferencepools.inference.networking.k8s.io-CRD. Suchen Sie in den Controller-Logs nach forbidden. |
Die Anfrage zum Vervollständigen des Chats gibt 413 zurück oder die Verbindung wird bei großen Prompts zurückgesetzt. |
Das standardmäßige Envoy-Pufferlimit (32 KiB) ist für KI-Nutzlasten zu klein. | Hängen Sie einen ClientTrafficPolicy mit connection.bufferLimit (die Validierung verwendet 50 Mi) an den Gateway an. |
Der Dienst zur Ratenbegrenzung Pod ist CrashLoopBackOff |
Redis ist unter der konfigurierten URL nicht erreichbar | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}"; Beheben Sie rateLimit.backend.redis.url in der Datei mit den Integrationswerten und führen Sie das Upgrade noch einmal durch. |
Zusätzliche Materialien
- Dokumentation zum Envoy Agent Router
- Versionshinweise und Kompatibilitätsmatrix für Envoy Agent Router
- Envoy Gateway-Dokumentation
- Kubernetes Gateway API
- Gateway API Inference Extension
- Standardcluster erstellen | Google Distributed Cloud mit Air Gap
Harbor-Projekte erstellen | Google Distributed Cloud mit Air Gap
Nutzerhandbuch für textkörperbasiertes Routing mit Envoy Agent Router