Este documento fornece instruções detalhadas para implantar um gateway de IA em ambientes isolados 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 tráfego de modelos de linguagem grandes (LLMs). Ele aborda o seeding 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 baseada em token e a validação da instalação com cargas de trabalho de exemplo.
Os back-ends de disponibilização de modelos (Ollama, vLLM) são implantados com o conjunto complementar de guias Modelos de peso aberto em GDC isolado por ar. O Guia do usuário de roteamento baseado em corpo com o roteador de agente do Envoy mostra como rotear solicitações para eles por nome do 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 Envoy com recursos da API Gateway (GatewayClass, Gateway, HTTPRoute), e o controlador do roteador do agente Envoy, que estende esse plano de dados com um processador externo (ExtProc) para tráfego de IA (AIGatewayRoute, AIServiceBackend, InferencePool). Os clientes de aplicativos enviam solicitações compatíveis com a OpenAI para o proxy 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 baseada em token.

Envoy Gateway
O Envoy Gateway é 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. Ela 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 de 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. Ela fornece uma camada unificada para roteamento e gerenciamento do tráfego de LLMs com roteamento compatível com modelos, autenticação upstream, limitação de taxa baseada em token e capacidade de observação. Além disso, ela se integra à Extensão de inferência da API Gateway (InferencePool, seletor de endpoints) para seleção de endpoints com reconhecimento de métricas. O
controlador monitora os recursos aigateway.envoyproxy.io/v1beta1 e injeta
um processador externo ao lado do proxy 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 faz a tradução entre
esquemas de API quando necessário.
Antes de começar
Antes de continuar 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 exigidos estão configurados corretamente. Configurar essas ferramentas na sua estação de trabalho é essencial para gerenciar registros de contêineres, interagir com clusters e automatizar o processo de implantação.
- O ambiente 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 de gateway são executados apenas na CPU. Os back-ends de disponibilização do modelo têm requisitos próprios de acelerador (consulte os guias Modelos de peso aberto no GDC air-gapped).
- Uma instância do Harbor disponível e acessível.
- O IAM necessário foi aplicado.
- Estação de trabalho com a conectividade necessária ao ambiente e à 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árias do IAM estão configurados corretamente.
Papéis de usuário do GDC no projeto (RoleBinding no namespace do projeto, concedidos por um administrador do IAM do 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 do cluster padrão (
standard-cluster-admin, necessário paragdcloud clusters get-credentials)
Papel Usuário do GDC no cluster padrão: os papéis de 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 da API de gerenciamento. A vinculação é propagada para os clusters padrão do projeto em segundos (status.clusters[].conditions mostra Propagated=True). São necessárias permissões em todo o cluster 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 da API de gerenciamento.USER: usuário.PROJECT: projeto.
Permissões da conta de robô do Harbor crane (crane):
- Listar repositório
- Extrair repositório
- 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
- Extrair repositório
- Ler artefato
- Listar artefato
- Tag de lista
Estação de trabalho
Este guia exige uma estação de trabalho com a conectividade necessária ao ambiente e à Internet.
Requisitos
As seguintes ferramentas precisam ser instaladas na estação de trabalho:
crane: gerencie e copie 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 portátil de linha de comando.
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 do robôcranedo Harbor.GDCS_HARBOR_CRANE_ROBOT_TOKEN: o token de autenticação da conta de robôcranedo Harbor.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 de robô de extração de imagens do Kubernetes do Harbor.
Depois de reunir os valores de todas as variáveis necessárias, gere o arquivo de variáveis de ambiente. Depois de criado, você pode editar o arquivo manualmente a qualquer momento.
Crie os diretórios raiz da solução e a pasta de segredos:
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 da GDC.PROJECT: projeto do GDC.ZONE: zona da GDC.HARBOR_INSTANCE_NAME: nome da instância do GDC Harbor.
Crie o arquivo de configuração do ambiente do 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 do robô do GDC Harbor.HARBOR_K8S_ROBOT_NAME: nome da conta do robô do GDC Harbor.
Adicione seus tokens aos arquivos de secret:
set +o history echo "CRANE_ROBOT_TOKEN" > ${HOME}/gdcag-solutions/secrets/harbor_crane_robot_token echo "KUBERNETES_ROBOT_TOKEN" > ${HOME}/gdcag-solutions/secrets/harbor_k8s_robot_token set -o historySubstitua:
CRANE_ROBOT_TOKEN: token do robô guindaste.KUBERNETES_ROBOT_TOKEN: token de robô do Kubernetes.
Crie o arquivo de carregador do 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 de 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 esteja configurada para confiar nos certificados TLS do seu 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-classVerifique se cada nó executa a versão do Kubernetes exigida na seção Antes de começar deste guia:
kubectl get nodes -o custom-columns='NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion'
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 camadas de imagens grandes para evitar tempos limite de token de autenticação ao usar o ajudante de credenciais do Managed Harbor Service (MHS) (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 do Harbor OCI 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 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)Faça o seeding das imagens de contêiner necessárias para o Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_registry.sh
Defina a lista de gráficos 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)Inicialize os gráficos do Helm necessários no Artifact Registry:
${GDCS_IMPLEMENTATION_HOME}/seed_charts.shVerifique se os gráficos podem ser lidos novamente 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
Envoy Gateway
O Envoy Gateway é instalado primeiro e validado por conta própria com o início rápido upstream. A integração do Envoy Agent Router é abordada na próxima seção.
Namespace
Crie o namespace para o Envoy Gateway. Os proxies
Deploymentdo 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 inicialização:
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 os CRDs estão registrados:
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 segredo de extração de imagens;
crds.enabled=falseporque os CRDs foram instalados 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 vêm do Harbor:
kubectl get pods --namespace="${GDCS_ENVOY_GATEWAY_NAMESPACE}" \ --output=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
Proxy do Envoy e classe de gateway
Crie o manifesto para o modelo de plano de dados
EnvoyProxye oGatewayClass. OEnvoyProxydefine a imagem do proxy, o segredo de extração de imagem e as solicitações de recursos dosPods de 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 o
EnvoyProxye oGatewayClass: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 depois.
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 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 porta. O Envoy
Servicede 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 de 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 de agente do Envoy no gráfico de seed:
helm template aieg-crds "${GDCS_HARBOR_CHART_OCI_URI}/envoyproxy/ai-gateway-crds-helm" \ --version "${GDCS_ENVOY_AGENT_ROUTER_VERSION}" | kubectl apply --server-side --filename=-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 os CRDs estão registrados:
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. Um serviço Redis atual pode ser usado mudando o valor de
rateLimit.backend.redis.url na próxima seção.
Crie o manifesto para o 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 EOFAplique o manifesto do Redis
Deployment:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/redis.yaml" \ --namespace="${GDCS_REDIS_NAMESPACE}"Aguarde até que o Redis
Deploymentesteja 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 do agente 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 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 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 Envoy Gateway
O Envoy Gateway precisa ser reconfigurado para chamar o controlador do roteador do agente 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 Envoy Gateway 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 ao controlador do Envoy Gateway monitorar recursosInferencePool. O gráfico não concede essa permissão. UmClusterRoleBindingseparado sobrevive a 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 o
ClusterRole:kubectl apply \ --filename="${GDCS_IMPLEMENTATION_HOME}/envoy-gateway-inferencepool-rbac.yaml"Reinicie o controlador do Envoy Gateway para que ele receba a nova configuração e as permissões. 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
compatível com OpenAI simulado por trás de um AIGatewayRoute) no namespace do roteador de agente
do Envoy e o remove depois.
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 o sidecar do processador externo injetado pelo roteador do agente do 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 porta. 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 segundo dia para os planos de controle do gateway.
Fazer upgrade
- Insira 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 do CRD comkubectl apply --server-sidee execute os mesmos comandoshelm upgrade --installcom o novo--version. Confira a matriz de compatibilidade do roteador de agentes do Envoy para as versões do gateway do Envoy e da API Gateway compatíveis com a versão de destino. O roteador de agentes do Envoy 1.1.0 é criado para o gateway do Envoy 1.8.
Desinstalar
- Exclua primeiro os recursos
Gateway,AIGatewayRouteeInferencePooldos guias do usuário e 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 |
helm não tem credenciais para o Harbor (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. |
O Envoy Gateway ou o roteador do agente Envoy Pods permanecem em ImagePullBackOff |
A imagem não foi propagada ou o secret de pull da imagem está faltando no namespace | Verifique kubectl describe pod, compare o caminho da imagem com crane ls "${GDCS_HARBOR_PROJECT_URI}/envoyproxy/gateway" e verifique 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 ClusterRoleBinding envoy-gateway-inferencepool-reader e o CRD inferencepools.inference.networking.k8s.io. Confira 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 está 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 materiais
- Documentação do roteador de agentes do Envoy
- Notas da versão e matriz de compatibilidade do roteador do agente Envoy
- Documentação do Envoy Gateway (em inglês)
- API Kubernetes Gateway
- Extensão Gateway API Inference
- 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 do roteador de agente Envoy para roteamento baseado no corpo