このドキュメントでは、Google Distributed Cloud(GDC)のエアギャップ環境に AI Gateway をデプロイする手順について説明します。このゲートウェイは、Envoy プロキシに基づく Kubernetes Gateway API 実装である Envoy Gateway と、Envoy Gateway を大規模言語モデル(LLM)トラフィック用の OpenAI 互換の統合エントリ ポイントにする拡張機能である Envoy Agent Router(以前の Envoy AI Gateway)から構築されています。コンテナ イメージと Helm チャートをローカルの Harbor レジストリにシードする、標準クラスタに両方のコントロール プレーンをインストールする、オプションのトークンベースのレート制限バックエンドを準備する、サンプル ワークロードでインストールを検証する手順について説明します。
モデル提供バックエンド(Ollama、vLLM)は、コンパニオン ガイドのセット GDC エアギャップでのオープン ウェイト モデルでデプロイされます。Envoy エージェント ルーターを使用した本文ベースのルーティングのユーザーガイドでは、モデル名でリクエストをルーティングする方法について説明しています。
アーキテクチャ
このソリューションは GDC 標準クラスタで実行されます。管理者ワークステーションは、イメージと Helm チャートをプロジェクトの Harbor レジストリにシードし、2 つのコントロール プレーン(Envoy プロキシ データプレーンを Gateway API リソース(GatewayClass、Gateway、HTTPRoute)からプログラムする Envoy Gateway コントローラと、AI トラフィック用の外部プロセッサ(ExtProc)でデータプレーンを拡張する Envoy Agent Router コントローラ(AIGatewayRoute、AIServiceBackend、InferencePool))をインストールします。アプリケーション クライアントは、OpenAI 互換のリクエストを Envoy プロキシに送信します。Envoy プロキシは、リクエストをモデル提供バックエンドまたは InferencePool にルーティングします。オプションの Redis インスタンスは、トークンベースのレート制限用の Envoy レート制限サービスのカウンタを保存します。

Envoy Gateway
Envoy Gateway は、Envoy プロキシ上に構築されたオープンソース プロジェクトで、Kubernetes API ゲートウェイとしての Envoy プロキシの導入、使用、管理を簡素化します。これは、Ingress API の後継である Kubernetes Gateway API を実装して拡張します。GatewayClass リソースと Gateway リソースはエントリ ポイントを記述し、HTTPRoute などのルート リソースはトラフィックのマッチングと転送の方法を記述します。また、ロール指向の設計により、インフラストラクチャ チームとアプリケーション チームの責任が分離されます。Envoy Gateway は、独自の拡張機能 API(EnvoyProxy(データプレーン設定)、Backend(クラスタ外のエンドポイントまたは FQDN で参照されるエンドポイント)、ClientTrafficPolicy(バッファ上限などの接続設定)など)を追加します。
Envoy エージェント ルーター
Envoy Agent Router(以前の Envoy AI Gateway)は、Envoy Gateway を使用してアプリケーション クライアントから生成 AI サービスへのリクエスト トラフィックを処理するオープンソース プロジェクトです。モデル認識ルーティング、アップストリーム認証、トークンベースのレート制限とオブザーバビリティを使用して LLM トラフィックをルーティングおよび管理するための統合レイヤを提供し、指標認識エンドポイント選択のために Gateway API 推論拡張機能(InferencePool、エンドポイント ピッカー)と統合します。コントローラは aigateway.envoyproxy.io/v1beta1 リソースを監視し、Envoy プロキシの横に外部プロセッサを挿入します。外部プロセッサはリクエスト本文(OpenAI チャット完了リクエストの model フィールドなど)を解析し、x-ai-eg-model などのルーティング ヘッダーを設定し、必要に応じて API スキーマ間で変換します。
始める前に
デプロイを続行する前に、環境がすべての必要な前提条件を満たし、必要なコマンドライン ユーティリティが適切に構成されていることを確認してください。ワークステーションにこれらのツールを設定することは、コンテナ レジストリの管理、クラスタとのやり取り、デプロイ プロセスの自動化に不可欠です。
- GDC エアーギャップ 1.16.2-hf1 以降の環境は、Kubernetes v1.32.13-gke.400 以降を実行する標準クラスタで使用できます。
- 十分なリソースを使用して作成された Standard クラスタ。ゲートウェイ コンポーネントは CPU でのみ実行されます。モデル提供バックエンドには独自アクセラレータ要件があります(GDC エアギャップ環境でのオープン ウェイト モデルのガイドをご覧ください)。
- Harbor インスタンスが利用可能でアクセス可能である。
- 必要な IAM が適用されています。
- 環境とインターネットへの接続に必要なワークステーション
環境の構成
環境構成では、ID と権限、ワークステーション、GDC 環境とクラスタへのアクセスについて説明します。
Identity and Access Management
必要な IAM アカウント、ロール、権限が正しく構成されていることを確認します。
プロジェクトに対する GDC ユーザーロール(プロジェクト Namespace の RoleBinding、プロジェクト IAM 管理者によって付与):
- Harbor インスタンス閲覧者(
harbor-instance-viewer) - Harbor プロジェクト作成者(
harbor-project-creator、Harbor プロジェクトがまだ存在しない場合のみ) - 標準クラスタ管理者(
standard-cluster-admin、gdcloud clusters get-credentialsに必要)
標準クラスタの GDC ユーザーロール: 前述のプロジェクト ロールでは、クラスタ内の権限は付与されません。また、プロジェクト IAM 管理者は、管理 API サーバーのプロジェクト Namespace で StandardClusterRoleBinding を使用して、ユーザーを StandardClusterRole cluster-admin にバインドする必要があります。バインディングは、数秒以内にプロジェクトの標準クラスタに伝播されます(status.clusters[].conditions は Propagated=True を示します)。このガイドでは、カスタム リソース定義、ClusterRole、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
次のように置き換えます。
MANAGEMENT_API_SERVER: 管理 API サーバーの kubeconfig ファイルのパス。USER: ユーザー。PROJECT: プロジェクト。
Harbor crane(crane)ロボット アカウントの権限:
- リポジトリを一覧表示する
- リポジトリを pull する
- リポジトリを push する
- アーティファクトの読み取り
- アーティファクトを一覧表示する
- タグを作成
- リストタグ
Harbor Kubernetes イメージ pull(kubernetes-image-puller)ロボット アカウントの権限:
- リポジトリを一覧表示する
- リポジトリを pull する
- アーティファクトの読み取り
- アーティファクトを一覧表示する
- リストタグ
ワークステーション
このガイドでは、環境とインターネットに接続できるワークステーションが必要です。
要件
ワークステーションに次のツールをインストールする必要があります。
crane: レジストリ間でコンテナ イメージと OCI アーティファクトを管理してコピーします(ドキュメント)。gdcloud: GDC リソースを管理するためのコマンドライン インターフェース(CLI)(ドキュメント)。kubectl: Kubernetes クラスタとの通信と管理に使用されるコマンドライン インターフェース(CLI)。helm: Kubernetes 用パッケージ マネージャー(バージョン 3.8 以降、OCI レジストリのサポートあり)(ドキュメント)。curl: URL を使用してデータを転送するためのコマンドライン ツール。jq: 軽量で柔軟なコマンドライン JSON プロセッサ。yq: ポータブル コマンドライン YAML プロセッサ。
このガイドのすべてのコマンドは、手順に別の指示がない限り、ワークステーションから実行します。
ワークステーションの構成
ワークステーションの構成には、環境に関する次の情報が必要です。
GDC_STANDARD_CLUSTER_NAME: GDC Standard クラスタの名前。GDC_DOMAIN_SUFFIX: GDC 環境のドメイン サフィックス(例:gdc.example.com)。GDC_ORG: GDC 組織の名前。GDC_PROJECT: GDC プロジェクトの名前。GDC_ZONE: GDC デプロイ ゾーンの名前。GDC_HARBOR_INSTANCE_NAME: プロジェクト内の Harbor インスタンスの名前。GDCS_HARBOR_PROJECT_NAME: イメージに使用する Harbor プロジェクトの名前(デフォルト:solutions)GDCS_HARBOR_CRANE_ROBOT_NAME: Harborcraneロボット アカウントの名前。GDCS_HARBOR_CRANE_ROBOT_TOKEN: Harborcraneロボット アカウントの認証トークン。GDCS_HARBOR_K8S_ROBOT_NAME: Harbor Kubernetes イメージ pull ロボット アカウントの名前。GDCS_HARBOR_K8S_ROBOT_TOKEN: Harbor Kubernetes イメージ プル ロボット アカウントの認証トークン。
必要なすべての変数の値を収集したら、環境変数ファイルの生成に進みます。作成後、いつでも手動でファイルを編集できます。
ルート ソリューション ディレクトリとシークレット フォルダを作成します。
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/*プラットフォーム環境構成ファイルを作成します。
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次のように置き換えます。
STANDARD_CLUSTER_NAME: GDC Standard クラスタ名。DOMAIN_SUFFIX: GDC ドメイン接尾辞。ORG: GDC 組織。PROJECT: GDC プロジェクト。ZONE: GDC ゾーン。HARBOR_INSTANCE_NAME: GDC Harbor インスタンス名。
レジストリ環境構成ファイルを作成します。
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次のように置き換えます。
HARBOR_CRANE_ROBOT_NAME: GDC Harbor ロボット アカウント名。HARBOR_K8S_ROBOT_NAME: GDC Harbor ロボット アカウント名。
トークンをシークレット ファイルに追加します。
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次のように置き換えます。
CRANE_ROBOT_TOKEN: クレーンロボットのトークン。KUBERNETES_ROBOT_TOKEN: Kubernetes ロボット トークン。
ルート環境ローダー ファイルを作成します。
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
ソリューション変数を構成する
ソリューション実装ディレクトリを作成します。
mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.dソリューション環境構成ファイルを作成します。
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実装環境ローダー ファイルを作成します。
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任意のエディタで環境ファイルを編集して確認します。
${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環境ファイルをソースにします。
source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.sh出力は次のようになります。
GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
GDC
このガイドでは、ワークステーションが GDC 環境と Harbor インスタンスの TLS 証明書を信頼するように構成されていることを前提としています。
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}"GDC 環境に対して認証します。
gdcloud auth login
クラスタ
クラスタの認証情報を取得します。
gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \ --project="${GDC_PROJECT}" \ --standard \ --zone="${GDC_ZONE}"クラスタへの接続を確認します。
kubectl get nodes -L node.cluster.private.gdc.goog/machine-classすべてのノードが、このガイドの始める前にのセクションで求められている Kubernetes バージョンを実行していることを確認します。
kubectl get nodes -o custom-columns='NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion'
アーティファクトの移行の準備
- アーティファクト レジストリの接続と構成を確認します。
crane の Docker 構成ファイルを作成します。ロボット アカウントは、ユーザー アカウントで Managed Harbor Service(MHS)認証情報ヘルパー(docker-credential-mhs)を使用するときに、認証トークンのタイムアウトを回避するために、大きなイメージレイヤを push するために使用されます。
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 historyKubernetes 用の Docker 構成ファイルを作成します。
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 historyKubernetes イメージ pull ロボット アカウントを使用して、
helmで Harbor OCI レジストリにログインします。helmは独自のレジストリ認証情報を保持しており、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出力は次のようになります。
Login Succeededseed_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"seed_charts.shスクリプトを作成します。OCI アーティファクトとして公開された Helm チャートも、プラットフォームの選択やコンテナ イメージ リポジトリに使用されるcreateタグなしでcraneを使用してコピーされます。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"次のように置き換えます。
REGISTRY_HOST: レジストリ ホスト。REPOSITORY: リポジトリ。CHART_VERSION: チャートのバージョン。
ソリューションに必要なコンテナ イメージのリストを定義します。
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)必要なコンテナ イメージをアーティファクト レジストリにシードします。
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
ソリューションに必要な Helm チャートのリストを定義します。
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)必要な Helm チャートをアーティファクト レジストリにシードします。
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shHarbor からチャートを読み取れることを確認します。
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):'出力は次のようになります。
name: gateway-helm version: v1.8.5 name: ai-gateway-helm version: v1.1.0Gateway API Inference Extension マニフェストをダウンロードします。これらは、チャートではなくリリース アセットとして公開されます。
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"出力は次のようになります。
4
Envoy Gateway
Envoy Gateway は最初にインストールされ、アップストリーム クイックスタートで単独で検証されます。Envoy Agent Router の統合については、次のセクションで説明します。
名前空間
Envoy Gateway の Namespace を作成します。この Namespace には、すべての
Gatewayの Envoy プロキシDeploymentも作成されます。kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"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 -
カスタム リソース定義
シードされたチャートから Gateway API(標準チャネル)と Envoy Gateway カスタム リソース定義(CRD)をインストールします。
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=-CRD が登録されていることを確認します。
kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
コントローラ
Envoy Gateway の Helm 値ファイルを作成します。イメージは、イメージ pull シークレットを使用して Harbor から pull されます。これは、CRD が個別にインストールされたためです。
crds.enabled=falsecat <<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 をインストールします。
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}"Envoy Gateway コントローラが使用可能になるまで待ちます。
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'"コントローラのイメージとその証明書生成ジョブが Harbor から取得されていることを確認します。
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Envoy プロキシと Gateway クラス
EnvoyProxyデータプレーン テンプレートとGatewayClassのマニフェストを作成します。EnvoyProxyは、プロキシ イメージ、イメージ プル シークレット、プロキシPodのリソース リクエストを設定します。GatewayClassはユーザーガイドで共有されます。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} EOFEnvoyProxyとGatewayClassのマニフェストを適用します。kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"GatewayClassが Accepted であることを確認します。kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"出力は次のようになります。
NAME CONTROLLER ACCEPTED AGE envoy-ai-gateway gateway.envoyproxy.io/gatewayclass-controller True 5s
検証
検証では、Envoy Gateway クイックスタート(HTTPRoute の背後にあるエコー バックエンド)を Envoy Gateway Namespace にデプロイし、その後削除します。
クイックスタート ワークロードのマニフェストを作成します。
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クイックスタート ワークロードのマニフェストを適用します。
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"Gatewayが Programmed になるまで待ちます。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'"バックエンド
Deploymentが使用可能になるまで待ちます。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'"ポート転送を使用して、Gateway 経由でテスト リクエストを送信します。
Gatewayの EnvoyServiceは、所有ゲートウェイのラベルによって検出されます。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}出力は次のようになります。
{ "path": "/get", "host": "www.example.com", "method": "GET", ... "namespace": "envoy-gateway-system", "pod": "eg-quickstart-backend-...", ... }クイックスタート ワークロードを削除します。
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
Envoy エージェント ルーター
Envoy Agent Router は独自の Namespace にインストールされます。その後、Envoy Gateway が拡張サーバーとして呼び出すように再構成されます。
名前空間
Envoy エージェント ルーター コントローラの Namespace を作成します。
kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"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 -
カスタム リソース定義
シードされたチャートから Envoy エージェント ルーター CRD をインストールします。
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=-ダウンロードしたマニフェストから Gateway API 推論拡張機能 CRD(
InferencePool、InferenceObjective)をインストールします。kubectl apply --server-side \ --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"CRD が登録されていることを確認します。
kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'出力は次のようになります。
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
トークンベースのレート制限は、Envoy レート制限サービスによって適用されます。このサービスは、カウンタを Redis に保存します。このガイドでは、永続性のない単一レプリカの Redis をデプロイします。次のセクションで rateLimit.backend.redis.url の値を変更すると、既存の Redis サービスを代わりに使用できます。
Redis
Deploymentのマニフェストを作成します。cat <<EOF > "${GDCS_IMPLEMENTATION_HOME}/redis.yaml" && echo "Successfully created." || echo "Failed to create!" apiVersion: v1 kind: Service metadata: name: redis labels: app: redis spec: ports: - name: redis port: 6379 selector: app: redis --- apiVersion: apps/v1 kind: Deployment metadata: name: redis spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - image: ${GDCS_HARBOR_PROJECT_URI}/library/redis:${GDCS_REDIS_IMAGE_TAG} imagePullPolicy: IfNotPresent name: redis ports: - name: redis containerPort: 6379 resources: limits: memory: 512Mi requests: cpu: 100m memory: 128Mi imagePullSecrets: - name: ${GDCS_HARBOR_K8S_PULL_SECRET} restartPolicy: Always EOFRedis
Deploymentのマニフェストを適用します。kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"Redis
Deploymentが使用可能になるまで待ちます。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'"
コントローラ
Envoy Agent Router の Helm 値ファイルを作成します。
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 エージェント ルーターをインストールします。
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}"Envoy Agent Router コントローラが使用可能になるまで待ちます。
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 の統合
Envoy Gateway を再構成して、Envoy Agent Router コントローラを拡張サーバーとして呼び出し、InferencePool リソースをバックエンドとして受け入れ、Redis ベースのレート制限サービスを使用する必要があります。
インテグレーションの Helm 値ファイルを作成します。
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両方の値ファイルを使用して 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" \ --values="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-agent-router-values.yaml" \ --version="${GDCS_ENVOY_GATEWAY_VERSION}"Envoy Gateway コントローラが
InferencePoolリソースを監視できるようにするClusterRoleのマニフェストを作成します。この権限はグラフによって付与されません。グラフで管理されるClusterRoleのパッチとは異なり、個別のClusterRoleBindingはグラフのアップグレード後も存続します。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} EOFClusterRoleのマニフェストを適用します。kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"新しい構成と権限を読み込むように Envoy Gateway コントローラを再起動し、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レート制限サービスがデプロイされ、使用可能であることを確認します。
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'"
検証
検証では、Envoy Agent Router の基本的な例(AIGatewayRoute の背後にある OpenAI 互換のモック アップストリーム)を Envoy Agent Router Namespace にデプロイし、その後削除します。
検証ワークロードのマニフェストを作成します。
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検証ワークロードのマニフェストを適用します。
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Gatewayが Programmed になるまで待ちます。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'"モック アップストリーム
Deploymentが使用可能になるまで待ちます。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'"Envoy プロキシ
GatewayのPodが、Envoy エージェント ルーターによって挿入された外部プロセッサ サイドカーを実行していることを確認します。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}'出力は次のようになります。
envoy-envoy-ai-gateway-system-aieg-basic-... envoy shutdown-manager ai-gateway-extprocポート転送を使用して、ゲートウェイ経由でチャット完了リクエストを送信します。外部プロセッサは、リクエスト本文の
modelフィールドを読み取り、モック アップストリームに転送します。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}出力は次のようになります。
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { ... } }検証ワークロードを削除します。
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
運用
ゲートウェイ コントロール プレーンの 2 日目のタスク。
アップグレード
- 新しいバージョンのイメージとチャートをシードし(
env.shのバージョン変数を更新し、seed_registry.shとseed_charts.shを再実行)、kubectl apply --server-sideで新しい CRD チャートを適用してから、新しい--versionで同じhelm upgrade --installコマンドを実行します。ターゲット リリースでサポートされている Envoy Gateway と Gateway API のバージョンについては、Envoy Agent Router の互換性マトリックスをご覧ください。Envoy Agent Router 1.1.0 は Envoy Gateway 1.8 に対してビルドされています。
アンインストール
- まず、ユーザーガイドの
Gateway、AIGatewayRoute、InferencePoolリソースを削除し、次にhelm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"、helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"、ClusterRoleenvoy-gateway-inferencepool-reader、GatewayClass、RedisDeployment、最後に CRD を削除します。
トラブルシューティング
| 症状 | 考えられる原因 | アクション |
|---|---|---|
helm show chart または helm upgrade が unauthorized または FetchReference で失敗する |
helm に Harbor の認証情報がない(crane Docker 構成を使用していない) |
Kubernetes イメージ pull ロボット アカウントを使用して helm registry login ステップを再度実行します。 |
Envoy Gateway または Envoy Agent Router の Pod が ImagePullBackOff のままになる |
イメージがシードされていないか、イメージ pull シークレットが Namespace にない | kubectl describe pod を確認し、イメージパスを crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway" と比較して、シークレットが ${GDCS_ENVOY_GATEWAY_NAMESPACE} と ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} に存在することを確認します。 |
統合後も Gateway は Programmed=False のまま |
Envoy Gateway コントローラが拡張機能サーバーに到達できないか、アップグレード後に再起動されていない | kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"。service/ai-gateway-controller が ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} に存在し、ポート 1063 がリストされていることを確認し、ロールアウトの再起動を繰り返します。 |
InferencePool を参照する AIGatewayRoute が承認されない |
Envoy Gateway に inferencepools を読み取る権限がないか、InferencePool CRD がありません |
ClusterRoleBinding envoy-gateway-inferencepool-reader と inferencepools.inference.networking.k8s.io CRD を確認し、コントローラのログで forbidden を確認します。 |
チャット完了リクエストが 413 を返すか、大きなプロンプトで接続がリセットされる |
デフォルトの Envoy バッファの上限(32 KiB)が AI ペイロードに対して小さすぎる | connection.bufferLimit(検証では 50Mi を使用)を含む ClientTrafficPolicy を Gateway に関連付けます。 |
レート制限サービス Pod は CrashLoopBackOff です |
構成された URL で Redis にアクセスできない | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}"。統合値ファイルで rateLimit.backend.redis.url を修正して、再度アップグレードします。 |
その他の教材
- Envoy Agent Router のドキュメント
- Envoy Agent Router のリリースノートと互換性マトリックス
- Envoy Gateway のドキュメント
- Kubernetes Gateway API
- Gateway API 推論拡張機能
- 標準クラスタを作成する | Google Distributed Cloud エアギャップ