Conteúdos

Microsserviços na Prática

Rodando um Laboratório de microsserviços e monitoramento local utilizando o Kind

Quando comecei a me aventurar nesse mundo dos contêineres e Microsserviços, acabei investindo um bom tempo para entender os conceitos e tentar replicar algumas coisas em meu dia a dia.

Como tenho um background de infraestrutura tradicional, virtualização e redes, as aplicações em Microsserviços em si foi um dos conceitos que precisei dar uma boa atenção e compreender melhor a ideia, arquitetura e funcionamento.

Recentemente um amigo que assim como eu também vem da área de infraestrutura, comentou que seria interessante ter um laboratório onde fosse mais simples visualizar isso funcionando, para facilitar na visualização do conceito, arquitetura e comunicação entre os componentes, além de entender como monitorar isso.

Daí surgiu a ideia de preparar esse laboratório, onde o objetivo é simplesmente tentar auxiliar alguém a compreender melhor algum assunto. Um trabalhador ajudando outro trabalhador a se desenvolver, assim estamos fortalecendo e valorizando nossa comunidade técnica.

A aplicação

Neste exemplo, iremos utilizar o “Sock-Shop”, uma aplicação que foi desenvolvida com o intuito de auxiliar na demonstração e teste de microsserviços e tecnologias cloud native. A Weaveworks construiu esta aplicação utilizando Spring Boot, Go kit e Node.js e empacotando isso em contêineres Docker. Todos os serviços se comunicam usando REST sobre HTTP.

A arquitetura desta aplicação de demonstração foi projetada intencionalmente para fornecer o maior número possível de microsserviços dentro de seu contexto.

/microservicos-na-pratica/architecture.png
Arquitetura da aplicação

Preparando o terreno

Nota:
Para esse Lab precisaremos já ter instaladas as seguintes ferramentas: Git, Docker, kubectl e o Kind. Ou seja, partiremos do princípio que você já contempla estes requisitos. 👍

Clonar o repositório

1
git clone https://github.com/tfinardi/microservices-demo.git

Criar o cluster com o Kind

Para facilitar o nosso trabalho, preparei um arquivo simples com a definição do cluster a ser utilizado neste laboratório. O ponto mais importante é o mapeamento das portas que serão utilizadas pelos serviços que iremos acessar via browser, fazendo já o trabalho de port-forwarding dos mesmos.

Abaixo, veremos a configuração do cluster a ser utilizado:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# cluster-config.yml
kind: Cluster
name: sock-shop
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  # Front-end Sock-Shop
  - containerPort: 30001
    hostPort: 80
    protocol: TCP
  # Prometheus UI
  - containerPort: 31090
    hostPort: 9090
    protocol: TCP
  # Grafana UI
  - containerPort: 31300
    hostPort: 3000
    protocol: TCP
  # Jaeger UI
  - containerPort: 16686
    hostPort: 8080
    protocol: TCP

Agora iremos efetivamente criar o cluster, para isto, basta executar o comando de criação passando o arquivo YAML.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cd microservices-demo
kind create cluster --config ./kind.yaml

Creating cluster "sock-shop" ...
 ✓ Ensuring node image (kindest/node:v1.21.1) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-sock-shop"
You can now use your cluster with:

kubectl cluster-info --context kind-sock-shop

Thanks for using kind! 😊

Agora confira se o cluster foi criado

1
2
kind get clusters
sock-shop

E veja o status do node

1
2
3
kubectl get nodes
NAME                      STATUS   ROLES                  AGE   VERSION
sock-shop-control-plane   Ready    control-plane,master   28m   v1.21.1

Deploy da aplicação

Todos os recursos da aplicação estão consolidados no manifesto complete-demo.yaml, sendo assim, iremos aplicar este manifesto e aguardar os pods ficarem disponíveis.

Aplicando o manifesto da aplicação

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
kubectl apply -f ./app/complete-demo.yaml
namespace/sock-shop created
deployment.apps/carts created
service/carts created
deployment.apps/carts-db created
service/carts-db created
deployment.apps/catalogue created
service/catalogue created
deployment.apps/catalogue-db created
service/catalogue-db created
deployment.apps/front-end created
service/front-end created
deployment.apps/orders created
service/orders created
deployment.apps/orders-db created
service/orders-db created
deployment.apps/payment created
service/payment created
deployment.apps/queue-master created
service/queue-master created
deployment.apps/rabbitmq created
service/rabbitmq created
deployment.apps/session-db created
service/session-db created
deployment.apps/shipping created
service/shipping created
deployment.apps/user created
service/user created
deployment.apps/user-db created
service/user-db created

Conferir o namespace que foi criado

1
2
3
4
5
6
7
8
kubectl get ns
NAME              STATUS   AGE
default              Active   40m
kube-node-lease      Active   40m
kube-public          Active   40m
kube-system          Active   40m
local-path-storage   Active   40m
sock-shop            Active   90s

Verificar o status dos PODs aplicados

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
kubectl get pods -n sock-shop
NAME                            READY   STATUS    RESTARTS   AGE
carts-b4d4ffb5c-w9tfh           1/1     Running   0          4m10s
carts-db-6c6c68b747-qxxsr       1/1     Running   0          4m10s
catalogue-759cc6b86-2fhjj       1/1     Running   0          4m10s
catalogue-db-96f6f6b4c-255pg    1/1     Running   0          4m10s
front-end-5c89db9f57-48dsh      1/1     Running   0          4m10s
orders-7664c64d75-78qb2         1/1     Running   0          4m10s
orders-db-659949975f-rhlnx      1/1     Running   0          4m10s
payment-7bcdbf45c9-87fp6        1/1     Running   0          4m10s
queue-master-5f6d6d4796-rqd2b   1/1     Running   0          4m9s
rabbitmq-5bcbb547d7-r49zk       2/2     Running   0          4m9s
session-db-7cf97f8d4f-kngjs     1/1     Running   0          4m9s
shipping-7f7999ffb7-5s49g       1/1     Running   0          4m9s
user-68df64db9c-rlw2v           1/1     Running   0          4m9s
user-db-6df7444fc-frr4k         1/1     Running   0          4m8s

Verificando os services da aplicação

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
kubectl get svc -n sock-shop
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
carts          ClusterIP   10.96.184.20    <none>        80/TCP              5m41s
carts-db       ClusterIP   10.96.133.62    <none>        27017/TCP           5m41s
catalogue      ClusterIP   10.96.27.30     <none>        80/TCP              5m41s
catalogue-db   ClusterIP   10.96.6.130     <none>        3306/TCP            5m41s
front-end      NodePort    10.96.116.18    <none>        80:30001/TCP        5m41s
orders         ClusterIP   10.96.148.103   <none>        80/TCP              5m41s
orders-db      ClusterIP   10.96.202.83    <none>        27017/TCP           5m41s
payment        ClusterIP   10.96.36.33     <none>        80/TCP              5m41s
queue-master   ClusterIP   10.96.109.74    <none>        80/TCP              5m41s
rabbitmq       ClusterIP   10.96.86.20     <none>        5672/TCP,9090/TCP   5m41s
session-db     ClusterIP   10.96.250.205   <none>        6379/TCP            5m41s
shipping       ClusterIP   10.96.150.123   <none>        80/TCP              5m41s
user           ClusterIP   10.96.146.211   <none>        80/TCP              5m41s
user-db        ClusterIP   10.96.36.157    <none>        27017/TCP           5m41s

Acessando a aplicação

Neste ponto, já temos a aplicação rodando, podendo ser acessada via http://localhost através do browser

/microservicos-na-pratica/front-end.gif
Front-end da aplicação

Monitoramento

A ideia aqui é apenas dar uma visão do que é possível fazer em relação a monitoração dessa aplicação que subimos.

Não vou entrar na explicação dos conceitos pois meu amigo Rafael Cirolini já fez isso em seu excelente Curso de Monitoração com o Prometheus. Recomendo fortemente investir um tempo para fazer este curso.

Dentro do diretório manifests-monitoring temos todos os manifestos que iremos utilizar para subir o node-exporter para expor as métricas do host, o kube-state-metrics para expor as métricas do cluster, do Prometheus para coletar estas métricas e do Grafana para visualizar essas métricas em dashboards.

Criando o namespace

Primeiramente iremos criar o namespace monitoring para agrupar todos os recursos atinentes ao monitoramento

1
2
3
cd manifests-monitoring
kubectl apply -f 00-monitoring-ns.yaml
namespace/monitoring created

caso queira validar os namespaces:

1
2
3
4
5
6
7
8
9
kubectl get ns
NAME                 STATUS   AGE
default              Active   65m
kube-node-lease      Active   65m
kube-public          Active   65m
kube-system          Active   65m
local-path-storage   Active   65m
monitoring           Active   12s
sock-shop            Active   26m

Prometheus, kube-state-metrics e node-exporter

Para aplicar a stack basta rodar o comando abaixo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
kubectl apply $(ls *-prometheus-*.yaml | awk ' { print " -f " $1 } ')
serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prometheus-configmap created
configmap/prometheus-alertrules created
deployment.apps/prometheus-deployment created
service/prometheus created
daemonset.apps/node-directory-size-metrics created
serviceaccount/node-exporter created
daemonset.apps/node-exporter created
service/node-exporter created

para verificar o status dos PODs:

1
2
3
4
5
kubectl get pods -n monitoring
NAME                                     READY   STATUS    RESTARTS   AGE
node-directory-size-metrics-2twv4        2/2     Running   0          47s
node-exporter-bn2x5                      1/1     Running   0          47s
prometheus-deployment-6bb9c45868-b6j87   1/1     Running   0          47s

Assim que os Pods estiverem disponíveis, teremos o Prometheus respondendo em http://localhost:9090.

Na figura abaixo, podemos ver um exemplo com o calculo de utilização de memória RAM no node utilizando as métricas: node_memory_MemAvailable_bytes e node_memory_MemTotal_bytes.

/microservicos-na-pratica/prometheus.png
Métricas no Prometheus

Deploy do Grafana

Para subir o Grafana, primeiramente iremos aplicar os manifestos do número 20, 21 e 22.

1
2
3
4
kubectl apply $(ls 2[0-2]-grafana-*.yaml | awk ' { print " -f " $1 } ')
configmap/grafana-import-dashboards created
deployment.apps/grafana-core created
service/grafana created

Vamos verificar se o POD do Grafana está rodando

1
2
3
kubectl get pods -n monitoring --selector=app=grafana
NAME                            READY   STATUS    RESTARTS   AGE
grafana-core-589d98b9f4-7kr9g   1/1     Running   0          6m36s

Importando as dashboards

Antes de acessar o Grafana, iremos importar o Datasource do Prometheus e as Dashboards para visualizarmos as métricas relativas ao Cluster, nodes e a aplicação.

1
2
kubectl apply -f 23-grafana-import-dash-batch.yaml
job.batch/grafana-import-dashboards created

Caso queira acompanhar o log da execução do job basta rodar o seguinte comando:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kubectl logs -n monitoring job.batch/grafana-import-dashboards
importing prometheus-datasource.json
{"datasource":{"id":1,"uid":"eHjbvlHnz","orgId":1,"name":"prometheus","type":"prometheus","typeLogoUrl":"","access":"proxy","url":"http://prometheus:9090","password":"","user":"","database":"","basicAuth":false,"basicAuthUser":"","basicAuthPassword":"","withCredentials":false,"isDefault":false,"jsonData":{},"secureJsonFields":{},"version":1,"readOnly":false},"id":1,"message":"Datasource added","name":"prometheus"}
importing k8s-pod-resources-dashboard.json
{"pluginId":"","title":"Kubernetes Pod Resources","imported":true,"importedUri":"db/kubernetes-pod-resources","importedUrl":"/d/FTCbv_Hnk/kubernetes-pod-resources","slug":"kubernetes-pod-resources","dashboardId":1,"folderId":0,"importedRevision":1,"revision":1,"description":"","path":"","removed":false}
importing prometheus-node-exporter-dashboard.json
{"pluginId":"","title":"Kubernetes Node Resources","imported":true,"importedUri":"db/kubernetes-node-resources","importedUrl":"/d/rYdddlPWk/kubernetes-node-resources","slug":"kubernetes-node-resources","dashboardId":2,"folderId":0,"importedRevision":1,"revision":1,"description":"","path":"","removed":false}
importing sock-shop-analytics-dashboard.json
{"pluginId":"","title":"Sock-Shop Analytics","imported":true,"importedUri":"db/sock-shop-analytics","importedUrl":"/d/mmqxv_Nnk/sock-shop-analytics","slug":"sock-shop-analytics","dashboardId":3,"folderId":0,"importedRevision":1,"revision":1,"description":"","path":"","removed":false}
importing sock-shop-performance-dashboard.json
{"pluginId":"","title":"Sock-Shop Performance","imported":true,"importedUri":"db/sock-shop-performance","importedUrl":"/d/HH3bvlH7k/sock-shop-performance","slug":"sock-shop-performance","dashboardId":4,"folderId":0,"importedRevision":1,"revision":1,"description":"","path":"","removed":false}
importing sock-shop-resources-dashboard.json
{"pluginId":"","title":"Sock-Shop Resources","imported":true,"importedUri":"db/sock-shop-resources","importedUrl":"/d/x13bD_Nnz/sock-shop-resources","slug":"sock-shop-resources","dashboardId":5,"folderId":0,"importedRevision":1,"revision":1,"description":"","path":"","removed":false}

O importante aqui é verificarmos se as Dashboards foram importadas com sucesso.

Acessando o Grafana

O Grafana ficará acessível através de http://localhost:3000, e as Dashboards importadas estarão disponíveis para visualização. O usuário e senha de acesso é admin

No exemplo abaixo, temos uma Dashboard com os recursos utilizados pelo node:

/microservicos-na-pratica/grafana1.png
Dashboard recursos node

Nesta outra, podemos ver algumas métricas relativas a performance dos microserviços que compõe a loja:

/microservicos-na-pratica/grafana2.png
Dashboard shop performance

Para visualizar mais métricas do Node, importe a Dashboard do Node Exporter Full através do código 1860 que você terá muito mais métricas para analisar

/microservicos-na-pratica/grafana3.png
Dashboard Node Exporter Full

Deploy do Jaeger / Tracing

Para fins didáticos, deixo aqui um exemplo com um deployment simples do Jaeger para visualizar o tracing das requisições entre os microserviços, para isso, basta aplicar todos os manifestos que estão no diretório jaeger-manifests.

1
kubectl apply -f manifests-jaeger/

como resultado teremos o Jaeger rodando em http://localhost:8080

/microservicos-na-pratica/Jaeger1.png
UI do Jaeger

E podemos verificar as os traces e a duração de cada request, como por exemplo:

/microservicos-na-pratica/jaeger2.png
Traces do Jaeger

Concluindo

Como disse logo no início, o intuito desse Lab é tentar auxiliar no processo de entendimento de conceitos, de forma prática. visando mostrar como funciona a arquitetura de uma aplicação em microsserviços, além de subir uma stack simples de monitoramento. A ideia é utilizar esse repositório para aplicar mais conceitos e melhorar os existentes.

Seria muito legal poder ter a colaboração dos amigos visando a melhoria contínua desse Lab, ajudando mais e mais pessoas a aprender e se desenvolver.

Referências