Implementasi referensi AI Gateway dengan Envoy Agent Router di GDC dengan air gap

Dokumen ini memberikan petunjuk langkah demi langkah untuk men-deploy Gateway AI di lingkungan Google Distributed Cloud (GDC) dengan air gap. Gateway ini dibangun dari Envoy Gateway, implementasi Gateway API Kubernetes berdasarkan proxy Envoy, dan Envoy Agent Router (sebelumnya Envoy AI Gateway), ekstensi yang mengubah Envoy Gateway menjadi titik entri terpadu yang kompatibel dengan OpenAI untuk traffic Model Bahasa Besar (LLM). Materi ini mencakup penyemaian image container dan diagram Helm ke registry Harbor lokal, penginstalan kedua bidang kontrol pada cluster standar, penyiapan backend pembatasan kapasitas berbasis token opsional, dan validasi penginstalan dengan contoh workload.

Backend penyajian model (Ollama, vLLM) di-deploy dengan kumpulan panduan pendamping Model Bobot Terbuka di GDC dengan air gap; Panduan pengguna perutean berbasis isi dengan Envoy Agent Router menunjukkan cara merutekan permintaan ke backend tersebut berdasarkan nama model.

Arsitektur

Solusi ini berjalan di cluster standar GDC. Workstation administrator menyalurkan image dan diagram Helm ke registry Harbor project dan menginstal dua bidang kontrol: pengontrol Envoy Gateway, yang memprogram bidang data proxy Envoy dari resource Gateway API (GatewayClass, Gateway, HTTPRoute), dan pengontrol Envoy Agent Router, yang memperluas bidang data tersebut dengan pemroses eksternal (ExtProc) untuk traffic AI (AIGatewayRoute, AIServiceBackend, InferencePool). Klien aplikasi mengirimkan permintaan yang kompatibel dengan OpenAI ke proxy Envoy, yang merutekannya ke backend penyajian model atau InferencePool. Instance Redis opsional menyimpan penghitung layanan pembatasan kapasitas Envoy untuk pembatasan kapasitas berbasis token.

Arsitektur referensi AI Gateway dengan Envoy Agent Router di GDC dengan air gap.

Envoy Gateway

Envoy Gateway adalah project open source, yang dibangun di proxy Envoy, yang menyederhanakan adopsi, penggunaan, dan pengelolaan proxy Envoy sebagai gateway API Kubernetes. Gateway API mengimplementasikan dan memperluas Kubernetes Gateway API, penerus Ingress API: resource GatewayClass dan Gateway menjelaskan titik entri, resource rute seperti HTTPRoute menjelaskan cara traffic dicocokkan dan diteruskan, dan desain berorientasi peran memisahkan tanggung jawab tim infrastruktur dan aplikasi. Envoy Gateway menambahkan API ekstensinya sendiri, misalnya EnvoyProxy (setelan bidang data), Backend (endpoint di luar cluster atau yang direferensikan oleh FQDN), dan ClientTrafficPolicy (setelan koneksi seperti batas buffering).

Router Agen Envoy

Envoy Agent Router (sebelumnya Envoy AI Gateway) adalah project open source yang menggunakan Envoy Gateway untuk menangani traffic permintaan dari klien aplikasi ke layanan AI Generatif. Gateway API menyediakan lapisan terpadu untuk merutekan dan mengelola traffic LLM dengan perutean berbasis model, autentikasi upstream, pembatasan kapasitas berbasis token, dan kemampuan observasi, serta terintegrasi dengan Gateway API Inference Extension (InferencePool, Endpoint Picker) untuk pemilihan endpoint berbasis metrik. Pengontrol memantau resource aigateway.envoyproxy.io/v1beta1 dan memasukkan pemroses eksternal di samping proxy Envoy; pemroses eksternal mengurai isi permintaan (misalnya kolom model dari permintaan penyelesaian chat OpenAI), menetapkan header perutean seperti x-ai-eg-model, dan menerjemahkan antara skema API jika diperlukan.

Sebelum memulai

Sebelum melanjutkan deployment, pastikan lingkungan Anda memenuhi semua prasyarat yang diperlukan dan utilitas command line yang diperlukan telah dikonfigurasi dengan benar. Menyiapkan alat ini di workstation Anda sangat penting untuk mengelola registry container, berinteraksi dengan cluster, dan mengotomatiskan proses deployment.

  • Lingkungan GDC dengan air gap 1.16.2-hf1 atau yang lebih baru tersedia dengan cluster standar yang menjalankan Kubernetes v1.32.13-gke.400 atau yang lebih baru.
  • Cluster standar dibuat dengan resource yang memadai. Komponen gateway hanya berjalan di CPU; backend penyajian model memiliki persyaratan akseleratornya sendiri (lihat panduan Model Bobot Terbuka di GDC dengan air gap).
  • Instance Harbor tersedia dan dapat diakses.
  • IAM yang diperlukan telah diterapkan.
  • Workstation dengan konektivitas yang diperlukan ke lingkungan dan internet

Konfigurasi lingkungan

Konfigurasi lingkungan mencakup identitas dan izin, workstation, serta akses ke lingkungan GDC dan cluster.

Identity and Access Management

Pastikan akun, peran, dan izin IAM yang diperlukan telah dikonfigurasi dengan benar.

Peran GDC User di project (RoleBinding di namespace project, yang diberikan oleh IAM Project Admin):

  • Harbor Instance Viewer (harbor-instance-viewer)
  • Harbor Project Creator (harbor-project-creator, hanya jika project Harbor belum ada)
  • Standard Cluster Admin (standard-cluster-admin, diperlukan untuk gdcloud clusters get-credentials)

Peran GDC User di cluster standar: peran project sebelumnya tidak memberikan izin di dalam cluster. Project IAM Admin juga harus mengikat pengguna ke StandardClusterRole cluster-admin dengan StandardClusterRoleBinding di namespace project di server API pengelolaan; binding ini disebarkan ke cluster standar project dalam hitungan detik (status.clusters[].conditions menampilkan Propagated=True). Izin di seluruh cluster diperlukan karena panduan ini menginstal Definisi Resource Kustom, ClusterRole, dan 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

Ganti kode berikut:

  • MANAGEMENT_API_SERVER: jalur ke file kubeconfig server API pengelolaan.
  • USER: user.
  • PROJECT: project.

Izin akun robot Harbor crane (crane):

  • Repositori Daftar
  • Repositori Pull
  • Repositori Push
  • Membaca Artefak
  • Artefak Daftar
  • Buat Tag
  • Tag Daftar

Izin akun robot penarik image Kubernetes Harbor (kubernetes-image-puller):

  • Repositori Daftar
  • Repositori Pull
  • Membaca Artefak
  • Artefak Daftar
  • Tag Daftar

Workstation

Jalankan semua perintah dalam panduan ini dari workstation dengan alat dan konektivitas yang diperlukan ke lingkungan dan internet, kecuali jika ada langkah yang menyatakan sebaliknya.

Persyaratan

Alat berikut harus diinstal di workstation:

  • crane: mengelola dan menyalin image container dan artefak OCI di antara registry (dokumentasi).
  • gdcloud: antarmuka command line (CLI) untuk mengelola resource GDC (dokumentasi).
  • kubectl: antarmuka command line (CLI) yang digunakan untuk berkomunikasi dengan dan mengelola cluster Kubernetes.
  • helm: pengelola paket untuk Kubernetes, versi 3.8 atau yang lebih tinggi (dukungan registry OCI) (dokumentasi).
  • curl: alat command line untuk mentransfer data dengan URL.
  • jq: pemroses JSON command line yang ringan dan fleksibel.
  • yq: pemroses YAML command line portabel.

Jalankan semua perintah dalam panduan ini dari workstation, kecuali jika langkahnya menyatakan sebaliknya.

Konfigurasi workstation

Informasi berikut tentang lingkungan diperlukan untuk Konfigurasi Workstation:

  • GDC_STANDARD_CLUSTER_NAME: Nama cluster standar GDC.
  • GDC_DOMAIN_SUFFIX: Akhiran domain untuk lingkungan GDC (misalnya, gdc.example.com).
  • GDC_ORG: Nama organisasi GDC.
  • GDC_PROJECT: Nama project GDC.
  • GDC_ZONE: Nama zona deployment GDC.
  • GDC_HARBOR_INSTANCE_NAME: Nama instance Harbor dalam project.

  • GDCS_HARBOR_PROJECT_NAME: Nama project Harbor yang akan digunakan untuk image (default: solutions)

  • GDCS_HARBOR_CRANE_ROBOT_NAME: Nama akun robot crane Harbor.

  • GDCS_HARBOR_CRANE_ROBOT_TOKEN: Token autentikasi untuk akun robot crane Harbor.

  • GDCS_HARBOR_K8S_ROBOT_NAME: Nama akun robot penarikan image Kubernetes Harbor.

  • GDCS_HARBOR_K8S_ROBOT_TOKEN: Token autentikasi untuk akun robot penarikan image Kubernetes Harbor.

Setelah Anda mengumpulkan nilai untuk semua variabel yang diperlukan, lanjutkan dengan membuat file variabel lingkungan. Setelah dibuat, Anda dapat mengedit file secara manual kapan saja.

  1. Buat direktori solusi root dan folder rahasia:

    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/*
    
  2. Buat file konfigurasi lingkungan platform:

    cat << 'EOF' > ${HOME}/gdcag-solutions/env.d/platform.sh && echo "Successfully created." || echo "Failed to create!"
    # Infrastructure (Platform Native)
    export GDC_STANDARD_CLUSTER_NAME="STANDARD_CLUSTER_NAME"
    export GDC_DOMAIN_SUFFIX="DOMAIN_SUFFIX"
    export GDC_ORG="ORG"
    export GDC_PROJECT="PROJECT"
    export GDC_ZONE="ZONE"
    export GDC_HARBOR_INSTANCE_NAME="HARBOR_INSTANCE_NAME"
    
    # Derived platform values
    export GDC_ZONAL_HOSTNAME="${GDC_ORG}.${GDC_ZONE}.${GDC_DOMAIN_SUFFIX}"
    export GDC_ZONAL_CONSOLE_URL="https://console.${GDC_ZONAL_HOSTNAME}"
    export GDC_HARBOR_HOST="${GDC_HARBOR_INSTANCE_NAME}-${GDC_PROJECT}.${GDC_ORG}.${GDC_ZONE}.${GDC_DOMAIN_SUFFIX}"
    EOF
    

    Ganti kode berikut:

    • STANDARD_CLUSTER_NAME: Nama cluster standar GDC.
    • DOMAIN_SUFFIX: Akhiran domain GDC.
    • ORG: Organisasi GDC.
    • PROJECT: Project GDC.
    • ZONE: Zona GDC.
    • HARBOR_INSTANCE_NAME: Nama instance GDC Harbor.
  3. Buat file konfigurasi lingkungan registry:

    cat << 'EOF' > ${HOME}/gdcag-solutions/env.d/registry.sh && echo "Successfully created." || echo "Failed to create!"
    # GDC Solutions Registry & Secrets
    export GDCS_HARBOR_PROJECT_NAME="solutions"
    export GDCS_HARBOR_CRANE_ROBOT_NAME="HARBOR_CRANE_ROBOT_NAME"
    export GDCS_HARBOR_CRANE_ROBOT_TOKEN="$(cat ${GDCS_ROOT_HOME}/secrets/harbor_crane_robot_token)"
    export GDCS_HARBOR_K8S_ROBOT_NAME="HARBOR_K8S_ROBOT_NAME"
    export GDCS_HARBOR_K8S_ROBOT_TOKEN="$(cat ${GDCS_ROOT_HOME}/secrets/harbor_k8s_robot_token)"
    export GDCS_HARBOR_K8S_PULL_SECRET="gdcs-image-pull-secret"
    
    # Derived registry values
    export GDCS_HARBOR_PROJECT_URI="${GDC_HARBOR_HOST}/${GDCS_HARBOR_PROJECT_NAME}"
    export GDCS_HARBOR_CHART_OCI_URI="oci://${GDCS_HARBOR_PROJECT_URI}"
    EOF
    

    Ganti kode berikut:

    • HARBOR_CRANE_ROBOT_NAME: Nama akun robot GDC Harbor.
    • HARBOR_K8S_ROBOT_NAME: Nama akun robot GDC Harbor.
  4. Tambahkan token Anda ke file secret:

    set +o history
    
    echo "CRANE_ROBOT_TOKEN" > ${HOME}/gdcag-solutions/secrets/harbor_crane_robot_token
    echo "KUBERNETES_ROBOT_TOKEN" > ${HOME}/gdcag-solutions/secrets/harbor_k8s_robot_token
    
    set -o history
    

    Ganti kode berikut:

    • CRANE_ROBOT_TOKEN: token robot crane.
    • KUBERNETES_ROBOT_TOKEN: Token robot Kubernetes.
  5. Buat file loader lingkungan root:

    cat << 'EOF' > ${HOME}/gdcag-solutions/env.sh && echo "Successfully created." || echo "Failed to create!"
    export GDCS_ROOT_HOME="${HOME}/gdcag-solutions"
    echo "GDCS_ROOT_HOME=${GDCS_ROOT_HOME}"
    
    # Sourced in dependency order
    source "${GDCS_ROOT_HOME}/env.d/platform.sh"
    source "${GDCS_ROOT_HOME}/env.d/registry.sh"
    EOF
    

Mengonfigurasi variabel solusi

  1. Buat direktori implementasi solusi:

    mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.d
    
  2. Buat file konfigurasi lingkungan solusi:

    cat << 'EOF' > ${HOME}/gdcag-solutions/ai-gateway/envoy/env.d/envoy.sh && echo "Successfully created." || echo "Failed to create!"
    # Envoy Gateway
    export GDCS_ENVOY_GATEWAY_NAMESPACE="envoy-gateway-system"
    export GDCS_ENVOY_GATEWAY_VERSION="v1.8.5"
    export GDCS_ENVOY_PROXY_IMAGE_TAG="distroless-v1.38.4"
    export GDCS_ENVOY_RATELIMIT_IMAGE_TAG="8fe6ea42"
    export GDCS_GATEWAY_API_ECHO_IMAGE_TAG="v1.5.1"
    
    # Envoy Agent Router (formerly Envoy AI Gateway; the images and charts keep the ai-gateway names)
    export GDCS_ENVOY_AGENT_ROUTER_NAMESPACE="envoy-ai-gateway-system"
    export GDCS_ENVOY_AGENT_ROUTER_VERSION="v1.1.0"
    
    # Gateway API Inference Extension (InferencePool, Endpoint Picker)
    export GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION="v1.5.0"
    
    # Redis (token-based rate limiting backend)
    export GDCS_REDIS_IMAGE_TAG="8.10.2-alpine3.23"
    export GDCS_REDIS_NAMESPACE="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
    
    # Gateway class shared by the user guides
    export GDCS_GATEWAY_CLASS_NAME="envoy-ai-gateway"
    
    # Docker configuration directories for crane and Kubernetes
    export GDCS_HARBOR_CRANE_DOCKER_CONFIG="${GDCS_IMPLEMENTATION_HOME}/docker/crane"
    export GDCS_HARBOR_K8S_DOCKER_CONFIG="${GDCS_IMPLEMENTATION_HOME}/docker/k8s"
    EOF
    
  3. Buat file loader lingkungan implementasi:

    cat << 'EOF' > ${HOME}/gdcag-solutions/ai-gateway/envoy/env.sh && echo "Successfully created." || echo "Failed to create!"
    source "${HOME}/gdcag-solutions/env.sh"
    
    export GDCS_IMPLEMENTATION_HOME="${HOME}/gdcag-solutions/ai-gateway/envoy"
    echo "GDCS_IMPLEMENTATION_HOME=${GDCS_IMPLEMENTATION_HOME}"
    
    # Sourced in dependency order
    source "${GDCS_IMPLEMENTATION_HOME}/env.d/envoy.sh"
    EOF
    
  4. Edit dan tinjau file lingkungan dengan editor pilihan Anda:

    ${EDITOR:-vi} ${HOME}/gdcag-solutions/env.d/platform.sh
    ${EDITOR:-vi} ${HOME}/gdcag-solutions/env.d/registry.sh
    ${EDITOR:-vi} ${HOME}/gdcag-solutions/ai-gateway/envoy/env.d/envoy.sh
    
  5. Ambil file lingkungan:

    source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.sh
    

    Outputnya mirip dengan hal berikut ini:

    GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions
    GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
    

GDC

Panduan ini mengasumsikan bahwa workstation Anda dikonfigurasi untuk memercayai sertifikat TLS untuk lingkungan GDC dan instance Harbor Anda.

  1. Konfigurasikan 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}"
    
  2. Lakukan autentikasi ke lingkungan GDC:

    gdcloud auth login
    

Cluster

  1. Ambil kredensial cluster:

    gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \
    --project="${GDC_PROJECT}" \
    --standard \
    --zone="${GDC_ZONE}"
    
  2. Verifikasi konektivitas ke cluster:

    kubectl get nodes -L node.cluster.private.gdc.goog/machine-class
    

Persiapan migrasi artefak

  1. Buat file konfigurasi Docker untuk crane. Akun robot digunakan untuk mendorong lapisan image besar guna menghindari waktu tunggu token autentikasi saat menggunakan pembantu kredensial Managed Harbor Service (MHS) (docker-credential-mhs) dengan akun pengguna:

    set +o history
    
    export DOCKER_CONFIG="${GDCS_HARBOR_CRANE_DOCKER_CONFIG}"
    
    crane auth login "${GDC_HARBOR_HOST}" \
    --password="${GDCS_HARBOR_CRANE_ROBOT_TOKEN}" \
    --username="${GDCS_HARBOR_CRANE_ROBOT_NAME}"
    
    set -o history
    
  2. Buat file konfigurasi Docker untuk 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 history
    
  3. Login ke registry OCI Harbor dengan helm menggunakan akun robot penarikan image Kubernetes. helm menyimpan kredensial registry-nya sendiri dan memerlukannya untuk mengambil diagram dari Harbor:

    set +o history
    helm registry login "${GDC_HARBOR_HOST}" \
    --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \
    --username="${GDCS_HARBOR_K8S_ROBOT_NAME}"
    set -o history
    

    Outputnya mirip dengan hal berikut ini:

    Login Succeeded
    
  4. Buat skrip 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"
    
  5. Buat skrip seed_charts.sh. Diagram Helm yang dipublikasikan sebagai artefak OCI juga disalin dengan crane, tanpa pemilihan platform dan tanpa tag create yang digunakan untuk repositori image container:

    cat << 'EOF' > ${GDCS_IMPLEMENTATION_HOME}/seed_charts.sh && echo "Successfully created." || echo "Failed to create!"
    #!/bin/bash
    
    # seed_charts.sh: OCI Helm chart migration for GDC Solutions
    
    # Requires the env.sh file to be sourced first.
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    set -o nounset
    source "${SCRIPT_DIR}/env.sh"
    
    # Set the Docker config
    export DOCKER_CONFIG="${GDCS_HARBOR_CRANE_DOCKER_CONFIG}"
    eval "${SERIALIZED_CHARTS}"
    
    # Ensure GDCS_REGISTRY_CHARTS is set
    if [[ ${#GDCS_REGISTRY_CHARTS[@]} -eq 0 ]]; then
      echo "GDCS_REGISTRY_CHARTS must be set, exiting..."
      exit 1
    fi
    
    # Migrate the charts (source format: REGISTRY_HOST/REPOSITORY:CHART_VERSION)
    for source_chart in "${GDCS_REGISTRY_CHARTS[@]}"; do
      chart_path="${source_chart#*/}"
      destination_chart="${GDCS_HARBOR_PROJECT_URI}/${chart_path}"
      crane copy "${source_chart}" "${destination_chart}" || { echo "Failed to copy ${source_chart} to ${destination_chart}"; exit 1; }
    done
    echo "Migration complete: Charts are available at ${GDCS_HARBOR_CHART_OCI_URI}"
    EOF
    chmod u+x "${GDCS_IMPLEMENTATION_HOME}/seed_charts.sh"
    

    Ganti kode berikut:

    • REGISTRY_HOST: host registry.
    • REPOSITORY: repositori.
    • CHART_VERSION: versi diagram.
  6. Tentukan daftar image container yang diperlukan untuk solusi:

    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)
    
  7. Lakukan seeding image container yang diperlukan ke artifact registry:

    ${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
    
  1. Tentukan daftar chart Helm yang diperlukan untuk solusi:

    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)
    
  2. Masukkan chart Helm yang diperlukan ke artifact registry:

    ${GDCS_IMPLEMENTATION_HOME}/seed_charts.sh
    
  3. Pastikan diagram dapat dibaca kembali dari 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):'
    

    Outputnya mirip dengan hal berikut ini:

    name: gateway-helm
    version: v1.8.5
    name: ai-gateway-helm
    version: v1.1.0
    
  4. Download manifes Gateway API Inference Extension. Mereka dipublikasikan sebagai aset rilis, bukan sebagai diagram:

    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"
    

    Outputnya mirip dengan hal berikut ini:

    4
    

Envoy Gateway

Envoy Gateway diinstal terlebih dahulu dan divalidasi sendiri dengan panduan memulai upstream; integrasi Envoy Agent Router akan dibahas di bagian berikutnya.

Namespace

  1. Buat namespace untuk Envoy Gateway. Deployment proxy Envoy dari setiap Gateway juga dibuat di namespace ini:

    kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"
    
  2. Tambahkan 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 -
    

Definisi Resource Kustom

  1. Instal Gateway API (saluran standar) dan Definisi Resource Kustom (CRD) Envoy Gateway dari diagram yang di-seed:

    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=-
    
  2. Pastikan CRD telah terdaftar:

    kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
    

Pengontrol

  1. Buat file nilai Helm untuk Envoy Gateway. Image ditarik dari Harbor dengan secret pull image; crds.enabled=false karena CRD diinstal secara terpisah:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-values.yaml" && echo "Successfully created." || echo "Failed to create!"
    config:
      envoyGateway:
        extensionApis:
          enableBackend: true
          enableEnvoyPatchPolicy: true
        gateway:
          controllerName: gateway.envoyproxy.io/gatewayclass-controller
        logging:
          level:
            default: info
        provider:
          type: Kubernetes
    crds:
      enabled: false
    global:
      imagePullSecrets:
        - name: ${GDCS_HARBOR_K8S_PULL_SECRET}
      imageRegistry: ${GDCS_HARBOR_PROJECT_URI}
      images:
        envoyProxy:
          image: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/envoy:${GDCS_ENVOY_PROXY_IMAGE_TAG}
          pullSecrets:
            - name: ${GDCS_HARBOR_K8S_PULL_SECRET}
    EOF
    
  2. Menginstal 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}"
    
  3. Tunggu hingga pengontrol Envoy Gateway tersedia:

    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'"
    
  4. Pastikan image pengontrol dan tugas pembuatan sertifikatnya berasal dari Harbor:

    kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \
    --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
    

Proxy Envoy dan class Gateway

  1. Buat manifes untuk template bidang data EnvoyProxy dan GatewayClass. EnvoyProxy menetapkan image proxy, secret pull image, dan permintaan resource Pod proxy; GatewayClass dibagikan oleh panduan pengguna:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml" && echo "Successfully created." || echo "Failed to create!"
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: EnvoyProxy
    metadata:
      name: ${GDCS_GATEWAY_CLASS_NAME}
      namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE}
    spec:
      provider:
        type: Kubernetes
        kubernetes:
          envoyDeployment:
            container:
              image: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/envoy:${GDCS_ENVOY_PROXY_IMAGE_TAG}
              resources:
                limits:
                  memory: 2Gi
                requests:
                  cpu: 250m
                  memory: 512Mi
            pod:
              imagePullSecrets:
                - name: ${GDCS_HARBOR_K8S_PULL_SECRET}
    ---
    apiVersion: gateway.networking.k8s.io/v1
    kind: GatewayClass
    metadata:
      name: ${GDCS_GATEWAY_CLASS_NAME}
    spec:
      controllerName: gateway.envoyproxy.io/gatewayclass-controller
      parametersRef:
        group: gateway.envoyproxy.io
        kind: EnvoyProxy
        name: ${GDCS_GATEWAY_CLASS_NAME}
        namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE}
    EOF
    
  2. Terapkan manifes untuk EnvoyProxy dan GatewayClass:

    kubectl apply \
    --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"
    
  3. Pastikan GatewayClass berstatus Accepted:

    kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"
    

    Outputnya mirip dengan hal berikut ini:

    NAME               CONTROLLER                                      ACCEPTED   AGE
    envoy-ai-gateway   gateway.envoyproxy.io/gatewayclass-controller   True       5s
    

Validasi

Validasi ini men-deploy panduan memulai Envoy Gateway (backend echo di belakang HTTPRoute) ke dalam namespace Envoy Gateway dan menghapusnya setelahnya.

  1. Buat manifes untuk workload panduan memulai:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" && echo "Successfully created." || echo "Failed to create!"
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: eg-quickstart
    spec:
      gatewayClassName: ${GDCS_GATEWAY_CLASS_NAME}
      listeners:
        - name: http
          protocol: HTTP
          port: 80
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: eg-quickstart-backend
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: eg-quickstart-backend
      labels:
        app: eg-quickstart-backend
    spec:
      ports:
        - name: http
          port: 3000
          targetPort: 3000
      selector:
        app: eg-quickstart-backend
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: eg-quickstart-backend
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: eg-quickstart-backend
      template:
        metadata:
          labels:
            app: eg-quickstart-backend
        spec:
          serviceAccountName: eg-quickstart-backend
          containers:
            - image: ${GDCS_HARBOR_PROJECT_URI}/gateway-api/echo-basic:${GDCS_GATEWAY_API_ECHO_IMAGE_TAG}
              imagePullPolicy: IfNotPresent
              name: backend
              ports:
                - containerPort: 3000
              env:
                - name: POD_NAME
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
                - name: NAMESPACE
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
          imagePullSecrets:
            - name: ${GDCS_HARBOR_K8S_PULL_SECRET}
    ---
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: eg-quickstart-backend
    spec:
      parentRefs:
        - name: eg-quickstart
      hostnames:
        - "www.example.com"
      rules:
        - backendRefs:
            - group: ""
              kind: Service
              name: eg-quickstart-backend
              port: 3000
              weight: 1
          matches:
            - path:
                type: PathPrefix
                value: /
    EOF
    
  2. Terapkan manifes untuk workload panduan memulai:

    kubectl apply \
    --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \
    --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
    
  3. Tunggu hingga Gateway Diprogram:

    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'"
    
  4. Tunggu hingga backend Deployment tersedia:

    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'"
    
  5. Kirim permintaan pengujian melalui gateway menggunakan penerusan port. Service Envoy dari Gateway ditemukan berdasarkan label gateway pemiliknya:

    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}
    

    Outputnya mirip dengan hal berikut ini:

    {
      "path": "/get",
      "host": "www.example.com",
      "method": "GET",
      ...
      "namespace": "envoy-gateway-system",
      "pod": "eg-quickstart-backend-...",
      ...
    }
    
  6. Hapus workload panduan memulai:

    kubectl delete \
    --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \
    --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
    

Router Agen Envoy

Envoy Agent Router diinstal ke namespace-nya sendiri; Envoy Gateway kemudian dikonfigurasi ulang untuk memanggilnya sebagai server ekstensi.

Namespace

  1. Buat namespace untuk pengontrol Envoy Agent Router:

    kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
    
  2. Tambahkan 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 -
    

Definisi Resource Kustom

  1. Instal CRD Envoy Agent Router dari diagram yang di-seed:

    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=-
    
  2. Instal CRD Gateway API Inference Extension (InferencePool, InferenceObjective) dari manifes yang didownload:

    kubectl apply --server-side \
    --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"
    
  3. Pastikan CRD telah terdaftar:

    kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'
    

    Outputnya mirip dengan hal berikut ini:

    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

Pembatasan kapasitas berbasis token diterapkan oleh layanan batas kapasitas Envoy, yang menyimpan penghitungnya di Redis. Panduan ini men-deploy Redis satu replika tanpa persistensi; layanan Redis yang ada dapat digunakan sebagai gantinya dengan mengubah nilai rateLimit.backend.redis.url di bagian berikutnya.

  1. Buat manifes untuk Deployment Redis:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/redis.yaml" && echo "Successfully created." || echo "Failed to create!"
    apiVersion: v1
    kind: Service
    metadata:
      name: redis
      labels:
        app: redis
    spec:
      ports:
        - name: redis
          port: 6379
      selector:
        app: redis
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
        spec:
          containers:
            - image: ${GDCS_HARBOR_PROJECT_URI}/library/redis:${GDCS_REDIS_IMAGE_TAG}
              imagePullPolicy: IfNotPresent
              name: redis
              ports:
                - name: redis
                  containerPort: 6379
              resources:
                limits:
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 128Mi
          imagePullSecrets:
            - name: ${GDCS_HARBOR_K8S_PULL_SECRET}
          restartPolicy: Always
    EOF
    
  2. Terapkan manifes untuk Deployment Redis:

    kubectl apply \
    --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \
    --namespace="${GDCS_REDIS_NAMESPACE}"
    
  3. Tunggu hingga Redis Deployment tersedia:

    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'"
    

Pengontrol

  1. Buat file nilai Helm untuk 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}
    EOF
    
  2. Instal Envoy Agent Router:

    helm upgrade --install aieg "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/ai-gateway-helm" \
    --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}" \
    --values="${GDCS_IMPLEMENTATION_HOME}/envoy-agent-router-values.yaml" \
    --version="${GDCS_ENVOY_AGENT_ROUTER_VERSION}"
    
  3. Tunggu hingga pengontrol Envoy Agent Router tersedia:

    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'"
    

Integrasi Envoy Gateway

Envoy Gateway harus dikonfigurasi ulang untuk memanggil pengontrol Envoy Agent Router sebagai server ekstensinya, untuk menerima resource InferencePool sebagai backend, dan untuk menggunakan layanan pembatasan kapasitas yang didukung Redis.

  1. Buat file nilai Helm untuk integrasi:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-agent-router-values.yaml" && echo "Successfully created." || echo "Failed to create!"
    config:
      envoyGateway:
        extensionManager:
          backendResources:
            - group: inference.networking.k8s.io
              kind: InferencePool
              version: v1
          hooks:
            xdsTranslator:
              post:
                - Translation
                - Cluster
                - Route
              translation:
                cluster:
                  includeAll: true
                listener:
                  includeAll: true
                route:
                  includeAll: true
                secret:
                  includeAll: true
          service:
            fqdn:
              hostname: ai-gateway-controller.${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}.svc.cluster.local
              port: 1063
        rateLimit:
          backend:
            redis:
              url: redis.${GDCS_REDIS_NAMESPACE}.svc.cluster.local:6379
            type: Redis
    EOF
    
  2. Upgrade Envoy Gateway dengan kedua file nilai:

    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}"
    
  3. Buat manifes untuk ClusterRole yang memungkinkan pengontrol Envoy Gateway memantau resource InferencePool. Diagram tidak memberikan izin ini; ClusterRoleBinding terpisah akan bertahan dari upgrade diagram, tidak seperti patch ClusterRole yang dikelola diagram:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml" && echo "Successfully created." || echo "Failed to create!"
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: envoy-gateway-inferencepool-reader
    rules:
      - apiGroups:
          - inference.networking.k8s.io
        resources:
          - inferencepools
        verbs:
          - get
          - list
          - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: envoy-gateway-inferencepool-reader
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: envoy-gateway-inferencepool-reader
    subjects:
      - kind: ServiceAccount
        name: envoy-gateway
        namespace: ${GDCS_ENVOY_GATEWAY_NAMESPACE}
    EOF
    
  4. Terapkan manifes untuk ClusterRole:

    kubectl apply \
    --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"
    
  5. Mulai ulang pengontrol Envoy Gateway agar mengambil konfigurasi dan izin baru, lalu tunggu hingga statusnya Available:

    kubectl rollout restart deployment/envoy-gateway \
    --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
    
    kubectl rollout status deployment/envoy-gateway \
    --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \
    --timeout=5m
    
  6. Pastikan layanan pembatasan kapasitas telah di-deploy dan Tersedia:

    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'"
    

Validasi

Validasi ini men-deploy contoh dasar Envoy Agent Router (upstream tiruan yang kompatibel dengan OpenAI di balik AIGatewayRoute) ke dalam namespace Envoy Agent Router dan menghapusnya setelahnya.

  1. Buat manifes untuk workload validasi:

    cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" && echo "Successfully created." || echo "Failed to create!"
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: aieg-basic
    spec:
      gatewayClassName: ${GDCS_GATEWAY_CLASS_NAME}
      listeners:
        - name: http
          protocol: HTTP
          port: 80
    ---
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: ClientTrafficPolicy
    metadata:
      name: aieg-basic-buffer-limit
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: aieg-basic
      connection:
        bufferLimit: 50Mi
    ---
    apiVersion: aigateway.envoyproxy.io/v1beta1
    kind: AIGatewayRoute
    metadata:
      name: aieg-basic
    spec:
      parentRefs:
        - name: aieg-basic
          kind: Gateway
          group: gateway.networking.k8s.io
      rules:
        - matches:
            - headers:
                - type: Exact
                  name: x-ai-eg-model
                  value: some-cool-self-hosted-model
          backendRefs:
            - name: aieg-basic-testupstream
    ---
    apiVersion: aigateway.envoyproxy.io/v1beta1
    kind: AIServiceBackend
    metadata:
      name: aieg-basic-testupstream
    spec:
      schema:
        name: OpenAI
      backendRef:
        name: aieg-basic-testupstream
        kind: Backend
        group: gateway.envoyproxy.io
    ---
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: Backend
    metadata:
      name: aieg-basic-testupstream
    spec:
      endpoints:
        - fqdn:
            hostname: aieg-basic-testupstream.${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}.svc.cluster.local
            port: 80
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aieg-basic-testupstream
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aieg-basic-testupstream
      template:
        metadata:
          labels:
            app: aieg-basic-testupstream
        spec:
          containers:
            - name: testupstream
              image: ${GDCS_HARBOR_PROJECT_URI}/envoyproxy/ai-gateway-testupstream:${GDCS_ENVOY_AGENT_ROUTER_VERSION}
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 8080
              env:
                - name: TESTUPSTREAM_ID
                  value: test
              readinessProbe:
                httpGet:
                  path: /health
                  port: 8080
                initialDelaySeconds: 5
                periodSeconds: 10
              livenessProbe:
                httpGet:
                  path: /health
                  port: 8080
                initialDelaySeconds: 10
                periodSeconds: 20
          imagePullSecrets:
            - name: ${GDCS_HARBOR_K8S_PULL_SECRET}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aieg-basic-testupstream
    spec:
      selector:
        app: aieg-basic-testupstream
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
      type: ClusterIP
    EOF
    
  2. Terapkan manifes untuk workload validasi:

    kubectl apply \
    --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \
    --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
    
  3. Tunggu hingga Gateway Diprogram:

    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'"
    
  4. Tunggu hingga upstream tiruan Deployment tersedia:

    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'"
    
  5. Pastikan proxy Envoy Pod dari Gateway menjalankan sidecar pemroses eksternal yang diinjeksikan oleh 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}'
    

    Outputnya mirip dengan hal berikut ini:

    envoy-envoy-ai-gateway-system-aieg-basic-...   envoy shutdown-manager ai-gateway-extproc
    
  6. Mengirim permintaan penyelesaian chat melalui gateway menggunakan penerusan port. Pemroses eksternal membaca kolom model dari isi permintaan dan merutekannya ke upstream tiruan:

    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}
    

    Outputnya mirip dengan hal berikut ini:

    {
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "..."
          },
          "finish_reason": "stop"
        }
      ],
      "usage": {
        ...
      }
    }
    
  7. Hapus workload validasi:

    kubectl delete \
    --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \
    --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
    

Operasi

Tugas hari kedua untuk bidang kontrol gateway.

Upgrade

  • Lakukan seeding pada image dan diagram versi baru (update variabel versi di env.sh, jalankan ulang seed_registry.sh dan seed_charts.sh), terapkan diagram CRD baru dengan kubectl apply --server-side, lalu jalankan perintah helm upgrade --install yang sama dengan --version baru. Periksa matriks kompatibilitas Envoy Agent Router untuk mengetahui versi Envoy Gateway dan Gateway API yang didukung oleh rilis target; Envoy Agent Router 1.1.0 dibuat berdasarkan Envoy Gateway 1.8.

Uninstal

  • Hapus resource Gateway, AIGatewayRoute, dan InferencePool dari panduan pengguna terlebih dahulu, lalu helm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}", helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}", ClusterRole envoy-gateway-inferencepool-reader, GatewayClass, Deployment Redis, dan terakhir CRD.

Pemecahan masalah

Gejala Kemungkinan penyebab Tindakan
helm show chart atau helm upgrade gagal dengan unauthorized atau FetchReference helm tidak memiliki kredensial untuk Harbor (tidak menggunakan konfigurasi Docker crane) Jalankan langkah helm registry login lagi dengan akun robot penarikan image Kubernetes.
Envoy Gateway atau Envoy Agent Router Pod tetap berada di ImagePullBackOff Image tidak di-seed, atau secret pull image tidak ada di namespace Periksa kubectl describe pod, bandingkan jalur image dengan crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway", dan verifikasi bahwa secret ada di ${GDCS_ENVOY_GATEWAY_NAMESPACE} dan ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}.
Gateway tetap Programmed=False setelah integrasi Pengontrol Envoy Gateway tidak dapat menjangkau server ekstensi, atau tidak dimulai ulang setelah upgrade kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"; pastikan service/ai-gateway-controller ada di ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} dan port 1063 tercantum; ulangi mulai ulang peluncuran.
AIGatewayRoute yang merujuk ke InferencePool tidak Diterima Envoy Gateway tidak memiliki izin untuk membaca inferencepools, atau CRD InferencePool tidak ada Verifikasi ClusterRoleBinding envoy-gateway-inferencepool-reader dan CRD inferencepools.inference.networking.k8s.io; periksa log pengontrol untuk forbidden.
Permintaan penyelesaian chat menampilkan 413 atau koneksi direset untuk perintah yang besar Batas buffer Envoy default (32 KiB) terlalu kecil untuk payload AI Lampirkan ClientTrafficPolicy dengan connection.bufferLimit (validasi menggunakan 50 Mi) ke Gateway.
Layanan pembatasan kapasitas Pod adalah CrashLoopBackOff Redis tidak dapat dijangkau di URL yang dikonfigurasi kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}"; perbaiki rateLimit.backend.redis.url di file nilai integrasi dan upgrade lagi.

Materi tambahan