Alura > Cursos de DevOps > Cursos de Containers > Conteúdos de Containers > Primeiras aulas do curso Kubernetes: garantindo e protegendo a aplicação com o Istio

Kubernetes: garantindo e protegendo a aplicação com o Istio

O que é Istio - Apresentação

Boas-vindas a mais um curso aqui na Alura! Me chamo Leonardo Sartorello e serei seu instrutor neste curso de Kubernetes com Istio.

Audiodescrição: Leonardo é um homem branco com barba, cabelos castanhos e olhos azuis. Ao fundo, há uma parede com dois quadros pendurados, iluminada de um lado por uma luz azul e do outro por uma luz vermelha.

Vamos falar um pouco sobre o que será abordado neste curso.

Para quem é este curso?

Este curso é voltado para aqueles que já possuem conhecimentos em Kubernetes e Helm e desejam aprofundar-se em Istio, redes e service meshes ("malhas de serviço") dentro do ambiente Kubernetes.

O que vamos aprender?

Durante o curso, exploraremos o que é o Istio, sua integração com o Kubernetes e como podemos aumentar a confiabilidade de nossas aplicações. Também entenderemos como funciona a rede de serviços do Istio e abordaremos aspectos de segurança para proteger nossas aplicações contra acessos não autorizados.

Todo esse aprendizado será aplicado em um projeto prático, com foco em testar as mudanças que implementamos, garantindo que tudo funcione corretamente.

Aproveitem os recursos da plataforma, que incluem não apenas vídeos, mas também atividades e conteúdos extras, além do suporte do fórum e da comunidade no Discord. Há uma ampla variedade de material disponível!

Vamos lá?

O que é Istio - Deploy da aplicação

Começaremos trabalhando com a aplicação disponibilizada, cujo código é em JavaScript e roda no Node.js. Já temos todos os arquivos necessários para implementar a aplicação no Kubernetes.

Criaremos o cluster Kubernetes e realizaremos a implantação da aplicação nele.

Iniciando o cluster

No terminal integrado ao editor de código na parte inferior, executamos o comando para iniciar o cluster:

minikube start --memory=4G --cpus=6

Estamos alocando 4 GB de memória e 4 núcleos do computador para a aplicação. Após teclarmos "Enter", o Minikube começará a criar o cluster. Enquanto isso, analisaremos o código da aplicação.

Analisando o código da aplicação

À esquerda do editor de código, temos:

Na pasta code, encontramos o arquivo index.js, que contém o código da aplicação. Trata-se de uma aplicação pequena, com 71 linhas de código, incluindo comentários e espaçamentos. Entenderemos o que ela faz.

A aplicação está configurada para rodar na porta 3000 (const port = 3000) e faz requisições a uma API externa chamada WorldTimeAPI, que retorna informações sobre data e hora em formato JSON. Também temos o nome do serviço e uma chave JSON (json_key) que está sendo utilizada.

As bibliotecas necessárias já estão importadas, e o código contém um app.get() após o import request from 'node-fetch', que define que, sempre que uma requisição do tipo GET for feita para a raiz ("/"), um determinado processo será executado.

Esse processo mede o tempo de resposta da WorldTimeAPI e retorna o nome do serviço, o tempo gasto na requisição e os dados recebidos da API, permitindo que avaliemos o desempenho.

É possível substituir a WorldTimeAPI por outra aplicação, desde que a nova API também retorna dados em formato JSON.

A aplicação conta com outras funcionalidades que iremos explorar mais adiante, mas identificamos a necessidade de um mecanismo para lidar com possíveis erros. Por exemplo, se a API externa retornar um erro 500, nossa aplicação apenas repassa esse erro sem tentar uma nova requisição ou fornecer informações adicionais.

Implementando a aplicação

Para resolver essa questão, utilizamos o Istio, que nos ajuda a recriar requisições e a melhorar a segurança e a confiabilidade da aplicação. Vamos implantar a aplicação no Kubernetes e testá-la para garantir que o Istio funcione corretamente.

No terminal, executamos os comandos para fazer o deploy dos arquivos YAML na pasta k8s:

kubectl apply -f k8s/services.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/loadbalancer.yaml

ancer.yaml -f k8s/services.yaml

deployment.apps/frontend-prod created

deployment.apps/middleware-prod created

deployment.apps/middleware-canary created

deployment.apps/backend-prod created

service/frontend created

service/frontend configured

service/middleware created

service/backend created

Após o deploy, precisamos acessar a aplicação. Para isso, executamos um tunnel no Minikube:

Substitua o endereço IP pelo da sua máquina.

minikube tunnel --bind-address=(EndereçoIP)

Starting tunnel for for service frontend -lb

Após o tunnel estar pronto, podemos continuar.

Testando no Postman

Com o tunnel funcionando, abrimos o Postman e fazemos uma requisição GET para 192.168.3.3:3000 clicando no botão "Send" à direita.

1 frontend-prod 0.024segundos

2 middleware-prod 0.018segundos

3 backend-prod 0.005segundos

4 FetchError: request to https://worldtimeapi.org/api/timezone/America/ Sao_Paulo failed, reason: connect ECONNREFUSED 192.168.1.21:443

A aplicação deve conectar o front-end ao middleware e ao back-end. No entanto, pode ocorrer um erro devido a problemas recentes no Minikube.

Para corrigir, abrimos outro terminal e executamos:

minikube ssh

Agora estamos dentro da máquina virtual do Minikube. Observe que saímos do nosso login (no caso do instrutor leosa@kubernetes) para "docker@minikube:~$". Atualizamos a lista de pacotes:

sudo apt update

Não desejamos atualizar a máquina em si, mas sim instalar o pacote. Após a instalação dos pacotes, vamos instalar o editor de texto nano:

Pode-se utilizar o nano ou vim para editor o arquivo de texto

sudo apt install nano

Editamos o arquivo resolv.conf com o seguinte comando:

sudo nano /etc/resolv.conf

Com isso, entramos no arquivo intitulado "GNU nano 6.2":

GNU nano 6.2
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.

nameserver 192.168.1.21
search sartorello.freemyip.com
options ednsø trust-ad ndots:0

# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [host(127.0.0.53)]
# Overrides: []
# Option ndots from: internal

Alteramos o nameserver para 1.1.1.1 e comentamos o campo search com um #.

GNU nano 6.2
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.

nameserver 1.1.1.1
# search sartorello.freemyip.com
options ednsø trust-ad ndots:0

# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [host(127.0.0.53)]
# Overrides: []
# Option ndots from: internal

Salvamos com "Ctrl + O" e saímos do arquivo com "Ctrl + X". Saímos da máquina virtual usando o comando exit.

exit

Reiniciamos a aplicação para posteriormente atualizar os containers da aplicação, executamos:

kubectl delete -f k8s/deployment.yaml -f k8s/load_balancer.yaml -f k8s/services.yaml

deployment.apps "frontend-prod" deleted

deployment.apps "middleware-prod" deleted

deployment.apps "middleware-canary" deleted

deployment.apps "backend-prod" deleted

service "frontend-1b" deleted

service "frontend" deleted

service "middleware" deleted

service "backend" deleted

Executamos para remover todos esses arquivos e rodamos o apply:

kubectl apply -f k8s/deployment.yaml -f k8s/load_balancer.yaml -f k8s/services.yaml

deployment.apps/frontend-prod created

deployment.apps/middleware-prod created

deployment.apps/middleware-canary created

deployment.apps/backend-prod created

service/frontend-1b created

service/frontend created

service/middleware created

service/backend created

Verificando o tunnel e testando no Postman

Após renovar os containers e serviços, verificamos o tunnel no terminal:

Stopping tunnel for service frontend-lb

Starting tunnel for service frontend-lb

Observamos que ele parou e reiniciou. Agora, testamos novamente no Postman clicando em "Send" à direita.

frontend-prod - 0.431segundos

middleware-canary - 0.416segundos

backend-prod - 0.41segundos

{"utc_offset":"-03:00","timezone":"America/Sao_Paulo", "day_of_week":1, "day_of_year":232,"datetime":"2024-08-19T14:46:58.627922-03:00", "utc_datetime":"2024-08-19T17:46:58.627922+00:00", "unixtime":1724089618 "raw_offset":-10800, "week_number":34, "dst":false,"abbreviation":"-03","dst_offset":0,"dst_from":null, "dst_until": null, "client_ip":"189.54.50.195"}

A aplicação deve funcionar corretamente, com o front-end, middleware e back-end respondendo adequadamente, e o JSON com as informações requisitadas.

Próximo passo

Com a aplicação funcionando, vamos trabalhar com o Istio para garantir a consistência das respostas e proteger a aplicação.

Vamos lá?

O que é Istio - Instalando o istio

Começaremos a trabalhar com o Istio.

Essa ferramenta permite controlar diversos quesitos de rede relacionadas à aplicação, como estabelecer regras de firewall para bloquear conexões, implementar retries para aumentar a confiabilidade, coletar métricas para otimizar o desempenho e criar um mapa de requisições que ajuda a visualizar o fluxo das interações. Além disso, existem muitas outras funcionalidades disponíveis.

Instalando o Istio

Para instalar o Istio, abrimos o terminal e acessamos a documentação do Istio.

Acessamos a documentação e, na barra lateral, localizamos a seção "Sidecar Mode" e, em seguida, "Install". Em vez de clicar diretamente em "Install", expandimos o triângulo à esquerda e selecionamos "Install with Helm". Assim, utilizaremos o Helm para a instalação.

Atenção: A documentação do Istio é muito útil, mas os exemplos apresentados podem ser complexos e difíceis de entender. É fundamental ter uma visão crítica ao utilizá-los.

Primeiramente, é necessário atender aos pré-requisitos (seção "Prerequisites"), que incluem ter o cliente do Helm instalado e configurar o repositório correspondente:

Etapas e código retirados da documentação:

  1. Perform any necessary platform-specific setup.
  2. Check the Requirements for Pods and Services.
  3. Install the Helm client, version 3.6 or above.
  4. Configure the Helm repository:
helm repo add istio https://istio-release.storage.googleapis.com/charts
helm repo update

A documentação fornece o link do repositório, então copiamos o comando helm repo add istio https://istio-release.storage.googleapis.com/charts e o colamos no terminal, adicionando o Istio com sucesso.

helm repo add istio https://istio-release.storage.googleapis.com/charts

storage.googleapis.com/charts

"istio" already exists with the same configuration, skipping

Em seguida, atualizamos os repositórios com o comando helm repo update, que também é executado com sucesso.

Hang tight while we grab the latest from your chart repositories...

...Şuccessfully got an update from the "kiali" chart repository

...Successfully got an update from the "istio" chart repository

Update Complete. Happy Helming!*

Passamos para os passos de instalação na seção "Installation steps".

Criando os namespaces

Comando retirado da documentação:

helm install <release> <chart> --namespace <namespace> --create-namespace [--set <other_parameters>]

O primeiro comando não exige preocupação, pois ele apenas fornece o nome da release, o nome do chart, o namespace e outros detalhes.

Começamos criando o namespace com o comando kubectl create namespace istio-system, que é criado com sucesso.

kubectl create namespace istio-system

namespace/istio-system created

Repetimos o comando para criar o namespace istio-ingress, que também é necessário para os gateways de entrada do Istio.

kubectl create namespace istio-ingress

namespace/istio-ingress created

Com os namespaces criados, instalamos o istio-base usando o comando:

helm install istio-base istio/base -n istio-system --set defaultRevision=default

O processo pode variar em duração, mas, neste caso, foi concluído rapidamente e o istio-base foi instalado com sucesso.

Validando a instalação

Para validar a instalação, executamos helm ls -n istio-system e verificamos que o status está como deployed.

helm ls -n istio-system

NAME: istio-base

NAMESPACE: istio-system

REVISION: 1

UPDATED: 2024-08-19 17:58:51.374139953 +0000 UTC

STATUS: deployed

CHART: base-1.23.0

APP VERSION: 1.23.0

Isso confirma que o Istio foi instalado corretamente.

Instalando o istiod

Continuamos com a instalação do istiod, o serviço utilizado pelo Istio. Copiamos o seguinte comando da documentação e o executamos:

helm install istiod istio/istiod -n istio-system --wait

A tag --wait é para o Helm aguardar o deploy ser executado.

Esse processo pode levar um pouco mais de tempo, mas ao final, verificamos novamente com helm ls -n istio-system para confirmar o deploy do istiod.

helm ls -n istio-system

Observe que o status está indicando que o deploy foi realizado.

Por fim, instalamos o ingress gateway. Copiamos o comando da seção 9 da documentação de instalação, que, embora esteja marcado como opcional, é essencial para o funcionamento adequado do sistema. Executamos o comando:

helm install istio-ingress istio/gateway -n istio-ingress --wait

Após a instalação, confirmamos a presença do gateway istio-ingress com o comando helm ls -n istio-ingress.

helm ls -n istio-ingress

No retorno, observamos que o status está indicando que o deploy foi realizado.

Próximo passo

Com o Istio instalado, podemos começar a trabalhar com ele para melhorar nossa aplicação.

Sobre o curso Kubernetes: garantindo e protegendo a aplicação com o Istio

O curso Kubernetes: garantindo e protegendo a aplicação com o Istio possui 89 minutos de vídeos, em um total de 43 atividades. Gostou? Conheça nossos outros cursos de Containers em DevOps, ou leia nossos artigos de DevOps.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Containers acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas