Nota perev. : Malhas de serviço definitivamente se tornaram uma solução relevante na infraestrutura moderna para aplicativos que seguem a arquitetura de microsserviço. Embora o Istio possa ser ouvido por muitos engenheiros do DevOps, é um produto relativamente novo, que, sendo abrangente em termos dos recursos fornecidos, pode exigir um tempo considerável para se conhecer. O engenheiro alemão Rinor Maloku, responsável pela computação em nuvem para grandes clientes da empresa de telecomunicações Orange Networks, escreveu uma maravilhosa série de materiais que permitem que você mergulhe rápida e profundamente no Istio. Ele começa sua história com o que Istio pode fazer e como você pode vê-la rapidamente com seus próprios olhos.Istio é um projeto de código aberto desenvolvido em colaboração com equipes do Google, IBM e Lyft. Ele resolve as dificuldades que surgem em aplicativos baseados em microsserviços, por exemplo, como:
- Gerenciamento de tráfego : tempos limite, novas tentativas, balanceamento de carga;
- Segurança : autenticação e autorização do usuário final;
- Observabilidade : rastreamento, monitoramento, registro.
Todos eles podem ser resolvidos no nível do aplicativo, mas depois disso seus serviços deixarão de ser "micro". Todos os esforços adicionais para resolver esses problemas são um desperdício extra de recursos da empresa que podem ser usados diretamente para os valores de negócios. Considere um exemplo:
Gerente de projeto: quanto tempo adicionar feedback?
Desenvolvedor: Dois sprints.
MP: O quê? .. É apenas CRUD!
R: Criar CRUD é uma parte simples da tarefa, mas ainda precisamos autenticar e autorizar usuários e serviços. Como a rede não é confiável, você precisará implementar solicitações repetidas, bem como o padrão do disjuntor nos clientes. Ainda assim, para garantir que todo o sistema não caia, você precisará de tempos limites e anteparas (para obter mais detalhes sobre os dois padrões mencionados, veja mais no artigo - aprox. Transl.) E para detectar problemas, será necessário monitorar, rastrear, [...]
MP: Ah, então vamos apenas inserir esse recurso no serviço do produto.
Penso que a ideia é clara: o volume de etapas e esforços necessários para adicionar um serviço é enorme. Neste artigo, veremos como o Istio remove todas as dificuldades mencionadas acima (que não são direcionadas para a lógica de negócios) dos serviços.
Nota : Este artigo pressupõe que você tenha conhecimento prático do Kubernetes. Caso contrário, recomendo a leitura da
minha introdução ao Kubernetes e só depois continuarei a ler este material.
Idea Istio
Em um mundo sem o Istio, um serviço faz solicitações diretas a outro e, em caso de falha, o serviço deve processá-lo: faça uma nova tentativa, forneça um tempo limite, abra um disjuntor, etc.
Tráfego de rede em KubernetesO Istio também oferece uma solução especializada, completamente separada dos serviços e funcionando, interferindo na interação da rede. E assim implementa:
- Tolerância a falhas : com base no código de status na resposta, ele entende se a solicitação falhou e a executa novamente.
- Lançamentos das Canárias : redireciona para a nova versão do serviço apenas uma porcentagem fixa do número de solicitações.
- Monitoramento e métricas : por quanto tempo o serviço respondeu?
- Rastreamento e observabilidade : adiciona cabeçalhos especiais a cada solicitação e os rastreia no cluster.
- Segurança : extrai o token JWT, autentica e autoriza usuários.
Estas são apenas algumas das possibilidades (realmente apenas algumas!) Para intrigá-lo. Agora vamos mergulhar nos detalhes técnicos!
Arquitetura Istio
O Istio intercepta todo o tráfego de rede e aplica um conjunto de regras, inserindo um proxy inteligente em cada pod na forma de um contêiner lateral. Os proxies que ativam todos os recursos formam um
Data Plane e podem ser configurados dinamicamente usando o
Control Plane .
Plano de dados
Os proxies inseridos nos pods permitem que o Istio atenda facilmente aos requisitos de que precisamos. Por exemplo, verifique as funções de repetição e disjuntor.
Como tentativas e interrupção de circuito são implementadas no EnvoyPara resumir:
- Enviado (falando sobre um proxy em um contêiner lateral que é distribuído como um produto separado - aprox. Transl.) Envia uma solicitação para a primeira instância do serviço B e ocorre uma falha.
- O enviado Sidecar tenta novamente . (1)
- A solicitação com falha é retornada ao proxy que a chamou.
- Isso abre o disjuntor e chama o próximo serviço para solicitações subsequentes. 2)
Isso significa que você não precisa usar a próxima biblioteca Repetir, não precisa executar sua própria implementação de Descoberta de circuitos e descoberta de serviços na linguagem de programação X, Y ou Z. Tudo isso e muito mais está disponível imediatamente no Istio e não requer alterações no código.
Ótimo! Agora você pode querer fazer uma viagem com o Istio, mas ainda há algumas dúvidas, perguntas em aberto. Se essa é uma solução universal para todas as ocasiões da vida, você tem uma suspeita legítima: afinal, todas essas decisões na realidade acabam sendo inadequadas para qualquer ocasião.
E, finalmente, você pergunta: "É personalizável?"
Agora você está pronto para uma viagem marítima - e vamos nos familiarizar com o Plano de Controle.
Plano de controle
Ele consiste em três componentes:
Pilot ,
Mixer e
Citadel , que trabalham juntos para configurar Envoys para rotear tráfego, aplicar políticas e coletar dados de telemetria. Esquematicamente, tudo se parece com isso:
Interação do plano de controle com o plano de dadosOs enviados (ou seja, plano de dados) são configurados usando o
Kubernetes CRD (Definições de Recursos Personalizados) definido pelo Istio e projetado especificamente para essa finalidade. Para você, isso significa que eles parecem ser o próximo recurso no Kubernetes com sintaxe familiar. Após a criação, esse recurso será capturado pelo plano de controle e aplicado aos enviados.
Relação de serviço para Istio
Descrevemos a atitude do Istio em relação aos serviços, mas não o oposto: como os serviços se relacionam com o Istio?
Honestamente, o Istio conhece a presença de serviços e peixes - sobre a água, quando se perguntam: “O que é a água em geral?”.
Ilustração de Victoria Dimitrakopoulos : - Como você gosta da água? - O que é água em geral?Assim, você pode pegar o cluster de trabalho e, após a implantação dos componentes do Istio, os serviços localizados nele continuarão funcionando e, após a remoção desses componentes, tudo ficará bem novamente. É claro que, ao fazer isso, você perderá as oportunidades oferecidas pelo Istio.
Teoria suficiente - vamos colocar esse conhecimento em prática!
Istio na prática
O Istio requer um cluster Kubernetes no qual estão disponíveis pelo menos 4 vCPUs e 8 GB de RAM. Para aumentar rapidamente o cluster e seguir as instruções do artigo, recomendo usar o Google Cloud Platform, que oferece aos novos usuários
US $ 300 grátis .
Depois de criar um cluster e configurar o acesso ao Kubernetes através do utilitário do console, você pode instalar o Istio através do gerenciador de pacotes Helm.
Instalação do leme
Instale o cliente Helm no seu computador, como eles dizem na
documentação oficial . Nós o usaremos para gerar modelos para instalar o Istio na próxima seção.
Instale o Istio
Faça o download dos recursos do Istio da
versão mais recente (o link do autor original para a versão 1.0.5 é alterado para o atual, ou seja, 1.0.6 - aprox. Transl.) , Extraia o conteúdo para um diretório, que chamarei no futuro
[istio-resources]
.
Para facilitar a identificação dos recursos do Istio, crie o namespace
istio-system
no cluster K8s:
$ kubectl create namespace istio-system
Conclua a instalação indo para o
[istio-resources]
e executando o comando:
$ helm template install/kubernetes/helm/istio \ --set global.mtls.enabled=false \ --set tracing.enabled=true \ --set kiali.enabled=true \ --set grafana.enabled=true \ --namespace istio-system > istio.yaml
Este comando produzirá os principais componentes do Istio no arquivo
istio.yaml
. Alteramos o modelo padrão para nós mesmos, especificando os seguintes parâmetros:
global.mtls.enabled
definido como false
(ou seja, a autenticação mTLS está desativada - aprox. transl.) para simplificar nosso processo de namoro;tracing.enabled
ativa o rastreamento de consultas usando o Jaeger;kiali.enabled
instala o Kiali em um cluster para visualizar serviços e tráfego;grafana.enabled
define o Grafana para visualizar as métricas coletadas.
Aplicamos os recursos gerados com o comando:
$ kubectl apply -f istio.yaml
A instalação do Istio no cluster está concluída! Aguarde até que todos os pods no espaço de nomes
istio-system
estejam em
Running
ou
Completed
executando o comando abaixo:
$ kubectl get pods -n istio-system
Agora estamos prontos para continuar na próxima seção, onde criaremos e iniciaremos o aplicativo.
Arquitetura de aplicativos de análise de sentimentos
Vamos dar um exemplo do aplicativo de microsserviço Sentiment Analysis usado no
artigo de introdução já mencionado
no Kubernetes . É sofisticado o suficiente para mostrar as capacidades do Istio na prática.
O aplicativo consiste em quatro microsserviços:
- Serviço SA-Frontend , que atende a aplicativos front-end no Reactjs;
- Um serviço SA-WebApp que atende solicitações de análise de sentimentos;
- Serviço SA-Logic , que realiza análise sentimental ;
- Serviço SA-Feedback , que recebe feedback dos usuários sobre a precisão da análise.

Neste diagrama, além dos serviços, também vemos o Controlador de ingresso, que no Kubernetes roteia solicitações de entrada para os serviços correspondentes. O Istio usa um conceito semelhante no Ingress Gateway, cujos detalhes serão apresentados a seguir.
Iniciando um aplicativo com um proxy do Istio
Para as operações adicionais mencionadas no artigo, clone o repositório
istio-mastery . Ele contém o aplicativo e se manifesta para Kubernetes e Istio.
Inserção lateral
A inserção pode ser feita
automática ou
manualmente . Para inserir automaticamente contêineres laterais, é necessário definir o
istio-injection=enabled
para o
istio-injection=enabled
, o que é feito pelo seguinte comando:
$ kubectl label namespace default istio-injection=enabled namespace/default labeled
Agora, cada pod que será implantado no espaço para nome padrão receberá seu contêiner lateral. Para verificar isso, vamos instalar um aplicativo de teste acessando o diretório raiz do
[istio-mastery]
e executando o seguinte comando:
$ kubectl apply -f resource-manifests/kube persistentvolumeclaim/sqlite-pvc created deployment.extensions/sa-feedback created service/sa-feedback created deployment.extensions/sa-frontend created service/sa-frontend created deployment.extensions/sa-logic created service/sa-logic created deployment.extensions/sa-web-app created service/sa-web-app created
Após a expansão dos serviços, verificaremos se os pods têm dois contêineres (com o próprio serviço e seu side-car), executando o comando
kubectl get pods
e certificando-se de que o valor
2/2
indicado na coluna
READY
, simbolizando que os dois contêineres estão em execução:
$ kubectl get pods NAME READY STATUS RESTARTS AGE sa-feedback-55f5dc4d9c-c9wfv 2/2 Running 0 12m sa-frontend-558f8986-hhkj9 2/2 Running 0 12m sa-logic-568498cb4d-2sjwj 2/2 Running 0 12m sa-logic-568498cb4d-p4f8c 2/2 Running 0 12m sa-web-app-599cf47c7c-s7cvd 2/2 Running 0 12m
Visualmente, fica assim:
Enviar proxies em um dos podsAgora que o aplicativo está em funcionamento, precisamos permitir que o tráfego recebido entre no aplicativo.
Gateway de ingresso
A melhor prática para conseguir isso (para permitir tráfego no cluster) é por meio do
Gateway de ingresso no Istio, localizado na "borda" do cluster e permite ativar os recursos do Istio, como roteamento, balanceamento de carga, segurança e monitoramento do tráfego recebido.
O componente Ingress Gateway e o serviço que o encaminha para fora foram instalados no cluster durante a instalação do Istio. Para descobrir o endereço IP externo de um serviço, faça:
$ kubectl get svc -n istio-system -l istio=ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP istio-ingressgateway LoadBalancer 10.0.132.127 13.93.30.120
Continuaremos a acessar o aplicativo por esse IP (vou me referir a ele como IP EXTERNO); portanto, por conveniência, escreveremos o valor em uma variável:
$ EXTERNAL_IP=$(kubectl get svc -n istio-system \ -l app=istio-ingressgateway \ -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
Se você tentar acessar esse IP através de um navegador agora, receberá um erro de Serviço Indisponível, porque
Por padrão, o Istio bloqueia todo o tráfego recebido até que um Gateway seja definido.
Recurso de gateway
O Gateway é um CRD (Custom Resource Definition) no Kubernetes, definido após a instalação do Istio em um cluster e ativar a capacidade de especificar as portas, protocolos e hosts para os quais queremos permitir o tráfego de entrada.
No nosso caso, queremos permitir o tráfego HTTP na porta 80 para todos os hosts. A tarefa é implementada pela seguinte definição
( http-gateway.yaml ) :
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: http-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"
Essa configuração não precisa de explicação, exceto pelo
istio: ingressgateway
. Com esse seletor, podemos indicar a qual gateway de ingresso a configuração é aplicada. No nosso caso, este é o controlador do Ingress Gateway, que foi instalado por padrão no Istio.
A configuração é aplicada chamando o seguinte comando:
$ kubectl apply -f resource-manifests/istio/http-gateway.yaml gateway.networking.istio.io/http-gateway created
Agora, o gateway permite acesso à porta 80, mas não tem idéia de onde rotear solicitações. Isso exigirá
serviços virtuais .
Recurso VirtualService
O VirtualService informa ao Ingress Gateway como rotear solicitações permitidas no cluster.
Solicitações para nosso aplicativo enviadas via gateway http devem ser enviadas aos serviços sa-frontend, sa-web-app e sa-feedback:
Rotas para configurar com o VirtualServicesConsidere os pedidos que devem ser enviados ao SA-Frontend:
- Uma correspondência exata no caminho
/
deve ser enviada ao SA-Frontend para obter o index.html; - Os caminhos prefixados com
/static/*
devem ser enviados ao SA-Frontend para receber arquivos estáticos usados no frontend, como CSS e JavaScript; - Os caminhos que correspondem à expressão regular
'^.*\.(ico|png|jpg)$'
devem ser enviados ao SA-Frontend, como Estas são as imagens exibidas na página.
A implementação é alcançada pela seguinte configuração
( sa-virtualservice-external.yaml ): kind: VirtualService metadata: name: sa-external-services spec: hosts: - "*" gateways: - http-gateway # 1 http: - match: - uri: exact: / - uri: exact: /callback - uri: prefix: /static - uri: regex: '^.*\.(ico|png|jpg)$' route: - destination: host: sa-frontend # 2 port: number: 80
Pontos importantes:
- Este VirtualService refere-se a solicitações provenientes do gateway http ;
destination
define o serviço para o qual as solicitações são enviadas.
Nota : A configuração acima é armazenada no arquivo
sa-virtualservice-external.yaml
, que também contém as configurações de roteamento no SA-WebApp e no SA-Feedback, mas foi abreviado aqui no artigo por questões de brevidade.
Aplique o VirtualService chamando:
$ kubectl apply -f resource-manifests/istio/sa-virtualservice-external.yaml virtualservice.networking.istio.io/sa-external-services created
Nota : Quando usamos os recursos do Istio, o servidor da API do Kubernetes gera um evento que recebe o Istio Control Plane e, depois disso, a nova configuração é aplicada aos proxies Envoy de cada pod. E o controlador do Ingress Gateway parece ser o próximo enviado configurado no Control Plane. Tudo isso no diagrama é assim:
Configuração do Istio-IngressGateway para roteamento de consultaA Análise de sentimentos ficou disponível em
http://{EXTERNAL-IP}/
. Não se preocupe se você receber o status Não encontrado:
às vezes leva um pouco mais para a configuração entrar em vigor e os caches do Envoy serem atualizados .
Antes de prosseguir, trabalhe um pouco com o aplicativo para gerar tráfego
(sua presença é necessária para maior clareza nas próximas etapas - aprox. Transl.) .
Kiali: Observabilidade
Para acessar a interface administrativa do Kiali, execute o seguinte comando:
$ kubectl port-forward \ $(kubectl get pod -n istio-system -l app=kiali \ -o jsonpath='{.items[0].metadata.name}') \ -n istio-system 20001
... e abra
http: // localhost: 20001 / , efetuando login como admin / admin. Aqui você encontrará muitos recursos úteis, por exemplo, para verificar a configuração dos componentes do Istio, visualizar serviços com base nas informações coletadas ao interceptar solicitações de rede e receber respostas para as perguntas "Quem está entrando em contato com quem?", "Qual versão do serviço está travando?" etc. Em geral, explore as possibilidades do Kiali antes de visualizar métricas com o Grafana.

Grafana: visualização de métricas
As métricas coletadas no Istio entram no Prometheus e visualizadas com Grafana. Para acessar a interface de administração do Grafana, execute o comando abaixo e abra
http: // localhost: 3000 / :
$ kubectl -n istio-system port-forward \ $(kubectl -n istio-system get pod -l app=grafana \ -o jsonpath={.items[0].metadata.name}) 3000
Ao clicar no menu
inicial no canto superior esquerdo e selecionar o
Istio Service Dashboard no canto superior esquerdo, comece com o serviço
sa-web-app para examinar as métricas coletadas:

Aqui estamos aguardando um desempenho vazio e completamente chato - a gerência nunca aprovará isso. Vamos criar uma pequena carga com o seguinte comando:
$ while true; do \ curl -i http://$EXTERNAL_IP/sentiment \ -H "Content-type: application/json" \ -d '{"sentence": "I love yogobella"}'; \ sleep .8; done
Agora, temos gráficos muito mais agradáveis e, além deles, ferramentas maravilhosas do Prometheus para monitoramento e Grafana para visualização de métricas, o que nos permitirá aprender sobre o desempenho, status de saúde, melhorias / degradação dos serviços ao longo do tempo.
Por fim, vejamos o rastreamento de solicitações nos serviços.
Jaeger: trace
Precisamos rastrear, porque quanto mais serviços tivermos, mais difícil será chegar à causa da falha. Vejamos um caso simples da figura abaixo:
Um exemplo típico de uma solicitação com falha aleatóriaO pedido vem, cai -
qual é o motivo? Primeiro serviço? Ou o segundo? Há exceções em ambos - vamos examinar os logs de cada um. Quantas vezes você se encontra fazendo isso? Nosso trabalho é mais como detetives de software do que desenvolvedores ...
Esse é um problema generalizado nos microsserviços e é resolvido por sistemas de rastreamento distribuídos nos quais os serviços passam um ao outro por um cabeçalho exclusivo, após o qual essas informações são redirecionadas para o sistema de rastreamento, onde são mapeadas para os dados da solicitação. Aqui está uma ilustração:
TraceId é usado para identificar a solicitação.O Istio usa o Jaeger Tracer, que implementa uma estrutura de API do OpenTracing independente do fornecedor. Você pode acessar a interface do usuário do Jaeger com o seguinte comando:
$ kubectl port-forward -n istio-system \ $(kubectl get pod -n istio-system -l app=jaeger \ -o jsonpath='{.items[0].metadata.name}') 16686
Agora vá para
http: // localhost: 16686 / e selecione o serviço
sa-web-app . Se o serviço não for mostrado no menu suspenso, mostre / gere atividade na página e atualize a interface. Depois disso, clique no botão
Localizar rastreamentos, que mostrará os rastreamentos mais recentes - selecione qualquer - informações detalhadas sobre todos os rastreamentos serão exibidas:

Este rastreio mostra:
- A solicitação chega ao istio-ingressgateway (esta é a primeira interação com um dos serviços e o ID de rastreamento é gerado para a solicitação), após o qual o gateway envia a solicitação ao serviço de aplicativo da web sa .
- No serviço sa-web-app, a solicitação é atendida pelo envoy sidecar, um "filho" é criado no período (portanto, vemos nos rastreamentos) e redirecionado para o contêiner sa-web-app . ( Span é uma unidade lógica de trabalho em Jaeger que possui um nome, o horário em que a operação foi iniciada e sua duração. Os períodos podem ser aninhados e ordenados. Um gráfico acíclico direcionado dos períodos forma um traço. - aprox. Transl.)
- Aqui, a solicitação é processada pelo método sentimentAnalysis . Esses rastreamentos já são gerados pelo aplicativo, ou seja, eles exigiram alterações no código.
- A partir deste momento, uma solicitação POST para sa-logic é iniciada. O ID de rastreamento deve ser encaminhado a partir do sa-web-app .
- ...
Nota : Na etapa 4, o aplicativo deve ver os cabeçalhos gerados pelo Istio e passá-los para solicitações subsequentes, conforme mostrado na imagem abaixo:
(A) Istio é responsável por encaminhar os cabeçalhos; (B) Os serviços são responsáveis pelos cabeçalhos.Istio faz a maior parte do trabalho, como gera cabeçalhos para solicitações recebidas, cria novas extensões em cada cuidado lateral e as encaminha. No entanto, sem trabalhar com os cabeçalhos dentro dos serviços, o caminho completo de rastreamento da solicitação será perdido.
Os seguintes títulos devem ser considerados (encaminhados):
x-request-id x-b3-traceid x-b3-spanid x-b3-parentspanid x-b3-sampled x-b3-flags x-ot-span-context
Entretanto, para simplificar sua implementação, é uma tarefa simples, já existem
muitas bibliotecas - por exemplo, no serviço sa-web-app, o cliente RestTemplate encaminha esses cabeçalhos se você adicionar as bibliotecas Jaeger e OpenTracing, dependendo
dele .
Observe que o aplicativo Sentiment Analysis demonstra implementações no Flask, Spring e ASP.NET Core.Agora que ficou claro o que estamos obtendo da caixa (ou quase “pronto para uso”), consideraremos questões de roteamento bem ajustado, gerenciamento de tráfego de rede, segurança, etc.!
Nota perev. : Leia sobre isso na próxima edição do Istio de Rinor Maloku, que estará disponível em nosso blog em um futuro próximo. ATUALIZAÇÃO (14 de março): A segunda parte já foi publicada.PS do tradutor
Leia também em nosso blog: