このドキュメントでは、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 Agent Router を使用した本文ベースのルーティングのユーザーガイドでは、モデル名でリクエストをルーティングする方法について説明しています。
アーキテクチャ
このソリューションは GDC 標準クラスタで実行されます。管理者ワークステーションは、イメージと Helm チャートをプロジェクトの Harbor レジストリにシードし、2 つのコントロール プレーンをインストールします。1 つは、Gateway API リソース(GatewayClass、Gateway、HTTPRoute)から Envoy プロキシ データプレーンをプログラムする Envoy Gateway コントローラです。もう 1 つは、AI トラフィック(AIGatewayRoute、AIServiceBackend、InferencePool)用の外部プロセッサ(ExtProc)を使用してそのデータプレーンを拡張する Envoy Agent Router コントローラです。アプリケーション クライアントは、OpenAI 互換のリクエストを Envoy プロキシに送信します。Envoy プロキシは、リクエストをモデル提供バックエンドまたは InferencePool にルーティングします。オプションの Redis インスタンスには、トークンベースのレート制限用の Envoy レート制限サービスのカウンタが保存されます。

Envoy Gateway
Envoy Gateway は、Envoy プロキシをベースに構築されたオープンソース プロジェクトです。Envoy プロキシを Kubernetes API Gateway として採用、使用、管理することを簡素化します。これは、Ingress API の後継である Kubernetes Gateway API を実装して拡張します。GatewayClass リソースと Gateway リソースはエントリ ポイントを記述し、HTTPRoute などのルートリソースはトラフィックの照合方法と転送方法を記述します。ロール指向の設計により、インフラストラクチャ チームとアプリケーション チームの責任が分離されます。Envoy Gateway は、EnvoyProxy(データプレーン設定)、Backend(クラスタ外のエンドポイントまたは FQDN で参照されるエンドポイント)、ClientTrafficPolicy(バッファ制限などの接続設定)などの独自の拡張 API を追加します。
Envoy Agent Router
Envoy Agent Router(旧 Envoy AI Gateway)は、Envoy Gateway を使用してアプリケーション クライアントから生成 AI サービスへのリクエスト トラフィックを処理するオープンソース プロジェクトです。モデル認識ルーティング、アップストリーム認証、トークンベースのレート制限、オブザーバビリティを備えた LLM トラフィックのルーティングと管理のための統合レイヤを提供します。また、Gateway API Inference Extension(InferencePool、エンドポイント ピッカー)と統合して、指標を認識したエンドポイントの選択を行います。コントローラは aigateway.envoyproxy.io/v1beta1 リソースを監視し、Envoy プロキシの横に外部プロセッサを挿入します。外部プロセッサは、リクエスト本文(OpenAI チャット補完リクエストの model フィールドなど)を解析し、x-ai-eg-model などのルーティング ヘッダーを設定し、必要に応じて API スキーマ間で変換します。
始める前に
デプロイに進む前に、環境が必要な前提条件をすべて満たしていること、必要なコマンドライン ユーティリティが適切に構成されていることを確認してください。ワークステーションにこれらのツールを設定することは、Container Registry の管理、クラスタとのやり取り、デプロイ プロセスの自動化に不可欠です。
- GDC エアギャップ 1.16.2-hf1 以降の環境は、Kubernetes v1.32.13-gke.400 以降を実行する標準クラスタで使用できます。
- 十分なリソースを使用して作成された Standard クラスタ。ゲートウェイ コンポーネントは CPU のみで実行されます。モデル提供バックエンドには、独自のアクセラレータ要件があります(GDC エアギャップのオープン ウェイト モデルのガイドをご覧ください)。
- Harbor インスタンスが利用可能で、アクセスできる。
- 必要な IAM が適用されている。
- 環境とインターネットへの必要な接続性を備えたワークステーション
環境の構成
環境構成には、ID と権限、ワークステーション、GDC 環境とクラスタへのアクセスが含まれます。
Identity and Access Management
必要な IAM アカウント、ロール、権限が正しく構成されていることを確認します。
プロジェクトに対する GDC ユーザーロール(プロジェクト名前空間の RoleBinding、IAM プロジェクト管理者によって付与):
- Harbor インスタンス閲覧者(
harbor-instance-viewer) - Harbor プロジェクト作成者(
harbor-project-creator、Harbor プロジェクトがまだ存在しない場合のみ) - 標準クラスタ管理者(
standard-cluster-admin、gdcloud clusters get-credentialsに必要)
標準クラスタに対する GDC ユーザーロール: 前述のプロジェクト ロールでは、クラスタ内の権限は付与されません。プロジェクト IAM 管理者は、管理 API サーバーのプロジェクト名前空間で 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 標準クラスタの名前。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 イメージ pull ロボット アカウントの認証トークン。
必要なすべての変数の値を収集したら、環境変数ファイルの生成に進みます。作成後は、いつでもファイルを手動で編集できます。
ルート ソリューション ディレクトリと 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/*プラットフォーム環境構成ファイルを作成します。
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 標準クラスタ名。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
アーティファクトの移行の準備
- Artifact Registry の接続性と構成を確認します。
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 チャートもcraneでコピーされます。プラットフォームの選択はなく、コンテナ イメージ リポジトリに使用されるcreateタグもありません。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)必要なコンテナ イメージを Artifact Registry にシードします。
${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 チャートを Artifact Registry にシードします。
${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 を作成します。すべての
Gatewayの Envoy プロキシDeploymentも、この Namespace に作成されます。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=falseです。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 をインストールします。
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は、プロキシ イメージ、イメージ pull シークレット、プロキシ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がプログラムされるまで待ちます。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の 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 Agent Router
Envoy Agent Router は独自の名前空間にインストールされます。その後、Envoy Gateway は、拡張サーバーとして呼び出すように再構成されます。
名前空間
Envoy Agent Router コントローラの 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 Agent Router 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 Inference Extension 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 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}"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 コントローラを再起動して、新しい構成と権限を取得し、使用可能になるまで待ちます。
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がプログラムされるまで待ちます。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'"Gatewayの Envoy プロキシPodが、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}'出力は次のようになります。
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 シークレットがない | 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 Inference Extension
- 標準クラスタを作成する | Google Distributed Cloud エアギャップ