O Istio é a principal ferramenta de service mesh para o Kubernetes, ele disponibiliza diversas features para você gerenciar a sua malha de serviços, dentre essas features temos a parte de gerenciamento de tráfego onde uma das possibilidade é criar um ‘mirror’. Mas o que é um mirror? um mirror permite você ‘espelhar’ o tráfego de requisições de um serviço para outro. E porque isso é útil? podemos encaixar essa funcionalidade em algumas situações, dentre elas vou destacar uma:
Vamos supor que você tem uma aplicação que usa o banco de dados mysql e você precisa migra-la para postgresql, porém, antes de tornar a versão migrada produtiva você quer testar o comportamento dela para ver se os dados serão salvos corretamente e se a aplicação não apresentará erros. Para isso, você pode espelhar as requisições que chegam na aplicação cuja versão utiliza o mysql para a versão que utiliza o postgresql. O tráfego continuará sendo enviado para a versão com mysql e a versão com postgresql receberá uma cópia desse tráfego, o retorno da aplicação com postgresql não é enviado ao cliente, garantindo assim que o cliente receba apenas o retorno da aplicação com mysql que já funciona, evitanto assim receber possíveis erros da versão nova com postgresql.
Interessante, não? 🔥
Vamos ver como funciona na prática? Para isso vamos precisar das seguintes ferramentas instaladas na nossa máquina:
⚠️ Os comandos citados abaixo para criar os componentes começam com a instrução istioctl kube-inject -f, esta instrução injeta no pod a ser criado o container de proxy do istio, para que o istio possa controlar este pod. Caso você não queira usar esta instrução confira aqui como injetar o proxy do istio de outras maneiras.
Mãos a obra 🤝🎓
1 – Para começar, vamos subir nosso cluster minikube, primeiramente inicie o docker abrindo o docker desktop (para Windows), em seguida abra um terminal git bash e execute o seguinte comando para subir o minikube:
minikube start
2 – Instale o istio
istioctl install --set profile=demo -y
3 – Copie o código abaixo e execute no git bash para criar o deployment principal
cat <
4 - Agora faça o mesmo para o código abaixo para a versão 2 que receberá o tráfego espelhado
cat <
5 - Vamos criar o service do kubernetes
kubectl create -f - <
6 - Criaremos agora nosso virtualservice e destinationrule, estes são componentes do istio utilizados para gerenciamento de tráfego e neste momento possuem uma configuração básica, apenas enviar a requisição recebida para o pod v1
kubectl apply -f - <
7 - Com todos os componentes criados, vamos criar um deployment do httpbin para chamarmos a nossa aplicação e testa-la
cat <
8 - Com o httpbin criado podemos chamar o endpoint da aplicação que subimos no minikube e verificarmos o response dela pelo log do pod. Vamos então chamar a aplicação com o seguinte comando
export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://istioapp-service:8080/v1/istioapp/hello-word/ping
Verifique as logs dos dois pods
pod v1
export V1_POD=$(kubectl get pod -l app=istioapp,version=v1 -o jsonpath={.items..metadata.name})
kubectl logs "$V1_POD" -c istioapp
pod v2
export V2_POD=$(kubectl get pod -l app=istioapp,version=v2 -o jsonpath={.items..metadata.name})
kubectl logs "$V2_POD" -c istioapp
você deverá ver a mensagem 'PONG' na log do pod v1 e nada na log do pod v2.
9 - Vamos fazer agora o mirror funcionar, fazendo com que a chamada feita no passo 8 chegue tanto para o pod v1 quanto para o pod v2, para isso vamos configurar novamente nosso virtualservice e destinationrule, aplique as configurações abaixo
kubectl apply -f - <
10 - Chame novamente a aplicação
export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec "${SLEEP_POD}" -c sleep -- curl -sS http://istioapp-service:8080/v1/istioapp/hello-word/ping
Verifique a log dos pods novamente
pod v1
export V1_POD=$(kubectl get pod -l app=istioapp,version=v1 -o jsonpath={.items..metadata.name})
kubectl logs "$V1_POD" -c istioapp
pod v2
export V2_POD=$(kubectl get pod -l app=istioapp,version=v2 -o jsonpath={.items..metadata.name})
kubectl logs "$V2_POD" -c istioapp
O que aconteceu? 🤔
Como você pode notar, ambos os pods exibiram nas logs a mensagem PONG, o que significa que ambos receberam a requisição feita, porém, o pod v2 recebe apenas uma cópia do tráfego, o seu retorno seja sucesso ou falha não retorna ao cliente, o que nos dá segurança de testarmos qualquer alteração e em qualquer ambiente.
Como aconteceu? 😃
Toda a lógica do mirror fica entre os componentes virtualservice e destinationrule, analisando os arquivos acima note que o virtualservice através do atributo mirror consegue replicar o tráfego para um outro subset (v2), este subset é configurado no destinationrule e lá dizemos através de labels para qual pod a requisição deverá ser enviada. Também é possível dizer o percentual de tráfego que deverá ser espelhado com o atributo mirrorPercentage, se este for omitido, 100% do tráfego será espelhado.
Este artigo foi baseado na documentação oficial do istio. Recomendo navegar pela documentação e explorar mais e mais do istio 🚀
Espero que tenham gostado, até a próxima. 😉