Dieses Dokument enthält eine Schritt-für-Schritt-Anleitung für die Bereitstellung eines AI Gateway in GDC-Umgebungen (Google Distributed Cloud) mit Air Gap. Das Gateway basiert auf Envoy Gateway, der auf dem Envoy-Proxy basierenden Kubernetes Gateway API-Implementierung, 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 umwandelt. Darin wird beschrieben, wie Sie die Container-Images und Helm-Diagramme in die lokale Harbor-Registry einfügen, beide Steuerungsebenen in einem Standardcluster installieren, das optionale tokenbasierte Backend für die Ratenbegrenzung vorbereiten und die Installation mit Beispielarbeitslasten validieren.
Die Backends für die Modellbereitstellung (Ollama, vLLM) werden mit der zugehörigen Reihe von Anleitungen Open Weight Models on GDC mit Air Gap bereitgestellt. Im Nutzerhandbuch für Body-basiertes Routing mit Envoy Agent Router wird beschrieben, wie Anfragen nach Modellname an sie weitergeleitet werden.
Architektur
Die Lösung wird in einem GDC-Standardcluster ausgeführt. Auf einer Administrator-Workstation werden die Bilder und Helm-Diagramme in die Harbor-Registry des Projekts eingefügt und die beiden Steuerungsebenen installiert: der Envoy Gateway-Controller, der die Envoy-Proxy-Datenebene aus Gateway API-Ressourcen (GatewayClass, Gateway, HTTPRoute) programmiert, und der Envoy Agent Router-Controller, der diese Datenebene mit einem 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 an InferencePool weiterleitet. In einer optionalen Redis-Instanz werden die Zähler des Envoy-Ratenbegrenzungsdienstes für die tokenbasierte Ratenbegrenzung gespeichert.

Envoy Gateway
Envoy Gateway ist ein Open-Source-Projekt, das auf dem 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 referenziert) 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 Dienste mit generativer KI zu verarbeiten. Sie bietet eine einheitliche Ebene für das Routing und die Verwaltung von LLM-Traffic mit modellbewusstem Routing, Upstream-Authentifizierung, tokenbasierten Ratenbegrenzung und Observability. Außerdem ist sie in die Gateway API Inference Extension (InferencePool, Endpoint Picker) für die metrikbewusste Endpunktauswahl integriert. 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-Completion-Anfrage), 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 Befehlszeilenprogramme richtig konfiguriert sind. Die Einrichtung dieser Tools auf Ihrer Workstation ist unerlässlich, um Containerregistrierungen zu verwalten, mit Clustern zu interagieren und den Bereitstellungsprozess zu automatisieren.
- Die GDC-Umgebung ohne Internetverbindung 1.16.2-hf1 oder höher ist mit einem Standardcluster verfügbar, auf dem Kubernetes v1.32.13-gke.400 oder höher ausgeführt wird.
- Standardcluster mit ausreichenden Ressourcen erstellt. Die Gateway-Komponenten werden nur auf der CPU ausgeführt. Für die Back-Ends für die Modellbereitstellung gelten eigene Anforderungen an Beschleuniger (siehe die Anleitungen Open Weight Models on GDC air-gapped).
- Die Harbor-Instanz ist verfügbar und zugänglich.
- Erforderliches IAM angewendet.
- Workstation mit der erforderlichen Verbindung zur Umgebung und zum Internet
Umgebungskonfiguration
Die Umgebungskonfiguration umfasst die Identitäten und Berechtigungen, die Arbeitsstation 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-Nutzer-Rollen für Projekt (RoleBinding im Projekt-Namespace, zugewiesen von einem Projekt-IAM-Administrator):
- Harbor-Instanz-Betrachter (
harbor-instance-viewer) - Harbor Project Creator (
harbor-project-creator, nur wenn das Harbor-Projekt noch nicht vorhanden ist) - Standard-Clusteradministrator (
standard-cluster-admin, fürgdcloud clusters get-credentialserforderlich)
Rolle GDC-Nutzer im Standardcluster: Die vorherigen Projektrollen gewähren keine Berechtigungen im Cluster. Ein Projekt-IAM-Administrator muss den Nutzer zusätzlich mit einem StandardClusterRoleBinding im Projekt-Namespace auf dem Management-API-Server an die StandardClusterRole cluster-admin 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 Management-API-Servers.USER: user.PROJECT: Projekt
Berechtigungen für das Harbor-Robot-Konto crane (crane):
- Repository auflisten
- Repository pullen
- Repository pushen
- Artefakt lesen
- Artefakt auflisten
- Tag erstellen
- List-Tag
Berechtigungen für das Roboterkonto für das Abrufen von Harbor-Kubernetes-Images (kubernetes-image-puller):
- Repository auflisten
- Repository pullen
- Artefakt lesen
- Artefakt auflisten
- List-Tag
Workstation
Für diesen Leitfaden ist eine Workstation mit der erforderlichen Verbindung zum Netzwerk und zum Internet erforderlich.
Voraussetzungen
Die folgenden Tools müssen auf der Workstation installiert sein:
crane: Container-Images und OCI-Artefakte zwischen Registries verwalten und kopieren (Dokumentation).gdcloud: Befehlszeilenschnittstelle (CLI) zum Verwalten von GDC-Ressourcen (Dokumentation).kubectl: Befehlszeilenschnittstelle (CLI) zur Kommunikation mit und Verwaltung eines Kubernetes-Clusters.helm: Paketmanager für Kubernetes, Version 3.8 oder höher (OCI-Registrierungsunterstützung) (Dokumentation).curl: Befehlszeilentool zum Übertragen von Daten mit URLs.jq: Ein schlanker und flexibler JSON-Prozessor für die Befehlszeile.yq: portabler YAML-Befehlszeilenprozessor.
Führen Sie alle Befehle in dieser Anleitung auf der Workstation aus, sofern in einem Schritt nichts anderes angegeben ist.
Workstationkonfiguration
Für die Workstation-Konfiguration sind die folgenden Informationen zur Umgebung erforderlich:
GDC_STANDARD_CLUSTER_NAME: Der Name des GDC-Standardclusters.GDC_DOMAIN_SUFFIX: Das Domainsuffix 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 dascrane-Roboterkonto von Harbor.GDCS_HARBOR_K8S_ROBOT_NAME: Der Name des Harbor-Robotkontos für das Abrufen von Kubernetes-Images.GDCS_HARBOR_K8S_ROBOT_TOKEN: Das Authentifizierungstoken für das Harbor-Robotkonto zum Abrufen von Kubernetes-Images.
Nachdem Sie die Werte für alle erforderlichen Variablen erfasst haben, fahren Sie mit dem Generieren der Umgebungsvariablen-Datei fort. Nach der Erstellung können Sie die Datei jederzeit manuell bearbeiten.
Erstellen Sie die Stammverzeichnisse der Lösung und den Ordner „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: Standardname des GDC-Clusters.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 die 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: Token für Kranroboter.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 Umgebungsvariablen 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 Ihre 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 in 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-classPrüfen Sie, ob auf jedem Knoten die Kubernetes-Version ausgeführt wird, die im Abschnitt Vorbereitung dieses Leitfadens erforderlich ist:
kubectl get nodes -o custom-columns='NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion'
Migration von Artefakten vorbereiten
- Prüfen Sie die Verbindung und Konfiguration für die Artifact Registry.
Erstellen Sie eine Docker-Konfigurationsdatei für Crane. Ein Roboterkonto wird verwendet, um große Bildebenen zu übertragen, um Zeitüberschreitungen von Autorisierungstokens zu vermeiden, wenn der MHS-Anmeldeinformationshelfer (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 mit dem Kubernetes-Roboterkonto für das Abrufen von Images an.helmverwaltet seine eigenen Registry-Anmeldedaten und benötigt sie, 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
seed_registry.sh-Skript: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 dass eine Plattform ausgewählt wird 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: Die Version des Diagramms.
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 Push an die 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)Stellen Sie die erforderlichen Helm-Diagramme in der Artifact Registry bereit:
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shPrüfen Sie, ob die Diagramme aus Harbor gelesen 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 der 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 dem Upstream-Schnellstart validiert. Die Integration des Envoy Agent Router folgt im nächsten Abschnitt.
Namespace
Erstellen Sie den Namespace für Envoy Gateway. Die Envoy-Proxys
DeploymentjedesGatewaywerden 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 (Standardchannel) und die benutzerdefinierten Ressourcendefinitionen (CRDs) von 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-Datei mit den Werten für Envoy Gateway. Die Bilder 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} EOFEnvoy Gateway installieren:
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 Bilder des Controllers und des Zertifikaterstellungsjobs aus 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-Datenebene-Vorlage und dieGatewayClass. MitEnvoyProxywerden das Proxybild, das Image-Pull-Secret und die Ressourcenanforderungen der Proxy-Podfestgelegt.GatewayClasswird in den Nutzerhandbüchern 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
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 Kurzanleitung:
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
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 über die Portweiterleitung eine Testanfrage über das Gateway. 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 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. Envoy Gateway wird dann neu konfiguriert, um ihn als Erweiterungsserver aufzurufen.
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 dieser Anleitung wird eine Redis-Instanz 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 die Redis-Instanz
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-Instanz
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-Datei mit den Werten 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 Ratenbegrenzungsservice zu verwenden.
Erstellen Sie die Helm-Datei mit Werten 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 dem der Envoy Gateway-ControllerInferencePool-Ressourcen überwachen kann. Das Diagramm gewährt diese Berechtigung nicht. Ein separatesClusterRoleBindingübersteht Diagramm-Upgrades, im Gegensatz zu einem Patch des vom Diagramm verwaltetenClusterRole: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 für 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 grundlegende Beispiel für den Envoy-Agent-Router (ein Mock-Upstream, der mit OpenAI kompatibel ist und sich hinter einem AIGatewayRoute befindet) im Namespace des Envoy-Agent-Routers 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
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
PodderGatewayden externen Prozessor-Sidecar 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 über das Gateway eine Chat-Vervollständigungsanfrage mithilfe der Portweiterleitung. Der externe Prozessor liest das Feld
modeldes Anfragetexts und leitet es an den Mock-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
Aufgaben für den zweiten Tag für die Steuerungsebenen des Gateways.
Upgrade
- Erstelle die Bilder und Diagramme der neuen Versionen (aktualisiere die Versionsvariablen in
env.sh, führeseed_registry.shundseed_charts.shnoch einmal aus), wende die neuen CRD-Diagramme mitkubectl apply --server-sidean und führe dann dieselbenhelm upgrade --install-Befehle mit dem neuen--versionaus. In der Envoy Agent Router-Kompatibilitätsmatrix finden Sie die Envoy Gateway- und Gateway API-Versionen, die von der Zielversion unterstützt werden. Envoy Agent Router 1.1.0 wurde für Envoy Gateway 1.8 entwickelt.
Deinstallieren
- Löschen Sie zuerst die
Gateway-,AIGatewayRoute- undInferencePool-Ressourcen der 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 (es wird nicht die crane-Docker-Konfiguration verwendet). |
Führen Sie den Schritt helm registry login noch einmal mit dem Kubernetes-Roboterkonto zum Abrufen von Images aus. |
Envoy Gateway oder Envoy Agent Router Pods bleiben in ImagePullBackOff |
Image nicht bereitgestellt oder das Secret zum Abrufen von Images fehlt im Namespace | Prüfen Sie kubectl describe pod, vergleichen Sie den Bildpfad 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}"; bestätigen Sie, dass service/ai-gateway-controller in ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} vorhanden ist und Port 1063 aufgeführt wird. Wiederholen Sie den Neustart des Roll-outs. |
AIGatewayRoute mit Verweis auf eine InferencePool wird 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. |
Bei einer Anfrage zur Vervollständigung eines Chats wird 413 zurückgegeben 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 eine ClientTrafficPolicy mit connection.bufferLimit (für die Validierung werden 50 Mi verwendet) an die Gateway an. |
Die Ratenbegrenzung für den Dienst Pod ist CrashLoopBackOff |
Redis ist unter der konfigurierten URL nicht erreichbar | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}"; korrigieren Sie rateLimit.backend.redis.url in der Datei mit den Integrationswerten und führen Sie das Upgrade noch einmal durch. |
Zusätzliches Material
- Dokumentation zum Envoy Agent Router
- Versionshinweise und Kompatibilitätsmatrix für den 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
Textkörperbasiertes Routing mit dem Envoy Agent Router – Nutzerhandbuch