Este documento fornece instruções detalhadas para implantar um gateway de IA em ambientes com isolamento físico do Google Distributed Cloud (GDC). O gateway é criado com base no Envoy Gateway, a implementação da API Kubernetes Gateway baseada no proxy Envoy, e no Envoy Agent Router (antigo Envoy AI Gateway), a extensão que transforma o Envoy Gateway em um ponto de entrada unificado e compatível com a OpenAI para o tráfego de modelos de linguagem grandes (LLMs). Ele aborda a propagação das imagens de contêiner e dos gráficos do Helm no registro local do Harbor, a instalação dos dois planos de controle em um cluster padrão, a preparação do back-end opcional de limitação de taxa com base em token e a validação da instalação com cargas de trabalho de amostra.
Os back-ends de disponibilização de modelos (Ollama, vLLM) são implantados com o conjunto de guias Modelos de pesos abertos no GDC com isolamento físico. O guia do usuário de roteamento baseado em corpo com o roteador do agente do Envoy mostra como rotear solicitações para eles por nome de modelo.
Arquitetura
A solução é executada em um cluster padrão do GDC. Uma
estação de trabalho de administrador envia as imagens e os gráficos do Helm para o registro do Harbor
do projeto e instala os dois planos de controle: o controlador do Envoy Gateway, que programa o plano de dados do proxy do Envoy com base nos recursos da API Gateway
(GatewayClass, Gateway, HTTPRoute), e o controlador do Envoy Agent Router,
que estende esse plano de dados com um processador externo (ExtProc) para tráfego
de IA (AIGatewayRoute, AIServiceBackend, InferencePool). Os clientes
do aplicativo enviam solicitações compatíveis com a OpenAI para o proxy do Envoy, que as encaminha para
os back-ends de disponibilização do modelo ou InferencePools. Uma instância opcional do Redis
armazena os contadores do serviço de limitação de taxa do Envoy para limitação de taxa
com base em token.

Gateway do Envoy
O Gateway do Envoy é um projeto de código aberto, criado
no proxy do Envoy, que simplifica a adoção, o uso
e o gerenciamento do proxy do Envoy como um gateway de API do Kubernetes. Ele implementa e
estende a API Kubernetes Gateway, a
sucessora da API Ingress: os recursos GatewayClass e Gateway descrevem
os pontos de entrada, os recursos de rota, como HTTPRoute, descrevem como o tráfego é
correspondido e encaminhado, e o design orientado a papéis separa as
responsabilidades das equipes de infraestrutura e de aplicativos. O Envoy Gateway adiciona as próprias APIs de extensão, por exemplo, EnvoyProxy (configurações do plano de dados), Backend (endpoints fora do cluster ou referenciados por FQDN) e ClientTrafficPolicy (configurações de conexão, como limites de buffer).
Roteador do agente do Envoy
O Envoy Agent Router (antigo Envoy AI Gateway) é um projeto de código aberto que usa o Envoy Gateway para processar o tráfego de solicitações de clientes de aplicativos para serviços de IA generativa. Ele fornece uma
camada unificada para rotear e gerenciar o tráfego de LLM com roteamento com reconhecimento de modelo,
autenticação upstream, limitação de taxa e observabilidade baseadas em token, além de
se integrar à Extensão de inferência da API
Gateway
(InferencePool, seletor de endpoint) para seleção de endpoint com reconhecimento de métricas. O
controlador monitora os recursos aigateway.envoyproxy.io/v1beta1 e injeta
um processador externo ao lado do proxy do Envoy. O processador externo analisa o
corpo da solicitação (por exemplo, o campo model de uma solicitação de conclusão de chat
da OpenAI), define cabeçalhos de roteamento, como x-ai-eg-model, e traduz entre
esquemas de API, quando necessário.
Antes de começar
Antes de prosseguir com a implantação, verifique se o ambiente atende a todos os pré-requisitos necessários e se os utilitários de linha de comando necessários estão configurados corretamente. Configurar essas ferramentas na estação de trabalho é essencial para gerenciar Container Registry, interagir com clusters e automatizar o processo de implantação.
- O ambiente do GDC com isolamento físico 1.16.2-hf1 ou mais recente está disponível com um cluster padrão que executa o Kubernetes v1.32.13-gke.400 ou mais recente.
- Cluster padrão criado com recursos suficientes. Os componentes do gateway são executados apenas na CPU. Os back-ends de disponibilização de modelos têm os próprios requisitos de acelerador (consulte os guias Modelos de pesos abertos no GDC com isolamento físico).
- Instância do Harbor disponível e acessível.
- O IAM necessário foi aplicado.
- Estação de trabalho com a conectividade necessária com o ambiente e a Internet
Configuração do ambiente
A configuração do ambiente abrange as identidades e permissões, a estação de trabalho e o acesso ao ambiente do GDC e ao cluster.
Identity and Access Management
Verifique se as contas, os papéis e as permissões necessários do IAM estão configurados corretamente.
Papéis de usuário do GDC no projeto (RoleBinding no
namespace do projeto, concedido por um administrador do IAM no projeto):
- Leitor de instâncias do Harbor (
harbor-instance-viewer) - Criador de projetos do Harbor (
harbor-project-creator, somente se o projeto do Harbor ainda não existir) - Administrador de cluster padrão (
standard-cluster-admin, obrigatório paragdcloud clusters get-credentials)
Papel de usuário do GDC no cluster padrão: os papéis do projeto anteriores não concedem permissões dentro do cluster. Um administrador do IAM do projeto também precisa vincular o usuário ao StandardClusterRole cluster-admin com um StandardClusterRoleBinding no namespace do projeto no servidor de API de gerenciamento. A vinculação é propagada para os clusters padrão do projeto em segundos (status.clusters[].conditions mostra Propagated=True). As permissões em todo o cluster são necessárias porque este guia instala definições de recursos personalizados, ClusterRoles e um 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
Substitua:
MANAGEMENT_API_SERVER: o caminho para o arquivo kubeconfig do servidor de API de gerenciamento.USER: usuário.PROJECT: projeto.
Permissões da conta de robô do Harbor crane (crane):
- Listar repositório
- Repositório de pull
- Repositório de push
- Ler artefato
- Listar artefato
- Criar tag
- Tag de lista
Permissões da conta de robô de extração de imagens do Kubernetes do Harbor (kubernetes-image-puller):
- Listar repositório
- Repositório de pull
- Ler artefato
- Listar artefato
- Tag de lista
Estação de trabalho
Execute todos os comandos deste guia em uma estação de trabalho com as ferramentas e a conectividade necessárias para o ambiente e a Internet, a menos que uma etapa indique o contrário.
Requisitos
As seguintes ferramentas precisam ser instaladas na estação de trabalho:
crane: gerenciar e copiar imagens de contêiner e artefatos OCI entre registros (documentação).gdcloud: interface de linha de comando (CLI) para gerenciar recursos do GDC (documentação).kubectl: interface de linha de comando (CLI) usada para se comunicar com um cluster do Kubernetes e gerenciá-lo.helm: gerenciador de pacotes para Kubernetes, versão 3.8 ou mais recente (suporte ao registro OCI) (documentação).curl: ferramenta de linha de comando para transferir dados com URLs.jq: processador JSON de linha de comando leve e flexível.yq: processador YAML de linha de comando portátil.
Execute todos os comandos deste guia na estação de trabalho, a menos que uma etapa indique o contrário.
Configuração da estação de trabalho
As seguintes informações sobre o ambiente são necessárias para a configuração da estação de trabalho:
GDC_STANDARD_CLUSTER_NAME: o nome do cluster padrão do GDC.GDC_DOMAIN_SUFFIX: o sufixo de domínio do ambiente do GDC (por exemplo,gdc.example.com).GDC_ORG: o nome da organização do GDC.GDC_PROJECT: o nome do projeto do GDC.GDC_ZONE: o nome da zona de implantação do GDC.GDC_HARBOR_INSTANCE_NAME: o nome da instância do Harbor no projeto.GDCS_HARBOR_PROJECT_NAME: o nome do projeto do Harbor a ser usado para a imagem (padrão:solutions)GDCS_HARBOR_CRANE_ROBOT_NAME: o nome da conta de robô do Harborcrane.GDCS_HARBOR_CRANE_ROBOT_TOKEN: o token de autenticação da conta de robô do Harborcrane.GDCS_HARBOR_K8S_ROBOT_NAME: o nome da conta de robô de extração de imagens do Kubernetes do Harbor.GDCS_HARBOR_K8S_ROBOT_TOKEN: o token de autenticação da conta do robô de extração de imagens do Kubernetes do Harbor.
Depois de coletar os valores de todas as variáveis necessárias, gere o arquivo de variáveis de ambiente. Depois de criado, é possível editar o arquivo manualmente a qualquer momento.
Crie os diretórios raiz da solução e a pasta de 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/*Crie o arquivo de configuração do ambiente da plataforma:
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}" EOFSubstitua:
STANDARD_CLUSTER_NAME: nome do cluster padrão do GDC.DOMAIN_SUFFIX: sufixo de domínio do GDC.ORG: organização do GDC.PROJECT: projeto do GDC.ZONE: zona do GDC.HARBOR_INSTANCE_NAME: nome da instância do GDC Harbor.
Crie o arquivo de configuração do ambiente de registro:
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}" EOFSubstitua:
HARBOR_CRANE_ROBOT_NAME: nome da conta de robô do GDC Harbor.HARBOR_K8S_ROBOT_NAME: nome da conta de robô do GDC Harbor.
Adicione os tokens aos arquivos de secrets:
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 historySubstitua:
CRANE_ROBOT_TOKEN: token do robô do Crane.KUBERNETES_ROBOT_TOKEN: token de robô do Kubernetes.
Crie o arquivo do carregador de ambiente raiz:
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
Configurar variáveis de solução
Crie o diretório de implementação da solução:
mkdir -p ${HOME}/gdcag-solutions/ai-gateway/envoy/env.dCrie o arquivo de configuração do ambiente da solução:
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" EOFCrie o arquivo do carregador do ambiente de implementação:
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" EOFEdite e revise os arquivos de ambiente com seu editor preferido:
${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.shUse o comando source no arquivo de ambiente:
source ${HOME}/gdcag-solutions/ai-gateway/envoy/env.shO resultado será o seguinte:
GDCS_ROOT_HOME=HOME_DIRECTORY_PATH/gdcag-solutions GDCS_IMPLEMENTATION_HOME=HOME_DIRECTORY_PATH/gdcag-solutions/ai-gateway/envoy
GDC
Este guia pressupõe que sua estação de trabalho está configurada para confiar nos certificados TLS do ambiente do GDC e da instância do Harbor.
Configurar
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}"Autentique-se no ambiente do GDC:
gdcloud auth login
Cluster
Recupere as credenciais do cluster:
gdcloud clusters get-credentials "${GDC_STANDARD_CLUSTER_NAME}" \ --project="${GDC_PROJECT}" \ --standard \ --zone="${GDC_ZONE}"Verifique a conectividade com o cluster:
kubectl get nodes -L node.cluster.private.gdc.goog/machine-class
Preparação para a migração de artefatos
- Verifique a conectividade e a configuração do Artifact Registry.
Crie um arquivo de configuração do Docker para o crane. Uma conta de robô é usada para enviar grandes camadas de imagem para evitar tempos limite de token de autenticação ao usar o auxiliar de credenciais do Serviço Gerenciado do Harbor (MHS, na sigla em inglês) (docker-credential-mhs) com uma conta de usuário:
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 historyCrie um arquivo de configuração do Docker para o 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 historyFaça login no registro de OCI do Harbor com
helmusando a conta de robô de extração de imagens do Kubernetes. Ohelmmantém as próprias credenciais de registro e precisa delas para buscar os gráficos do Harbor:set +o history helm registry login "${GDC_HARBOR_HOST}" \ --password="${GDCS_HARBOR_K8S_ROBOT_TOKEN}" \ --username="${GDCS_HARBOR_K8S_ROBOT_NAME}" set -o historyO resultado será o seguinte:
Login SucceededCrie o script
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"Crie o script
seed_charts.sh. Os gráficos do Helm publicados como artefatos OCI também são copiados comcrane, sem seleção de plataforma e sem a tagcreateusada para repositórios de imagens de contêiner: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"Substitua:
REGISTRY_HOST: host do registro.REPOSITORY: repositório.CHART_VERSION: versão do gráfico.
Defina a lista de imagens de contêiner necessárias para a solução:
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)Envie as imagens de contêiner necessárias para o Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
Defina a lista de gráficos do Helm necessários para a solução:
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)Envie os gráficos do Helm necessários para o Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shVerifique se os gráficos podem ser lidos no 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):'O resultado será o seguinte:
name: gateway-helm version: v1.8.5 name: ai-gateway-helm version: v1.1.0Faça o download dos manifestos da extensão de inferência da API Gateway. Eles são publicados como um recurso de lançamento, não como um gráfico:
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"O resultado será o seguinte:
4
Gateway do Envoy
O Envoy Gateway é instalado primeiro e validado por conta própria com o guia de início rápido upstream. A integração do Envoy Agent Router é mostrada na próxima seção.
Namespace
Crie o namespace para o Envoy Gateway. Os
Deployments de proxy do Envoy de cadaGatewaytambém são criados nesse namespace:kubectl create namespace "${GDCS_ENVOY_GATEWAY_NAMESPACE}"Adicione o
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 -
Definições de recursos do Kubernetes
Instale a API Gateway (canal padrão) e as definições de recursos personalizados (CRDs) do Envoy Gateway do gráfico de sementes:
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=-Verifique se as CRDs estão registradas:
kubectl get crd | grep -E 'gateway.networking.k8s.io|gateway.envoyproxy.io'
Controlador
Crie o arquivo de valores do Helm para o Envoy Gateway. As imagens são extraídas do Harbor com o secret de extração de imagem;
crds.enabled=falseporque as CRDs foram instaladas separadamente: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} EOFInstale o 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}"Aguarde até que o controlador do Envoy Gateway esteja disponível:
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'"Verifique se as imagens do controlador e o job de geração de certificados são do Harbor:
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Proxy Envoy e classe de gateway
Crie o manifesto para o modelo de plano de dados
EnvoyProxye oGatewayClass. OEnvoyProxydefine a imagem do proxy, o secret de extração de imagem e as solicitações de recursos dosPods do proxy. OGatewayClassé compartilhado pelos guias do usuário: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} EOFAplique o manifesto para
EnvoyProxyeGatewayClass:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/gateway-class.yaml"Verifique se o
GatewayClassfoi aceito:kubectl get gatewayclass "${GDCS_GATEWAY_CLASS_NAME}"O resultado será o seguinte:
NAME CONTROLLER ACCEPTED AGE envoy-ai-gateway gateway.envoyproxy.io/gatewayclass-controller True 5s
Validação
A validação implanta o guia de início rápido do Envoy Gateway (um back-end de eco por trás de um
HTTPRoute) no namespace do Envoy Gateway e o remove em seguida.
Crie o manifesto para a carga de trabalho do guia de início rápido:
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: / EOFAplique o manifesto para a carga de trabalho do guia de início rápido:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"Aguarde até que o
Gatewayseja programado: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'"Aguarde até que o back-end
Deploymentesteja disponível: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'"Envie uma solicitação de teste pelo gateway usando o encaminhamento de portas. O
Servicedo Envoy de umGatewayé encontrado pelos rótulos do gateway proprietário: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}O resultado será o seguinte:
{ "path": "/get", "host": "www.example.com", "method": "GET", ... "namespace": "envoy-gateway-system", "pod": "eg-quickstart-backend-...", ... }Remova a carga de trabalho do guia de início rápido:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/eg-quickstart.yaml" \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"
Roteador do agente do Envoy
O roteador do agente do Envoy é instalado no próprio namespace. Em seguida, o gateway do Envoy é reconfigurado para chamá-lo como servidor de extensão.
Namespace
Crie o namespace para o controlador do roteador do agente do Envoy:
kubectl create namespace "${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Adicione o
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 -
Definições de recursos do Kubernetes
Instale os CRDs do roteador do agente do Envoy do gráfico propagado:
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=-Instale os CRDs da extensão de inferência da API Gateway (
InferencePool,InferenceObjective) dos manifestos baixados:kubectl apply --server-side \ --filename="${GDCS_IMPLEMENTATION_HOME}/manifests/gateway-api-inference-extension-${GDCS_GATEWAY_API_INFERENCE_EXTENSION_VERSION}.yaml"Verifique se as CRDs estão registradas:
kubectl get crd | grep -E 'aigateway.envoyproxy.io|inference.networking'O resultado será o seguinte:
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
A limitação de taxa baseada em token é aplicada pelo serviço de limitação de taxa do Envoy, que
armazena os contadores no Redis. Este guia implanta um Redis de réplica única sem
persistência. É possível usar um serviço Redis atual alterando o
valor rateLimit.backend.redis.url na próxima seção.
Crie o manifesto para o
Deploymentdo 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 EOFAplique o manifesto para o
Deploymentdo Redis:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"Aguarde até que o
Deploymentdo Redis esteja disponível: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'"
Controlador
Crie o arquivo de valores do Helm para o roteador de agente do Envoy:
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} EOFInstale o roteador do agente do Envoy:
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}"Aguarde até que o controlador do roteador do agente do Envoy esteja disponível:
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'"
Integração do gateway do Envoy
O Envoy Gateway precisa ser reconfigurado para chamar o controlador do roteador do agente do Envoy como
servidor de extensão, aceitar recursos InferencePool como back-ends e usar
o serviço de limitação de taxa com suporte do Redis.
Crie o arquivo de valores do Helm para a integração:
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 EOFFaça upgrade do gateway do Envoy com os dois arquivos de valores:
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}"Crie o manifesto para o
ClusterRoleque permite que o controlador do Envoy Gateway assista aos recursosInferencePool. O gráfico não concede essa permissão. UmClusterRoleBindingseparado sobrevive aos upgrades do gráfico, ao contrário de um patch doClusterRolegerenciado pelo gráfico: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} EOFAplique o manifesto para
ClusterRole:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"Reinicie o controlador do gateway do Envoy para que ele receba as novas configurações e permissões e aguarde até que ele esteja disponível:
kubectl rollout restart deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" kubectl rollout status deployment/envoy-gateway \ --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --timeout=5mVerifique se o serviço de limitação de taxa foi implantado e está disponível:
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'"
Validação
A validação implanta o exemplo básico do roteador de agente do Envoy (um upstream simulado
compatível com a OpenAI por trás de um AIGatewayRoute) no namespace do roteador de agente do
Envoy e o remove em seguida.
Crie o manifesto para a carga de trabalho de validação:
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 EOFAplique o manifesto para a carga de trabalho de validação:
kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"Aguarde até que o
Gatewayseja programado: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'"Aguarde até que o upstream simulado
Deploymentesteja disponível: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'"Verifique se o proxy Envoy
PoddoGatewayexecuta a injeção de sidecar do processador externo injetado pelo roteador do agente 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}'O resultado será o seguinte:
envoy-envoy-ai-gateway-system-aieg-basic-... envoy shutdown-manager ai-gateway-extprocEnvie uma solicitação de conclusão de chat pelo gateway usando o encaminhamento de portas. O processador externo lê o campo
modeldo corpo da solicitação e o encaminha para o upstream simulado: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}O resultado será o seguinte:
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { ... } }Remova a carga de trabalho de validação:
kubectl delete \ --filename="${GDCS_IMPLEMENTATION_HOME}/aieg-basic.yaml" \ --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}"
Operações
Tarefas do dia dois para os planos de controle do gateway.
Fazer upgrade
- Propague as imagens e os gráficos das novas versões (atualize as variáveis de versão
em
env.sh, execute novamenteseed_registry.sheseed_charts.sh), aplique os novos gráficos de CRD comkubectl apply --server-sidee execute os mesmos comandoshelm upgrade --installcom o novo--version. Verifique a matriz de compatibilidade do roteador do agente do Envoy para ver as versões do Envoy Gateway e da API Gateway compatíveis com a versão de destino. O roteador do agente do Envoy 1.1.0 é criado com base no Envoy Gateway 1.8.
Desinstalar
- Exclua os recursos
Gateway,AIGatewayRouteeInferencePooldos guias do usuário primeiro, depoishelm uninstall aieg --namespace="${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}",helm uninstall eg --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}", oClusterRoleenvoy-gateway-inferencepool-reader, oGatewayClass, o RedisDeploymente, por fim, os CRDs.
Solução de problemas
| Sintoma | Causa provável | Ação |
|---|---|---|
helm show chart ou helm upgrade falha com unauthorized ou FetchReference |
O helm não tem credenciais para o Harbor (ele não usa a configuração do Docker crane). |
Execute a etapa helm registry login novamente com a conta de robô de extração de imagens do Kubernetes. |
Os Pods do Envoy Gateway ou do Envoy Agent Router permanecem em ImagePullBackOff |
A imagem não foi propagada ou o secret de extração de imagem está ausente no namespace | Verifique kubectl describe pod, compare o caminho da imagem com crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway" e confirme se o secret existe em ${GDCS_ENVOY_GATEWAY_NAMESPACE} e ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE}. |
Gateway permanece Programmed=False após a integração |
O controlador do Envoy Gateway não consegue acessar o servidor de extensão ou não foi reiniciado após o upgrade. | kubectl logs deployment/envoy-gateway --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}"; confirme se service/ai-gateway-controller existe em ${GDCS_ENVOY_AGENT_ROUTER_NAMESPACE} e se a porta 1063 está listada; repita a reinicialização do lançamento. |
AIGatewayRoute que faz referência a um InferencePool não é aceito |
O Envoy Gateway não tem permissão para ler inferencepools ou os CRDs InferencePool estão ausentes |
Verifique o envoy-gateway-inferencepool-reader de ClusterRoleBinding e a CRD inferencepools.inference.networking.k8s.io. Verifique os registros do controlador para forbidden. |
A solicitação de conclusão de chat retorna 413 ou a conexão é redefinida para comandos grandes |
O limite de buffer padrão do Envoy (32 KiB) é muito pequeno para payloads de IA | Anexe um ClientTrafficPolicy com connection.bufferLimit (a validação usa 50 Mi) ao Gateway. |
O serviço de limitação de taxa Pod é CrashLoopBackOff |
Não é possível acessar o Redis no URL configurado | kubectl get service redis --namespace="${GDCS_REDIS_NAMESPACE}"; corrija rateLimit.backend.redis.url no arquivo de valores de integração e faça upgrade novamente. |
Outros recursos
- Documentação do roteador de agentes do Envoy
- Notas da versão e matriz de compatibilidade do roteador do agente do Envoy
- Documentação do Envoy Gateway
- API Kubernetes Gateway
- Extensão de inferência da API Gateway
- Criar um cluster padrão | Google Distributed Cloud com isolamento físico
Criar projetos do Harbor | Google Distributed Cloud com isolamento físico
Guia do usuário de roteamento baseado no corpo com o roteador de agente do Envoy