Divisão de Tráfego no Apache APISIX Ingress Controller
Fei Han
March 27, 2021
O Traffic Split é uma funcionalidade que divide e direciona o tráfego para múltiplos serviços de backend. Soluções como API Gateway (por exemplo, Apache APISIX e Traefik), Service Mesh (por exemplo, Istio e Linkerd) são capazes de realizar a divisão de tráfego e implementar funcionalidades como Canary Release e Blue-Green Deployment.
O Traffic Split também é uma funcionalidade chave no Ingress Controller. Como a camada de entrada no cluster Kubernetes, é desejável reduzir o risco ao liberar uma nova versão da aplicação configurando algumas regras de divisão de tráfego no controlador de entrada, de modo que apenas uma quantidade controlada de tráfego seja direcionada para as instâncias recém-lançadas. Neste artigo, vamos introduzir o Traffic Split (também chamado de Canary Release) no Ingress Nginx e no Kong Ingress Controller, e, por fim, explicaremos o Traffic Split no Apache APISIX Ingress Controller.
(PS: Para descrições mais concisas, usamos o termo "canary app" para descrever o serviço de backend que é direcionado após as regras de canário serem atendidas, e o termo "stable app" para descrever o serviço de backend que é direcionado quando as regras de canário não são atendidas. Por exemplo, no diagrama a seguir, os aplicativos canário e estável são "foo-canary" e "foo", respectivamente.)
Ingress Nginx
O Ingress Nginx suporta o canary release, que é controlado por uma anotação "nginx.ingress.kubernetes.io/canary", e ele suporta várias anotações para personalizar essa funcionalidade.
- nginx.ingress.kubernetes.io/canary-by-header
O destino é decidido com base no valor do cabeçalho (indicado por nginx.ingress.kubernetes.io/canary-by-header). O aplicativo Canary será direcionado se o valor for "always", caso contrário, o aplicativo estável será direcionado (valor do cabeçalho é "never").
- nginx.ingress.kubernetes.io/canary-by-header-value
Esta anotação estende a funcionalidade de nginx.ingress.kubernetes.io/canary-by-header, agora o valor do cabeçalho não precisa mais ser "always" ou "never".
- nginx.ingress.kubernetes.io/canary-by-header-pattern
Semelhante a nginx.ingress.kubernetes.io/canary-by-header, mas o valor é uma expressão regular compatível com PCRE.
- nginx.ingress.kubernetes.io/canary-by-cookie
Usa o campo de dados no cabeçalho Cookie para decidir o serviço de backend.
- nginx.ingress.kubernetes.io/canary-weight
Atribui um valor de peso entre 0 e 100, o tráfego será entregue de acordo com esse peso. Um peso de 0 significa que todo o tráfego será direcionado para o aplicativo canário, e um peso de 100 direcionará todo o tráfego para o aplicativo estável.
O seguinte trecho YAML direciona as solicitações cujo caminho URI começa com "/get" e o User-Agent corresponde ao padrão ".Mozilla." para o aplicativo canário "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
O Kong Gateway possui um plugin de canary release e expõe esse plugin ao seu controlador de entrada por meio do recurso KongPlugin. Administradores/Usuários precisam criar um objeto KongPlugin e preencher a regra de canary release, injetando uma anotação "konghq.com/plugins" no Kubernetes Service alvo. Ou você pode criar um objeto KongClusterPlugin para que essa regra de canário seja efetiva em todo o cluster.
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
O caso acima marca o serviço "foo-canary" como "canary" e cria uma regra de canary release para direcionar 30% do tráfego para esse serviço.
Apache APISIX
O Apache APISIX divide o tráfego com regras personalizadas por meio de seu plugin traffic-split, e o Apache APISIX Ingress Controller implementa a funcionalidade de divisão de tráfego no ApisixRoute (como suporte de primeira classe, sem depender de anotações) por meio desse plugin e das habilidades flexíveis de correspondência de rotas no ApisixRoute.
Baseado em Peso
Ao configurar múltiplos Kubernetes Services, a regra de canário baseada em peso pode ser aplicada da seguinte forma:
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
O caso acima direciona ⅔ das solicitações cujo Host é "foo.org" e com prefixo de caminho URI "/get" para o serviço "foo-canary" e o restante para "foo".
O peso para o serviço canário pode ser pequeno para uma verificação em pequena escala, e o peso pode ser aumentado modificando o ApisixRoute até que todo o tráfego seja direcionado para o serviço canário, concluindo totalmente a liberação.
Baseado em Regras
O campo Exprs no ApisixRoute permite que os usuários configurem regras personalizadas de correspondência de rotas. Por outro lado, várias regras de rota podem ser agrupadas em um único objeto ApisixRoute, então há uma maneira perfeita de implementar a divisão de tráfego baseada em regras.
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
As solicitações cujo Host é "foo.org" e o prefixo do caminho URI é "/get" serão separadas em duas partes:
- O parâmetro id cujo valor é 3, 13, 23 ou 33 irá corresponder à regra2 e será encaminhado para foo-canary;
- Outros irão corresponder à regra1 e serão direcionados para foo.
Resumo
O Traffic Split (Canary release) no Ingress Nginx suporta esquemas baseados em peso e em regras de cabeçalho, mas depende de anotações, cuja semântica é fraca; A abordagem do Kong suporta apenas a configuração de canary release por peso, os cenários são um tanto limitados, e a configuração é complicada (você precisa configurar vários recursos); Em contraste, o traffic split no Apache APISIX Ingress Controller é flexível e fácil de configurar, funcionando bem tanto para esquemas de divisão de tráfego baseados em peso quanto em regras.