División de Tráfico en Apache APISIX Ingress Controller
Fei Han
March 27, 2021
La división de tráfico es una función que divide y dirige el tráfico a múltiples servicios backend. Soluciones como API Gateway (por ejemplo, Apache APISIX y Traefik), Service Mesh (por ejemplo, Istio y Linkerd) son capaces de realizar la división de tráfico e implementar funcionalidades como Canary Release y Blue-Green Deployment.
La división de tráfico también es una característica clave en Ingress Controller. Como la capa de entrada en el clúster de Kubernetes, es deseable reducir el riesgo al lanzar una nueva versión de la aplicación configurando algunas reglas de división de tráfico en el controlador de entrada, de modo que solo una cantidad controlable de tráfico se dirija a las instancias recién lanzadas. En este artículo, presentaremos la división de tráfico (también llamada lanzamiento canario) en Ingress Nginx y Kong Ingress Controller, y finalmente explicaremos la división de tráfico en Apache APISIX Ingress Controller.
(PS: Para descripciones más concisas, usamos el término "aplicación canario" para describir el servicio backend que se enruta después de que se cumplan las reglas canario, y el término "aplicación estable" para describir el servicio backend que se enruta debido a que no se cumplen las reglas canario, por ejemplo, las aplicaciones canario y estable son "foo-canary" y "foo" respectivamente en el siguiente diagrama).
Ingress Nginx
Ingress Nginx soporta el lanzamiento canario, se controla mediante una anotación "nginx.ingress.kubernetes.io/canary", y soporta varias anotaciones para personalizar esta función.
- nginx.ingress.kubernetes.io/canary-by-header
El destino se decide por el valor del encabezado (indicado por nginx.ingress.kubernetes.io/canary-by-header), la aplicación Canario se enrutará si el valor es "always", de lo contrario, la aplicación estable se enrutará (el valor del encabezado es "never").
- nginx.ingress.kubernetes.io/canary-by-header-value
Esta anotación extiende nginx.ingress.kubernetes.io/canary-by-header, ahora el valor del encabezado ya no necesita ser "always" o "never".
- nginx.ingress.kubernetes.io/canary-by-header-pattern
Similar a nginx.ingress.kubernetes.io/canary-by-header, pero el valor es una expresión regular compatible con PCRE.
- nginx.ingress.kubernetes.io/canary-by-cookie
Usa el campo de datos en el encabezado Cookie para decidir el servicio backend.
- nginx.ingress.kubernetes.io/canary-weight
Asigna un valor de peso entre 0 y 100, el tráfico se entregará según este peso, un peso de 0 significa que todo el tráfico se enrutará a la aplicación canario y un peso de 100 enrutará todo el tráfico a la aplicación estable.
El siguiente fragmento de YAML redirige las solicitudes cuya ruta URI comienza con "/get" y el User-Agent coincide con el patrón ".Mozilla." a la aplicación canario "foo-canary".
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "User-Agent"
nginx.ingress.kubernetes.io/canary-by-header-pattern:
".*Mozilla.*"
name: ingress-v1beta1
Kong
El Kong Gateway tiene un plugin de lanzamiento canario y expone este plugin a su controlador de entrada mediante el recurso KongPlugin. Los administradores/usuarios necesitan crear un objeto KongPlugin y llenar la regla de lanzamiento canario, inyectando una anotación "konghq.com/plugins" al Servicio de Kubernetes objetivo. O puedes crear un objeto KongClusterPlugin para que esta regla canario sea efectiva en todo el clúster.
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: foo-canary
config:
percentage: 30
upstream_host: foo.com
upstream_fallback: false
upstream_port: 80
plugin: canary
---
apiVersion: v1
kind: Service
metadata:
name: foo-canary
labels:
app: foo
annotations:
konghq.com/plugins: foo-canary
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: foo
canary: true
El caso anterior marca el servicio "foo-canary" como "canario" y crea una regla de lanzamiento canario para redirigir el 30% del tráfico a este servicio.
Apache APISIX
Apache APISIX divide el tráfico con reglas personalizadas mediante su plugin traffic-split, y Apache APISIX Ingress Controller implementa la función de división de tráfico en ApisixRoute (como soporte de primera clase, sin depender de anotaciones) mediante este plugin y las capacidades flexibles de coincidencia de rutas en ApisixRoute.
Basado en Peso
Al configurar múltiples servicios de Kubernetes, la regla canario basada en peso se puede aplicar de la siguiente manera:
apiVersion: apisix.apache.org/v2alpha1
kind: ApisixRoute
metadata:
name: foo-route
spec:
http:
- name: rule1
match:
hosts:
- foo.org
paths:
- /get*
backends:
- serviceName: foo-canary
servicePort: 80
weight: 10
- serviceName: foo
servicePort: 80
weight: 5
El caso anterior dirige ⅔ de las solicitudes cuyo Host es "foo.org" y con prefijo de ruta URI "/get" al servicio "foo-canary" y las demás a foo.
El peso para el servicio canario puede ser pequeño para la verificación a pequeña escala, y aumentar el peso modificando ApisixRoute hasta que todo el tráfico se dirija al servicio canario, finalizando el lanzamiento por completo.
Basado en Reglas
El campo Exprs en ApisixRoute permite a los usuarios configurar reglas personalizadas de coincidencia de rutas, por otro lado, múltiples reglas de ruta pueden agruparse en un solo objeto ApisixRoute, por lo que hay una forma perfecta de implementar la división de tráfico basada en reglas.
apiVersion: apisix.apache.org/v2alpha1
kind: ApisixRoute
metadata:
name: foo-route
spec:
http:
- name: rule1
priority: 1
match:
hosts:
- foo.org
paths:
- /get*
backends:
- serviceName: foo
servicePort: 80
- name: rule2
priority: 2
match:
hosts:
- foo.org
paths:
- /get*
exprs:
- subject:
scope: Query
name: id
op: In
set:
- "3"
- "13"
- "23"
- "33"
backends:
- serviceName: foo-canary
servicePort: 80
Las solicitudes cuyo Host es "foo.org", el prefijo de ruta URI es "/get" se separarán en dos partes:
- El parámetro id cuyo valor es 3, 13, 23 o 33 coincidirá con rule2 y se redirigirá a foo-canary;
- Las demás coincidirán con rule1 y se enrutarán a foo.
Resumen
La división de tráfico (lanzamiento canario) en Ingress Nginx soporta esquemas basados en peso y en reglas de encabezado, pero depende de anotaciones, cuya semántica es débil; La forma de Kong solo soporta configurar el lanzamiento canario por peso, los escenarios son algo limitados, y la configuración es complicada (necesitas configurar varios recursos); En contraste, la división de tráfico en Apache APISIX Ingress Controller es flexible y fácil de configurar, funciona bien tanto para esquemas de división de tráfico basados en peso como en reglas.