Automatize as Decisões de Canary Release no Seu Cluster Kubernetes

Chao Zhang

Chao Zhang

December 30, 2022

Technology

Contexto

Atualmente, os microsserviços tornaram-se um padrão de arquitetura de software típico e amplamente utilizado. Os serviços são fracamente acoplados e colaboram por meio de APIs. O padrão de microsserviços torna cada aplicação independentemente implantável e mantível, de modo que as versões são mais frequentes. Como todos sabemos, o lançamento é arriscado; você nunca sabe se há bugs na nova versão. É por isso que as pessoas usam estratégias como o lançamento canário e a implantação azul-verde para liberar gradualmente sua versão mais recente e reduzir o risco.

O Lançamento Canário divide o tráfego em dois grupos do serviço de destino: o grupo estável e o grupo canário. O API Gateway, como o Apache APISIX, expõe de forma eficiente e segura a arquitetura de microsserviços para APIs. Ele é equipado com o recurso de lançamento canário. Normalmente, há duas maneiras de decidir como dividir o tráfego: a maneira baseada em peso e a maneira baseada em expressão de predicado.

Maneira Baseada em Peso

Maneira Baseada em Peso

Os usuários precisam especificar a proporção do tráfego que atingirá o grupo canário. Na imagem acima, 95% do tráfego será encaminhado para o serviço estável, enquanto os outros 5% serão encaminhados para o canário.

Maneira Baseada em Expressão de Predicado

Maneira Baseada em Predicados

A maneira de expressão de predicado de solicitação indica que apenas o tráfego que se encaixa nas características especificadas atingirá o grupo canário. Por exemplo, apenas solicitações HTTP com o cabeçalho de solicitação X-Debug e seu valor real atingirão o serviço canário.

Automatizando o Lançamento Canário

Quando você opera o gateway de API chamando a API ou o painel de controle, haverá um atraso no ajuste da proporção de tráfego (para a maneira baseada em peso) ou dos predicados (para a maneira baseada em expressão de predicado). Atualmente, cada vez mais usuários usam Kubernetes para orquestrar seus microsserviços. As pessoas podem iniciar o lançamento canário assim que a nova versão do serviço é criada? Neste artigo, mostrarei como usar o API7 Cloud para automatizar o lançamento canário em seu cluster Kubernetes.

O que é o API7 Cloud

O API7 Cloud é uma plataforma SaaS multi-local e em qualquer nuvem para implantar, controlar, visualizar e monitorar APIs em escala. Execute suas APIs em qualquer lugar, mas gerencie-as em um único lugar. O API7 Cloud usa o Apache APISIX como o API Gateway para expor suas APIs de forma eficiente e segura.

API7 Cloud

Para usar o API7 Cloud, você deve implantar o Apache APISIX em suas infraestruturas, como Docker e Kubernetes. Você pode usar o Cloud CLI para facilitar a implantação.

# Configure um token de acesso do console do API7 Cloud.
cloud-cli configure --token {SEU TOKEN}

# Implante o Apache APISIX (versão 2.15.1) no namespace apisix, com apenas uma réplica.
cloud-cli deploy kubernetes \
  --name meu-apisix \
  --namespace apisix \
  --replica-count 1 \
  --apisix-image apache/apisix:2.15.1-centos

O Lançamento Canário é um dos recursos integrados do API7 Cloud. Os usuários podem configurar as regras de lançamento canário por meio do console ou chamar a API aberta do API7 Cloud. Nosso objetivo é automatizar as decisões de lançamento canário, então usaremos a segunda maneira.

Cenário

Digamos que em nosso cluster Kubernetes, há uma aplicação simples de página de erro, que sempre retorna uma mensagem de erro. Estamos lançando a versão 2.0 e queremos usar a estratégia de lançamento canário para reduzir o risco de lançamento. Além disso, também queremos automatizar todo o processo. Portanto, criamos um controlador de lançamento canário, que monitora as alterações nos recursos de serviço do Kubernetes e, em seguida, cria/modifica os lançamentos canários no API7 Cloud por meio do SDK Go do API7 Cloud. Usamos apenas a maneira baseada em peso para dividir o tráfego. Todos os componentes, incluindo o API Gateway Apache APISIX, serão implantados no Kubernetes, de modo que o diagrama será assim:

Diagrama

O controlador de lançamento canário observa as alterações no serviço e reage de acordo com algumas anotações, especificamente:

  • Se o serviço contiver a anotação api7.cloud/published-service, o controlador de lançamento canário tentará criar uma Aplicação no API7 Cloud.
  • Se o serviço tiver a anotação api7.cloud/published-canary-service, o controlador de lançamento canário tentará configurar a regra de lançamento canário no API7 Cloud, e a anotação api7.cloud/published-service-canary-percentage determinará a porcentagem.

Observe que este controlador não é autossuficiente (ele não exclui a Aplicação se o serviço for excluído), mas é suficiente para mostrar o processo automatizado de lançamento canário.

Vamos lá!

Vamos começar implantando o Apache APISIX e o controlador de lançamento canário. Como mencionado acima, usamos o Cloud CLI para implantar o Apache APISIX. Também temos dois arquivos YAML (error-page/manifest-v1.yaml e controller/manifest.yaml) para implantar a aplicação de página de erro e o controlador de lançamento canário.

  1. Prepare um cluster Kubernetes disponível se quiser executar os comandos a seguir.
  2. O controlador de lançamento canário precisa de um token de acesso para chamar a API do API7 Cloud. Obtemos um token de acordo com este documento e armazenamos o token em um segredo do K8s.
kubectl create namespace canary-release-demo
# Implante a versão v1 da página de erro.
kubectl apply -f https://raw.githubusercontent.com/tokers/canary-release-automation-demo/main/error-page/manifest-v1.yaml -n canary-release-demo

# Crie um segredo do K8s para salvar o token de acesso do API7 Cloud.
kubectl create secret generic api7-cloud --namespace canary-release-demo --from-literal token={Seu Token de Acesso}

# Implante o controlador de lançamento canário.
kubectl apply -f https://raw.githubusercontent.com/tokers/canary-release-automation-demo/main/controller/manifest.yaml -n canary-release-demo

# Verifique se todas as cargas de trabalho estão normais.
kubectl get all -n canary-release-demo

Verifique o proxy

Vamos publicar este serviço anotando-o.

kubectl annotate service -n canary-release-demo error-page-v1 "api7.cloud/published-service=error-page"

O controlador de lançamento canário observará essa alteração e criará uma Aplicação no API7 Cloud. Agora vamos acessar o Apache APISIX para ver se o proxy está normal.

kubectl port-forward -n canary-release-demo service/apisix-gateway 10080:80
curl http://127.0.0.1:10080/api/error_page -H 'Host: error-page' -s

Se tudo estiver OK, você verá {"error": "injected by error_page service", "version": "v1"}.

Atualmente, o controlador de lançamento canário cria uma API "match-everything" na Aplicação, e o Host é o mesmo que o nome da Aplicação (error-page).

Lançando a V2

Queremos lançar a versão 2 para a aplicação de página de erro. Primeiro, implantamos a versão 2 aplicando o manifest-v2.yaml. Anotamos o serviço error-page-v2 com as anotações de lançamento canário.

kubectl apply -f https://raw.githubusercontent.com/tokers/canary-release-automation-demo/main/error-page/manifest-v2.yaml -n canary-release-demo

# Informe ao controlador de lançamento canário que habilitamos o lançamento canário para error-page-v2, e a porcentagem é 10%.
kubectl annotate service -n canary-release-demo error-page-v2 "api7.cloud/published-canary-service=true" "api7.cloud/published-service-canary-percentage=10"

# Inicie o canário.
kubectl annotate service -n canary-release-demo error-page-v2 "api7.cloud/published-service=error-page"

Agora vamos enviar 100 solicitações ao Apache APISIX novamente e ver se algumas solicitações foram encaminhadas para o serviço canário error-page-v2.

kubectl port-forward -n canary-release-demo service/apisix-gateway 10080:80
for ((i=0; i<100; i++)); do
  curl http://127.0.0.1:10080/api/error_page -H 'Host: error-page' -s
done

Apenas cerca de 10% das solicitações atingirão o error-page-v2 (não exatamente 10% devido à estratégia interna que o Apache APISIX usa para selecionar o backend) se tudo estiver bem.

Reversão

Descobrimos que a versão 2 é instável e queremos revertê-la. Antes de fazer isso, vamos parar o canário, então mudamos a porcentagem para 0. Em seguida, enviamos solicitações ao Apache APISIX novamente.

kubectl annotate service -n canary-release-demo error-page-v2 "api7.cloud/published-service-canary-percentage=0" --overwrite
for ((i=0; i<100; i++)); do
  curl http://127.0.0.1:10080/api/error_page -H 'Host: error-page' -s
done

Você verá que todas as solicitações agora vão para o error-page-v1.

Lançamento

Depois de um bom tempo, acreditamos que a versão 2 está estável o suficiente e queremos que todas as solicitações atinjam a versão 2. Então podemos desativar a aplicação de página de erro da versão 1. Portanto, mudamos a porcentagem para 100%.

kubectl annotate service -n canary-release-demo error-page-v2 "api7.cloud/published-service-canary-percentage=100" --overwrite
for ((i=0; i<100; i++)); do
  curl http://127.0.0.1:10080/api/error_page -H 'Host: error-page' -s
done

Agora todas as solicitações são encaminhadas para o error-page-v2. E o error-page-v1 pode ser desativado com segurança.

Resumo

O lançamento canário é uma arma eficaz para o lançamento. No entanto, ajustar a estratégia de lançamento canário pode ser lento. Este artigo mostra como operar os lançamentos canários de forma declarativa e automatizar o lançamento canário até certo ponto. Algumas pessoas podem buscar o lançamento canário totalmente automático com a ajuda de componentes GitOps. Por exemplo, usando o Argo Rollouts, pode-se promover ou reverter automaticamente os serviços. O Argo Rollouts consulta as métricas do serviço e integra-se com controladores de ingresso para alterar seus CRDs. Por fim, o API Gateway encaminhará as solicitações nas proporções corretas para a versão canária.

Referência

Código-fonte para a página de erro e o controlador de lançamento canário: https://github.com/tokers/canary-release-automation-demo.

Tags: