Extensibilidad del plano de datos con EnvoyFilter
Puedes usar la API de EnvoyFilter para extender las capacidades del plano de datos en Cloud Service Mesh que, de otro modo, no se pueden lograr con otras APIs de Istio. Con la API de EnvoyFilter, puedes personalizar la configuración de Envoy generada a partir de otras políticas aplicadas a las cargas de trabajo, como agregar filtros a la cadena de filtros HTTP.
Consideraciones importantes
- Ten en cuenta que la superficie de la API está vinculada a detalles internos de la implementación, por lo que se debe tener especial cuidado al usar esta función, ya que las configuraciones incorrectas podrían desestabilizar la malla. Solo usa la API de
EnvoyFiltersi otras APIs de Istio no satisfacen tus necesidades. - La API de
EnvoyFilterse admite con restricciones específicas sobre qué campos y extensiones se pueden usar para fines de confiabilidad y asistencia. Para obtener una lista exhaustiva de las funciones compatibles con la API deEnvoyFilter, consulta Funciones compatibles con las APIs de Istio (plano de control administrado). - El alcance de la asistencia que ofrece Google se limita a propagar la configuración proporcionada por el usuario a las cargas de trabajo con sidecars de Envoy y no se extiende a la corrección de la configuración especificada con las APIs por extensión.
Campos de API admitidos
La API de EnvoyFilter se admite con la implementación del plano de control de TRAFFIC_DIRECTOR solo con compatibilidad limitada de la siguiente manera:
targetRefs: No compatibleconfigPatches[].applyTo: Solo se admiteHTTP_FILTER.configPatches[].patch.operation: Solo se admitenINSERT_FIRSTyINSERT_BEFOREcuando se usan con el filtro de ruta.configPatches[].patch.value.type_url: Consulta Extensiones admitidasconfigPatches[].patch.filterClass: No compatibleconfigPatches[].match.proxy: No compatibleconfigPatches[].match.routeConfiguration: No compatibleconfigPatches[].match.cluster: No compatible- Los siguientes campos solo se admiten para la operación
INSERT_BEFORE:configPatches[].match.listener: Solo se admitefilter.configPatches[].match.listener.filter.name: Solo se admiteenvoy.filters.network.http_connection_manager.configPatches[].match.listener.filter.subFilter.name: Solo se admiteenvoy.filters.http.router.
Extensiones compatibles
A continuación, se incluye la lista de extensiones admitidas junto con sus campos de API admitidos en los distintos canales de lanzamiento. Puedes encontrar la definición de la API y su semántica en la documentación oficial de Envoy.
type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
| Campo | Rápido | Normal | Estable |
|---|---|---|---|
stat_prefix |
|||
status |
|||
token_bucket |
|||
filter_enabled |
|||
filter_enforced |
|||
response_headers_to_add |
|||
request_headers_to_add_when_not_enforced |
|||
local_rate_limit_per_downstream_connection |
|||
enable_x_ratelimit_headers |
type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
| Campo | Rápido | Normal | Estable |
|---|---|---|---|
| (Sin campos) |
Ejemplo de uso
En este instructivo, aprenderás a usar la función integrada de límite de frecuencia local de Envoy para limitar de forma dinámica el tráfico a un servicio con la API de EnvoyFilter.
Costos
En este instructivo, se usan los siguientes componentes facturables de Google Cloud:
Cuando finalices este instructivo, podrás borrar los recursos creados para evitar que se te sigan cobrando. Para obtener más información, consulta Cómo realizar una limpieza.
Antes de comenzar
- Asegúrate de que la facturación esté habilitada para tu proyecto.
- Aprovisiona Cloud Service Mesh en un clúster de GKE.
Clona el repositorio:
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples cd anthos-service-mesh-samples
Implementa una puerta de enlace de entrada
Establece el contexto actual para
kubectlen el clúster:gcloud container clusters get-credentials CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATIONCrea un espacio de nombres para tu puerta de enlace de entrada:
kubectl create namespace asm-ingressHabilita el espacio de nombres para la inserción. Los pasos dependen de tu implementación del plano de control.
Aplica la etiqueta de inserción predeterminada al espacio de nombres:
kubectl label namespace asm-ingress \ istio.io/rev- istio-injection=enabled --overwriteImplementa la puerta de enlace de ejemplo en el repositorio
anthos-service-mesh-samples:kubectl apply -n asm-ingress \ -f docs/shared/asm-ingress-gatewayResultado esperado:
serviceaccount/asm-ingressgateway configured service/asm-ingressgateway configured deployment.apps/asm-ingressgateway configured gateway.networking.istio.io/asm-ingressgateway configured
Implementa la aplicación de muestra de Online Boutique.
Si no lo hiciste, establece el contexto actual para
kubectlen el clúster:gcloud container clusters get-credentials CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATIONCrea el espacio de nombres para la aplicación de ejemplo:
kubectl create namespace onlineboutiqueEtiqueta el espacio de nombres
onlineboutiquepara insertar de forma automática los proxies de Envoy:kubectl label namespace onlineboutique \ istio.io/rev- istio-injection=enabled --overwriteImplementa la app de ejemplo, el
VirtualServicepara el frontend y las cuentas de servicio para las cargas de trabajo. En este instructivo, implementarás Online Boutique, una app de demo de microservicios.kubectl apply \ -n onlineboutique \ -f docs/shared/online-boutique/virtual-service.yamlkubectl apply \ -n onlineboutique \ -f docs/shared/online-boutique/service-accounts
Cómo ver tus servicios
Visualiza los Pods en el espacio de nombres
onlineboutique:kubectl get pods -n onlineboutiqueResultado esperado:
NAME READY STATUS RESTARTS AGE adservice-85598d856b-m84m6 2/2 Running 0 2m7s cartservice-c77f6b866-m67vd 2/2 Running 0 2m8s checkoutservice-654c47f4b6-hqtqr 2/2 Running 0 2m10s currencyservice-59bc889674-jhk8z 2/2 Running 0 2m8s emailservice-5b9fff7cb8-8nqwz 2/2 Running 0 2m10s frontend-77b88cc7cb-mr4rp 2/2 Running 0 2m9s loadgenerator-6958f5bc8b-55q7w 2/2 Running 0 2m8s paymentservice-68dd9755bb-2jmb7 2/2 Running 0 2m9s productcatalogservice-84f95c95ff-c5kl6 2/2 Running 0 114s recommendationservice-64dc9dfbc8-xfs2t 2/2 Running 0 2m9s redis-cart-5b569cd47-cc2qd 2/2 Running 0 2m7s shippingservice-5488d5b6cb-lfhtt 2/2 Running 0 2m7sTodos los Pods de tu aplicación deben estar en funcionamiento, con un
2/2en la columnaREADY. Esto indica que los Pods tienen un proxy de sidecar de Envoy insertado de forma correcta. Si no aparece2/2después de un par de minutos, consulta la Guía de solución de problemas.Obtén la IP externa y configúrala en una variable:
kubectl get services -n asm-ingress export FRONTEND_IP=$(kubectl --namespace asm-ingress \ get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \ )Verás un resultado similar al siguiente:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE asm-ingressgateway LoadBalancer 10.19.247.233 35.239.7.64 80:31380/TCP,443:31390/TCP,31400:31400/TCP 27mVisita la dirección
EXTERNAL-IPen tu navegador web. Deberías ver la tienda Online Boutique en tu navegador.
Aplica la configuración del límite de frecuencia
En esta sección, se aplica un recurso EnvoyFilter para limitar todo el tráfico al servicio frontend a 5 solicitudes/min.
Aplica el CR al servicio
frontend:kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: frontend-local-ratelimit namespace: onlineboutique spec: workloadSelector: labels: app: frontend configPatches: - applyTo: HTTP_FILTER match: context: SIDECAR_INBOUND listener: filterChain: filter: name: "envoy.filters.network.http_connection_manager" subFilter: name: "envoy.filters.http.router" patch: operation: INSERT_BEFORE value: name: envoy.filters.http.local_ratelimit typed_config: "@type": type.googleapis.com/udpa.type.v1.TypedStruct type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit value: stat_prefix: http_local_rate_limiter token_bucket: max_tokens: 5 tokens_per_fill: 5 fill_interval: 60s filter_enabled: runtime_key: local_rate_limit_enabled default_value: numerator: 100 denominator: HUNDRED filter_enforced: runtime_key: local_rate_limit_enforced default_value: numerator: 100 denominator: HUNDRED EOFResultado esperado:
envoyfilter.networking.istio.io/frontend-local-ratelimit createdVerifica que el estado de CR no informe ningún error:
kubectl get envoyfilter -n onlineboutique frontend-local-ratelimit -o yamlResultado esperado:
... status: conditions: - lastTransitionTime: "2025-06-30T14:29:25.467017594Z" message: This resource has been accepted. This does not mean it has been propagated to all proxies yet reason: Accepted status: "True" type: AcceptedQuita la implementación de
loadgenerator, ya que llama al servicio varias veces, lo que consume tokens:kubectl delete -n onlineboutique deployment loadgeneratorResultado esperado:
deployment.apps/loadgenerator deletedCon
curl, verifica que no se permitan más de 5 solicitudes en 60 s. El código429indica que se aplica la límite de frecuencia.for i in {1..10}; do curl -s http://${FRONTEND_IP} -o /dev/null -w "%{http_code}\n"; sleep 1; doneResultado esperado:
200 200 200 200 200 429 429 429 429 429
Realiza una limpieza
Para evitar que se apliquen cargos continuos a tu Google Cloud cuenta por los recursos que se usaron en este instructivo, puedes borrar el proyecto o borrar los recursos individuales.
Borra el proyecto
En Cloud Shell, borra el proyecto:
gcloud projects delete PROJECT_ID
Borra recursos
Si deseas conservar el clúster y quitar la muestra de Online Retail, realiza la siguiente acción:
Borra los espacios de nombres de la aplicación:
kubectl delete namespace onlineboutiqueResultado esperado:
namespace "onlineboutique" deletedBorra el espacio de nombres de Ingress Gateway:
kubectl delete namespace asm-ingressResultado esperado:
namespace "asm-ingress" deleted
Si deseas evitar cargos adicionales, borra el clúster:
gcloud container clusters delete CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATION
Soluciona problemas
Consulta Cómo resolver problemas de extensibilidad del plano de datos.