O Gateway with Inference Extension oferece todos os recursos básicos da Gateway API e das extensões open source do Envoy Gateway. Este tópico aborda quatro tarefas comuns de gerenciamento de tráfego: roteamento por caminho HTTP, modificação de cabeçalhos de requisição, divisão proporcional de tráfego e terminação TLS.
Como funciona
O Gateway with Inference Extension baseia-se no projeto Envoy Gateway. Sua arquitetura possui duas camadas:
Plano de controle (componentes do Envoy Gateway): monitora as regras de roteamento de tráfego, cria e gerencia dinamicamente instâncias do Envoy Proxy. O plano de controle atualiza as regras de encaminhamento, mas não encaminha o tráfego diretamente.
Plano de dados (instâncias do Envoy Proxy): processa e encaminha o tráfego de forma eficiente e confiável.
Pré-requisitos
Antes de começar, certifique-se de ter:
Um cluster gerenciado ACK executando Kubernetes 1.30 ou posterior. Atualize seu cluster se necessário.
O Gateway with Inference Extension instalado no cluster.
Configure o ambiente
Conclua esta seção uma única vez antes de executar qualquer tarefa de gerenciamento de tráfego abaixo.
Etapa 1: Implante as aplicações de backend
Salve o YAML a seguir como backend.yaml e aplique-o ao seu cluster:
kubectl apply -f backend.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend
---
apiVersion: v1
kind: Service
metadata:
name: backend
labels:
app: backend
service: backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
serviceAccountName: backend
containers:
- image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/envoygateway-echo-basic:v20231214-v1.0.0-140-gf544a46e
imagePullPolicy: IfNotPresent
name: backend
ports:
- containerPort: 3000
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
Crie uma segunda aplicação de backend copiando backend.yaml, substituindo todas as ocorrências de backend por backend-2 e aplicando o manifesto atualizado.
Etapa 2: Verifique a GatewayClass
A instalação do Gateway with Inference Extension cria automaticamente uma GatewayClass padrão chamada ack-gateway. Verifique se ela existe:
kubectl get gatewayclass
A saída deve mostrar ACCEPTED: True, confirmando que o Envoy Gateway está gerenciando a GatewayClass:
NAME CONTROLLER ACCEPTED AGE
ack-gateway gateway.envoyproxy.io/gatewayclass-controller True 2m31s
Caso a GatewayClass não tenha sido criada automaticamente, crie-a manualmente:
-
Salve o YAML a seguir como
gatewayclass.yaml:apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: ack-gateway spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller -
Aplique o manifesto:
kubectl apply -f gatewayclass.yaml
Etapa 3: Crie o Gateway
Salve o YAML a seguir como gateway.yaml e aplique-o:
kubectl apply -f gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: ack-gateway
spec:
gatewayClassName: ack-gateway
listeners:
- name: http
protocol: HTTP
port: 80
O plano de controle provisiona automaticamente um Deployment do Envoy Proxy e um Service LoadBalancer com base na configuração do seu Gateway. O Service escuta nas portas definidas na especificação do Gateway. Para detalhes de faturamento sobre a instância do Server Load Balancer (SLB) provisionada, consulte SLB billing.
Para personalizar as especificações do Deployment do Envoy Proxy e os parâmetros do Service, consulte Customize EnvoyProxy. Para ativar o Horizontal Pod Autoscaler (HPA) para o gateway, consulte Referência da API EnvoyProxy.
Etapa 4: Obtenha o endereço IP do gateway
export GATEWAY_HOST=$(kubectl get gateway/ack-gateway -o jsonpath='{.status.addresses[0].value}')
Roteie tráfego HTTP por prefixo de caminho
Uma HTTPRoute corresponde a requisições recebidas e as encaminha para um Service de backend. O exemplo a seguir roteia todas as requisições com o prefixo de caminho /get para o Service backend.
-
Salve o YAML a seguir como
httproute.yamle aplique-o:kubectl apply -f httproute.yamlapiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 1 matches: - path: type: PathPrefix value: /get -
Envie uma requisição de teste:
curl -H "Host: www.example.com" http://$GATEWAY_HOST/getA aplicação de eco do backend retorna os detalhes da requisição. Uma resposta semelhante à seguinte confirma que a rota está funcionando:
{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": ["*/*"], "User-Agent": ["curl/8.9.1"], "X-Envoy-External-Address": ["115.XX.XXX.55"], "X-Forwarded-For": ["115.XX.XXX.55"], "X-Forwarded-Proto": ["http"], "X-Request-Id": ["953b2f8f-26d3-4ba9-93ba-a482b197b1ff"] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }
Adicione um cabeçalho de requisição
Use o filtro RequestHeaderModifier para injetar cabeçalhos nas requisições antes que elas cheguem ao backend. O exemplo a seguir adiciona added-header: foo a cada requisição correspondente ao prefixo /get.
-
Atualize
httproute.yamlcom o conteúdo a seguir e aplique-o:kubectl apply -f httproute.yamlapiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - matches: - path: type: PathPrefix value: /get backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 1 filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: "added-header" value: "foo" -
Envie uma requisição de teste:
curl -H "Host: www.example.com" http://$GATEWAY_HOST/getA resposta deve incluir
"Added-Header": ["foo"], confirmando que o cabeçalho foi injetado:{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": ["*/*"], "Added-Header": ["foo"], "User-Agent": ["curl/8.9.1"], "X-Envoy-External-Address": ["115.XX.XXX.55"], "X-Forwarded-For": ["115.XX.XXX.55"], "X-Forwarded-Proto": ["http"], "X-Request-Id": ["d37f19e5-25c1-45cf-90e5-51453e7ae3ed"] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }
Divida o tráfego proporcionalmente
Defina valores de weight em backendRefs para distribuir o tráfego entre vários Services. Cada Service recebe uma parcela proporcional ao seu peso dividido pela soma de todos os pesos — os pesos não precisam totalizar 100.
O exemplo a seguir envia 80% do tráfego para backend e 20% para backend-2 definindo pesos de 8 e 2.
-
Atualize
httproute.yamlcom o conteúdo a seguir e aplique-o:kubectl apply -f httproute.yamlapiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - matches: - path: type: PathPrefix value: /get backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 8 - group: "" kind: Service name: backend-2 port: 3000 weight: 2 -
Envie 20 requisições e verifique a distribuição:
for i in $(seq 1 20); do curl -sS -H "Host: www.example.com" http://$GATEWAY_HOST/get |grep backend; done | \ sed -E 's/".*"(backend(-2)?)-[0-9a-zA-Z]*-.*/\1/'A saída mostra qual backend tratou cada requisição. Aproximadamente 80% devem ir para
backende 20% parabackend-2:backend-2 backend backend backend backend backend backend backend backend backend backend backend-2 backend-2 backend backend backend-2 backend backend backend backend
Termine TLS
Adicione um listener TLS ao Gateway para aceitar tráfego HTTPS e terminar a conexão TLS no gateway.
-
Gere um certificado autoassinado e crie um Secret:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization" openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crt -
Adicione um listener TLS ao Gateway que referencie o Secret do certificado:
kubectl patch gateway ack-gateway --type=json --patch ' - op: add path: /spec/listeners/- value: name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - kind: Secret group: "" name: example-cert ' -
Verifique se a especificação do Gateway agora inclui ambos os listeners:
kubectl get gateway/ack-gateway -o yaml | grep spec: -A 20A saída deve mostrar tanto um listener HTTP na porta 80 quanto um listener HTTPS na porta 443:
spec: gatewayClassName: ack-gateway listeners: - allowedRoutes: namespaces: from: Same name: http port: 80 protocol: HTTP - allowedRoutes: namespaces: from: Same name: https port: 443 protocol: HTTPS tls: certificateRefs: - group: "" kind: Secret name: example-cert mode: Terminate status: -
Envie uma requisição de teste via HTTPS:
curl -H "Host: www.example.com" --resolve "www.example.com:443:${GATEWAY_HOST}" \ --cacert example.com.crt https://www.example.com/getUma resposta bem-sucedida confirma que a terminação TLS está funcionando. Note que
X-Forwarded-Protoéhttps:{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": ["*/*"], "User-Agent": ["curl/8.9.1"], "X-Envoy-External-Address": ["115.XX.XXX.55"], "X-Forwarded-For": ["115.XX.XXX.55"], "X-Forwarded-Proto": ["https"], "X-Request-Id": ["ac539756-3826-474b-be2f-5e57fdd49dac"] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }