DEV Community

Cover image for O básico de mirror do Istio
Wander
Wander

Posted on

2

O básico de mirror do Istio

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
Enter fullscreen mode Exit fullscreen mode

2 - Instale o istio

istioctl install --set profile=demo -y
Enter fullscreen mode Exit fullscreen mode

3 - Copie o código abaixo e execute no git bash para criar o deployment principal

cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: istioapp-v1
  labels:
    app: istioapp
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: istioapp
      version: v1
  template:
    metadata:
      labels:
        app: istioapp
        version: v1
    spec:
      containers:
      - name: istioapp
        image: wandpsilva/istioapp:v1.0
        ports:
        - containerPort: 8080
EOF
Enter fullscreen mode Exit fullscreen mode

4 - Agora faça o mesmo para o código abaixo para a versão 2 que receberá o tráfego espelhado

cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: istioapp-v2
  labels:
    app: istioapp
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: istioapp
      version: v2
  template:
    metadata:
      labels:
        app: istioapp
        version: v2
    spec:
      containers:
      - name: istioapp
        image: wandpsilva/istioapp:v1.0
        ports:
        - containerPort: 8080
EOF
Enter fullscreen mode Exit fullscreen mode

5 - Vamos criar o service do kubernetes

kubectl create -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: istioapp-service
spec:
  selector:
    app: istioapp
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  type: NodePort
EOF
Enter fullscreen mode Exit fullscreen mode

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 - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: istioapp-virtualservice
spec:
  hosts:
    - istioapp-service.default.svc.cluster.local
  http:
    - route:
        - destination:
            host: istioapp-service.default.svc.cluster.local
            subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: istioapp-destinationrule
spec:
  host: istioapp-service.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      app: istioapp
      version: v1
EOF
Enter fullscreen mode Exit fullscreen mode

7 - Com todos os componentes criados, vamos criar um deployment do httpbin para chamarmos a nossa aplicação e testa-la

cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      containers:
      - name: sleep
        image: curlimages/curl
        command: ["/bin/sleep","3650d"]
        imagePullPolicy: IfNotPresent
EOF
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

pod v2

export V2_POD=$(kubectl get pod -l app=istioapp,version=v2 -o jsonpath={.items..metadata.name})
kubectl logs "$V2_POD" -c istioapp
Enter fullscreen mode Exit fullscreen mode

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 - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: istioapp-virtualservice
spec:
  hosts:
    - istioapp-service.default.svc.cluster.local
  http:
    - route:
        - destination:
            host: istioapp-service.default.svc.cluster.local
            subset: v1
          weight: 100
      mirror:
        host: istioapp-service.default.svc.cluster.local
        subset: v2
      mirrorPercentage:
        value: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: istioapp-destinationrule
spec:
  host: istioapp-service.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      app: istioapp
      version: v1
  - name: v2
    labels:
      app: istioapp
      version: v2
EOF
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

pod v2

export V2_POD=$(kubectl get pod -l app=istioapp,version=v2 -o jsonpath={.items..metadata.name})
kubectl logs "$V2_POD" -c istioapp
Enter fullscreen mode Exit fullscreen mode

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. 😉

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (1)

Collapse
 
filipefbf profile image
Filipe Ferreira

Muito bom a demo bem clara e objetiva.